Browse Source

added http foundation.

Taylor Otwell 12 years ago
parent
commit
73e355bf18
58 changed files with 9442 additions and 0 deletions
  1. 51 0
      vendor/Symfony/Component/HttpFoundation/ApacheRequest.php
  2. 203 0
      vendor/Symfony/Component/HttpFoundation/Cookie.php
  3. 30 0
      vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php
  4. 21 0
      vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php
  5. 30 0
      vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php
  6. 20 0
      vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php
  7. 21 0
      vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php
  8. 129 0
      vendor/Symfony/Component/HttpFoundation/File/File.php
  9. 100 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php
  10. 26 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php
  11. 89 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php
  12. 59 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php
  13. 743 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php
  14. 121 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php
  15. 32 0
      vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php
  16. 223 0
      vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php
  17. 158 0
      vendor/Symfony/Component/HttpFoundation/FileBag.php
  18. 306 0
      vendor/Symfony/Component/HttpFoundation/HeaderBag.php
  19. 49 0
      vendor/Symfony/Component/HttpFoundation/JsonResponse.php
  20. 19 0
      vendor/Symfony/Component/HttpFoundation/LICENSE
  21. 27 0
      vendor/Symfony/Component/HttpFoundation/LaravelRequest.php
  22. 281 0
      vendor/Symfony/Component/HttpFoundation/ParameterBag.php
  23. 47 0
      vendor/Symfony/Component/HttpFoundation/README.md
  24. 83 0
      vendor/Symfony/Component/HttpFoundation/RedirectResponse.php
  25. 1413 0
      vendor/Symfony/Component/HttpFoundation/Request.php
  26. 221 0
      vendor/Symfony/Component/HttpFoundation/RequestMatcher.php
  27. 33 0
      vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php
  28. 98 0
      vendor/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php
  29. 1112 0
      vendor/Symfony/Component/HttpFoundation/Response.php
  30. 293 0
      vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
  31. 48 0
      vendor/Symfony/Component/HttpFoundation/ServerBag.php
  32. 137 0
      vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php
  33. 72 0
      vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php
  34. 154 0
      vendor/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php
  35. 171 0
      vendor/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php
  36. 158 0
      vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php
  37. 85 0
      vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php
  38. 300 0
      vendor/Symfony/Component/HttpFoundation/Session/Session.php
  39. 48 0
      vendor/Symfony/Component/HttpFoundation/Session/SessionBagInterface.php
  40. 167 0
      vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php
  41. 139 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
  42. 130 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
  43. 41 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php
  44. 65 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php
  45. 64 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php
  46. 24 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php
  47. 58 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandler.php
  48. 72 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php
  49. 221 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
  50. 218 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php
  51. 126 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php
  52. 347 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
  53. 135 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php
  54. 41 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php
  55. 95 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php
  56. 126 0
      vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
  57. 129 0
      vendor/Symfony/Component/HttpFoundation/StreamedResponse.php
  58. 33 0
      vendor/Symfony/Component/HttpFoundation/composer.json

+ 51 - 0
vendor/Symfony/Component/HttpFoundation/ApacheRequest.php

@@ -0,0 +1,51 @@
+<?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;
+
+/**
+ * Request represents an HTTP request from an Apache server.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ApacheRequest extends Request
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function prepareRequestUri()
+    {
+        return $this->server->get('REQUEST_URI');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function prepareBaseUrl()
+    {
+        $baseUrl = $this->server->get('SCRIPT_NAME');
+
+        if (false === strpos($this->server->get('REQUEST_URI'), $baseUrl)) {
+            // assume mod_rewrite
+            return rtrim(dirname($baseUrl), '/\\');
+        }
+
+        return $baseUrl;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function preparePathInfo()
+    {
+        return $this->server->get('PATH_INFO') ?: substr($this->prepareRequestUri(), strlen($this->prepareBaseUrl())) ?: '/';
+    }
+}

+ 203 - 0
vendor/Symfony/Component/HttpFoundation/Cookie.php

@@ -0,0 +1,203 @@
+<?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;
+
+/**
+ * Represents a cookie
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * @api
+ */
+class Cookie
+{
+    protected $name;
+    protected $value;
+    protected $domain;
+    protected $expire;
+    protected $path;
+    protected $secure;
+    protected $httpOnly;
+
+    /**
+     * Constructor.
+     *
+     * @param string                    $name       The name of the cookie
+     * @param string                    $value      The value of the cookie
+     * @param integer|string|\DateTime  $expire     The time the cookie expires
+     * @param string                    $path       The path on the server in which the cookie will be available on
+     * @param string                    $domain     The domain that the cookie is available to
+     * @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
+     *
+     * @api
+     */
+    public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true)
+    {
+        // from PHP source code
+        if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
+            throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
+        }
+
+        if (empty($name)) {
+            throw new \InvalidArgumentException('The cookie name cannot be empty.');
+        }
+
+        // convert expiration time to a Unix timestamp
+        if ($expire instanceof \DateTime) {
+            $expire = $expire->format('U');
+        } elseif (!is_numeric($expire)) {
+            $expire = strtotime($expire);
+
+            if (false === $expire || -1 === $expire) {
+                throw new \InvalidArgumentException('The cookie expiration time is not valid.');
+            }
+        }
+
+        $this->name = $name;
+        $this->value = $value;
+        $this->domain = $domain;
+        $this->expire = $expire;
+        $this->path = empty($path) ? '/' : $path;
+        $this->secure = (Boolean) $secure;
+        $this->httpOnly = (Boolean) $httpOnly;
+    }
+
+    public function __toString()
+    {
+        $str = urlencode($this->getName()).'=';
+
+        if ('' === (string) $this->getValue()) {
+            $str .= 'deleted; expires='.gmdate("D, d-M-Y H:i:s T", time() - 31536001);
+        } else {
+            $str .= urlencode($this->getValue());
+
+            if ($this->getExpiresTime() !== 0) {
+                $str .= '; expires='.gmdate("D, d-M-Y H:i:s T", $this->getExpiresTime());
+            }
+        }
+
+        if ('/' !== $this->path) {
+            $str .= '; path='.$this->path;
+        }
+
+        if (null !== $this->getDomain()) {
+            $str .= '; domain='.$this->getDomain();
+        }
+
+        if (true === $this->isSecure()) {
+            $str .= '; secure';
+        }
+
+        if (true === $this->isHttpOnly()) {
+            $str .= '; httponly';
+        }
+
+        return $str;
+    }
+
+    /**
+     * Gets the name of the cookie.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Gets the value of the cookie.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Gets the domain that the cookie is available to.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getDomain()
+    {
+        return $this->domain;
+    }
+
+    /**
+     * Gets the time the cookie expires.
+     *
+     * @return integer
+     *
+     * @api
+     */
+    public function getExpiresTime()
+    {
+        return $this->expire;
+    }
+
+    /**
+     * Gets the path on the server in which the cookie will be available on.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isSecure()
+    {
+        return $this->secure;
+    }
+
+    /**
+     * Checks whether the cookie will be made accessible only through the HTTP protocol.
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isHttpOnly()
+    {
+        return $this->httpOnly;
+    }
+
+    /**
+     * Whether this cookie is about to be cleared
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isCleared()
+    {
+        return $this->expire < time();
+    }
+}

+ 30 - 0
vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php

@@ -0,0 +1,30 @@
+<?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\File\Exception;
+
+/**
+ * Thrown when the access on a file was denied.
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class AccessDeniedException extends FileException
+{
+    /**
+     * Constructor.
+     *
+     * @param string $path  The path to the accessed file
+     */
+    public function __construct($path)
+    {
+        parent::__construct(sprintf('The file %s could not be accessed', $path));
+    }
+}

+ 21 - 0
vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php

@@ -0,0 +1,21 @@
+<?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\File\Exception;
+
+/**
+ * Thrown when an error occurred in the component File
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class FileException extends \RuntimeException
+{
+}

+ 30 - 0
vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php

@@ -0,0 +1,30 @@
+<?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\File\Exception;
+
+/**
+ * Thrown when a file was not found
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class FileNotFoundException extends FileException
+{
+    /**
+     * Constructor.
+     *
+     * @param string $path  The path to the file that was not found
+     */
+    public function __construct($path)
+    {
+        parent::__construct(sprintf('The file "%s" does not exist', $path));
+    }
+}

+ 20 - 0
vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php

@@ -0,0 +1,20 @@
+<?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\File\Exception;
+
+class UnexpectedTypeException extends FileException
+{
+    public function __construct($value, $expectedType)
+    {
+        parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
+    }
+}

+ 21 - 0
vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php

@@ -0,0 +1,21 @@
+<?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\File\Exception;
+
+/**
+ * Thrown when an error occurred during file upload
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class UploadException extends FileException
+{
+}

+ 129 - 0
vendor/Symfony/Component/HttpFoundation/File/File.php

@@ -0,0 +1,129 @@
+<?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\File;
+
+use Symfony\Component\HttpFoundation\File\Exception\FileException;
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
+use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
+
+/**
+ * A file in the file system.
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ *
+ * @api
+ */
+class File extends \SplFileInfo
+{
+    /**
+     * Constructs a new file from the given path.
+     *
+     * @param string  $path      The path to the file
+     * @param Boolean $checkPath Whether to check the path or not
+     *
+     * @throws FileNotFoundException If the given path is not a file
+     *
+     * @api
+     */
+    public function __construct($path, $checkPath = true)
+    {
+        if ($checkPath && !is_file($path)) {
+            throw new FileNotFoundException($path);
+        }
+
+        parent::__construct($path);
+    }
+
+    /**
+     * Returns the extension based on the mime type.
+     *
+     * If the mime type is unknown, returns null.
+     *
+     * @return string|null The guessed extension or null if it cannot be guessed
+     *
+     * @api
+     */
+    public function guessExtension()
+    {
+        $type = $this->getMimeType();
+        $guesser = ExtensionGuesser::getInstance();
+
+        return $guesser->guess($type);
+    }
+
+    /**
+     * Returns the mime type of the file.
+     *
+     * The mime type is guessed using the functions finfo(), mime_content_type()
+     * and the system binary "file" (in this order), depending on which of those
+     * is available on the current operating system.
+     *
+     * @return string|null The guessed mime type (i.e. "application/pdf")
+     *
+     * @api
+     */
+    public function getMimeType()
+    {
+        $guesser = MimeTypeGuesser::getInstance();
+
+        return $guesser->guess($this->getPathname());
+    }
+
+    /**
+     * Returns the extension of the file.
+     *
+     * \SplFileInfo::getExtension() is not available before PHP 5.3.6
+     *
+     * @return string The extension
+     *
+     * @api
+     */
+    public function getExtension()
+    {
+        return pathinfo($this->getBasename(), PATHINFO_EXTENSION);
+    }
+
+    /**
+     * Moves the file to a new location.
+     *
+     * @param string $directory The destination folder
+     * @param string $name      The new file name
+     *
+     * @return File A File object representing the new file
+     *
+     * @throws FileException if the target file could not be created
+     *
+     * @api
+     */
+    public function move($directory, $name = null)
+    {
+        if (!is_dir($directory)) {
+            if (false === @mkdir($directory, 0777, true)) {
+                throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
+            }
+        } elseif (!is_writable($directory)) {
+            throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
+        }
+
+        $target = $directory.DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : basename($name));
+
+        if (!@rename($this->getPathname(), $target)) {
+            $error = error_get_last();
+            throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
+        }
+
+        chmod($target, 0666);
+
+        return new File($target);
+    }
+}

+ 100 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php

@@ -0,0 +1,100 @@
+<?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\File\MimeType;
+
+/**
+ * A singleton mime type to file extension guesser.
+ *
+ * A default guesser is provided.
+ * You can register custom guessers by calling the register()
+ * method on the singleton instance.
+ *
+ * <code>
+ * $guesser = ExtensionGuesser::getInstance();
+ * $guesser->register(new MyCustomExtensionGuesser());
+ * </code>
+ *
+ * The last registered guesser is preferred over previously registered ones.
+ *
+ */
+class ExtensionGuesser implements ExtensionGuesserInterface
+{
+    /**
+     * The singleton instance
+     * @var ExtensionGuesser
+     */
+    static private $instance = null;
+
+    /**
+     * All registered ExtensionGuesserInterface instances
+     * @var array
+     */
+    protected $guessers = array();
+
+    /**
+     * Returns the singleton instance
+     *
+     * @return ExtensionGuesser
+     */
+    static public function getInstance()
+    {
+        if (null === self::$instance) {
+            self::$instance = new self();
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Registers all natively provided extension guessers
+     */
+    private function __construct()
+    {
+        $this->register(new MimeTypeExtensionGuesser());
+    }
+
+    /**
+     * Registers a new extension guesser
+     *
+     * When guessing, this guesser is preferred over previously registered ones.
+     *
+     * @param ExtensionGuesserInterface $guesser
+     */
+    public function register(ExtensionGuesserInterface $guesser)
+    {
+        array_unshift($this->guessers, $guesser);
+    }
+
+    /**
+     * Tries to guess the extension
+     *
+     * The mime type is passed to each registered mime type guesser in reverse order
+     * of their registration (last registered is queried first). Once a guesser
+     * returns a value that is not NULL, this method terminates and returns the
+     * value.
+     *
+     * @param  string $mimeType   The mime type
+     * @return string             The guessed extension or NULL, if none could be guessed
+     */
+    public function guess($mimeType)
+    {
+        foreach ($this->guessers as $guesser) {
+            $extension = $guesser->guess($mimeType);
+
+            if (null !== $extension) {
+                break;
+            }
+        }
+
+        return $extension;
+    }
+}

+ 26 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php

@@ -0,0 +1,26 @@
+<?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\File\MimeType;
+
+/**
+ * Guesses the file extension corresponding to a given mime type
+ */
+interface ExtensionGuesserInterface
+{
+    /**
+     * Makes a best guess for a file extension, given a mime type
+     *
+     * @param  string $mimeType   The mime type
+     * @return string             The guessed extension or NULL, if none could be guessed
+     */
+    function guess($mimeType);
+}

+ 89 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php

@@ -0,0 +1,89 @@
+<?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\File\MimeType;
+
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
+
+/**
+ * Guesses the mime type with the binary "file" (only available on *nix)
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
+{
+    private $cmd;
+
+    /**
+     * Constructor.
+     *
+     * The $cmd pattern must contain a "%s" string that will be replaced
+     * with the file name to guess.
+     *
+     * The command output must start with the mime type of the file.
+     *
+     * @param string $cmd The command to run to get the mime type of a file
+     */
+    public function __construct($cmd = 'file -b --mime %s 2>/dev/null')
+    {
+        $this->cmd = $cmd;
+    }
+
+    /**
+     * Returns whether this guesser is supported on the current OS
+     *
+     * @return Boolean
+     */
+    static public function isSupported()
+    {
+        return !defined('PHP_WINDOWS_VERSION_BUILD');
+    }
+
+    /**
+     * Guesses the mime type of the file with the given path
+     *
+     * @see MimeTypeGuesserInterface::guess()
+     */
+    public function guess($path)
+    {
+        if (!is_file($path)) {
+            throw new FileNotFoundException($path);
+        }
+
+        if (!is_readable($path)) {
+            throw new AccessDeniedException($path);
+        }
+
+        if (!self::isSupported()) {
+            return null;
+        }
+
+        ob_start();
+
+        // need to use --mime instead of -i. see #6641
+        passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
+        if ($return > 0) {
+            ob_end_clean();
+
+            return null;
+        }
+
+        $type = trim(ob_get_clean());
+
+        if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-]+)#i', $type, $match)) {
+            // it's not a type, but an error message
+            return null;
+        }
+
+        return $match[1];
+    }
+}

+ 59 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php

@@ -0,0 +1,59 @@
+<?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\File\MimeType;
+
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
+
+/**
+ * Guesses the mime type using the PECL extension FileInfo
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
+{
+    /**
+     * Returns whether this guesser is supported on the current OS/PHP setup
+     *
+     * @return Boolean
+     */
+    static public function isSupported()
+    {
+        return function_exists('finfo_open');
+    }
+
+    /**
+     * Guesses the mime type of the file with the given path
+     *
+     * @see MimeTypeGuesserInterface::guess()
+     */
+    public function guess($path)
+    {
+        if (!is_file($path)) {
+            throw new FileNotFoundException($path);
+        }
+
+        if (!is_readable($path)) {
+            throw new AccessDeniedException($path);
+        }
+
+        if (!self::isSupported()) {
+            return null;
+        }
+
+        if (!$finfo = new \finfo(FILEINFO_MIME_TYPE)) {
+            return null;
+        }
+
+        return $finfo->file($path);
+    }
+}

+ 743 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php

@@ -0,0 +1,743 @@
+<?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\File\Mimetype;
+
+/**
+ * Provides a best-guess mapping of mime type to file extension.
+ */
+class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
+{
+    /**
+     * A map of mime types and their default extensions.
+     *
+     * This list has been placed under the public domain by the Apache HTTPD project.
+     *
+     * @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+     *
+     * @var array
+     */
+    protected $defaultExtensions = array(
+        'application/andrew-inset' => 'ez',
+        'application/applixware' => 'aw',
+        'application/atom+xml' => 'atom',
+        'application/atomcat+xml' => 'atomcat',
+        'application/atomsvc+xml' => 'atomsvc',
+        'application/ccxml+xml' => 'ccxml',
+        'application/cdmi-capability' => 'cdmia',
+        'application/cdmi-container' => 'cdmic',
+        'application/cdmi-domain' => 'cdmid',
+        'application/cdmi-object' => 'cdmio',
+        'application/cdmi-queue' => 'cdmiq',
+        'application/cu-seeme' => 'cu',
+        'application/davmount+xml' => 'davmount',
+        'application/dssc+der' => 'dssc',
+        'application/dssc+xml' => 'xdssc',
+        'application/ecmascript' => 'ecma',
+        'application/emma+xml' => 'emma',
+        'application/epub+zip' => 'epub',
+        'application/exi' => 'exi',
+        'application/font-tdpfr' => 'pfr',
+        'application/hyperstudio' => 'stk',
+        'application/inkml+xml' => 'ink',
+        'application/ipfix' => 'ipfix',
+        'application/java-archive' => 'jar',
+        'application/java-serialized-object' => 'ser',
+        'application/java-vm' => 'class',
+        'application/javascript' => 'js',
+        'application/json' => 'json',
+        'application/lost+xml' => 'lostxml',
+        'application/mac-binhex40' => 'hqx',
+        'application/mac-compactpro' => 'cpt',
+        'application/mads+xml' => 'mads',
+        'application/marc' => 'mrc',
+        'application/marcxml+xml' => 'mrcx',
+        'application/mathematica' => 'ma',
+        'application/mathml+xml' => 'mathml',
+        'application/mbox' => 'mbox',
+        'application/mediaservercontrol+xml' => 'mscml',
+        'application/metalink4+xml' => 'meta4',
+        'application/mets+xml' => 'mets',
+        'application/mods+xml' => 'mods',
+        'application/mp21' => 'm21',
+        'application/mp4' => 'mp4s',
+        'application/msword' => 'doc',
+        'application/mxf' => 'mxf',
+        'application/octet-stream' => 'bin',
+        'application/oda' => 'oda',
+        'application/oebps-package+xml' => 'opf',
+        'application/ogg' => 'ogx',
+        'application/onenote' => 'onetoc',
+        'application/oxps' => 'oxps',
+        'application/patch-ops-error+xml' => 'xer',
+        'application/pdf' => 'pdf',
+        'application/pgp-encrypted' => 'pgp',
+        'application/pgp-signature' => 'asc',
+        'application/pics-rules' => 'prf',
+        'application/pkcs10' => 'p10',
+        'application/pkcs7-mime' => 'p7m',
+        'application/pkcs7-signature' => 'p7s',
+        'application/pkcs8' => 'p8',
+        'application/pkix-attr-cert' => 'ac',
+        'application/pkix-cert' => 'cer',
+        'application/pkix-crl' => 'crl',
+        'application/pkix-pkipath' => 'pkipath',
+        'application/pkixcmp' => 'pki',
+        'application/pls+xml' => 'pls',
+        'application/postscript' => 'ai',
+        'application/prs.cww' => 'cww',
+        'application/pskc+xml' => 'pskcxml',
+        'application/rdf+xml' => 'rdf',
+        'application/reginfo+xml' => 'rif',
+        'application/relax-ng-compact-syntax' => 'rnc',
+        'application/resource-lists+xml' => 'rl',
+        'application/resource-lists-diff+xml' => 'rld',
+        'application/rls-services+xml' => 'rs',
+        'application/rpki-ghostbusters' => 'gbr',
+        'application/rpki-manifest' => 'mft',
+        'application/rpki-roa' => 'roa',
+        'application/rsd+xml' => 'rsd',
+        'application/rss+xml' => 'rss',
+        'application/rtf' => 'rtf',
+        'application/sbml+xml' => 'sbml',
+        'application/scvp-cv-request' => 'scq',
+        'application/scvp-cv-response' => 'scs',
+        'application/scvp-vp-request' => 'spq',
+        'application/scvp-vp-response' => 'spp',
+        'application/sdp' => 'sdp',
+        'application/set-payment-initiation' => 'setpay',
+        'application/set-registration-initiation' => 'setreg',
+        'application/shf+xml' => 'shf',
+        'application/smil+xml' => 'smi',
+        'application/sparql-query' => 'rq',
+        'application/sparql-results+xml' => 'srx',
+        'application/srgs' => 'gram',
+        'application/srgs+xml' => 'grxml',
+        'application/sru+xml' => 'sru',
+        'application/ssml+xml' => 'ssml',
+        'application/tei+xml' => 'tei',
+        'application/thraud+xml' => 'tfi',
+        'application/timestamped-data' => 'tsd',
+        'application/vnd.3gpp.pic-bw-large' => 'plb',
+        'application/vnd.3gpp.pic-bw-small' => 'psb',
+        'application/vnd.3gpp.pic-bw-var' => 'pvb',
+        'application/vnd.3gpp2.tcap' => 'tcap',
+        'application/vnd.3m.post-it-notes' => 'pwn',
+        'application/vnd.accpac.simply.aso' => 'aso',
+        'application/vnd.accpac.simply.imp' => 'imp',
+        'application/vnd.acucobol' => 'acu',
+        'application/vnd.acucorp' => 'atc',
+        'application/vnd.adobe.air-application-installer-package+zip' => 'air',
+        'application/vnd.adobe.fxp' => 'fxp',
+        'application/vnd.adobe.xdp+xml' => 'xdp',
+        'application/vnd.adobe.xfdf' => 'xfdf',
+        'application/vnd.ahead.space' => 'ahead',
+        'application/vnd.airzip.filesecure.azf' => 'azf',
+        'application/vnd.airzip.filesecure.azs' => 'azs',
+        'application/vnd.amazon.ebook' => 'azw',
+        'application/vnd.americandynamics.acc' => 'acc',
+        'application/vnd.amiga.ami' => 'ami',
+        'application/vnd.android.package-archive' => 'apk',
+        'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
+        'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
+        'application/vnd.antix.game-component' => 'atx',
+        'application/vnd.apple.installer+xml' => 'mpkg',
+        'application/vnd.apple.mpegurl' => 'm3u8',
+        'application/vnd.aristanetworks.swi' => 'swi',
+        'application/vnd.astraea-software.iota' => 'iota',
+        'application/vnd.audiograph' => 'aep',
+        'application/vnd.blueice.multipass' => 'mpm',
+        'application/vnd.bmi' => 'bmi',
+        'application/vnd.businessobjects' => 'rep',
+        'application/vnd.chemdraw+xml' => 'cdxml',
+        'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
+        'application/vnd.cinderella' => 'cdy',
+        'application/vnd.claymore' => 'cla',
+        'application/vnd.cloanto.rp9' => 'rp9',
+        'application/vnd.clonk.c4group' => 'c4g',
+        'application/vnd.cluetrust.cartomobile-config' => 'c11amc',
+        'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz',
+        'application/vnd.commonspace' => 'csp',
+        'application/vnd.contact.cmsg' => 'cdbcmsg',
+        'application/vnd.cosmocaller' => 'cmc',
+        'application/vnd.crick.clicker' => 'clkx',
+        'application/vnd.crick.clicker.keyboard' => 'clkk',
+        'application/vnd.crick.clicker.palette' => 'clkp',
+        'application/vnd.crick.clicker.template' => 'clkt',
+        'application/vnd.crick.clicker.wordbank' => 'clkw',
+        'application/vnd.criticaltools.wbs+xml' => 'wbs',
+        'application/vnd.ctc-posml' => 'pml',
+        'application/vnd.cups-ppd' => 'ppd',
+        'application/vnd.curl.car' => 'car',
+        'application/vnd.curl.pcurl' => 'pcurl',
+        'application/vnd.data-vision.rdz' => 'rdz',
+        'application/vnd.dece.data' => 'uvf',
+        'application/vnd.dece.ttml+xml' => 'uvt',
+        'application/vnd.dece.unspecified' => 'uvx',
+        'application/vnd.dece.zip' => 'uvz',
+        'application/vnd.denovo.fcselayout-link' => 'fe_launch',
+        'application/vnd.dna' => 'dna',
+        'application/vnd.dolby.mlp' => 'mlp',
+        'application/vnd.dpgraph' => 'dpg',
+        'application/vnd.dreamfactory' => 'dfac',
+        'application/vnd.dvb.ait' => 'ait',
+        'application/vnd.dvb.service' => 'svc',
+        'application/vnd.dynageo' => 'geo',
+        'application/vnd.ecowin.chart' => 'mag',
+        'application/vnd.enliven' => 'nml',
+        'application/vnd.epson.esf' => 'esf',
+        'application/vnd.epson.msf' => 'msf',
+        'application/vnd.epson.quickanime' => 'qam',
+        'application/vnd.epson.salt' => 'slt',
+        'application/vnd.epson.ssf' => 'ssf',
+        'application/vnd.eszigno3+xml' => 'es3',
+        'application/vnd.ezpix-album' => 'ez2',
+        'application/vnd.ezpix-package' => 'ez3',
+        'application/vnd.fdf' => 'fdf',
+        'application/vnd.fdsn.mseed' => 'mseed',
+        'application/vnd.fdsn.seed' => 'seed',
+        'application/vnd.flographit' => 'gph',
+        'application/vnd.fluxtime.clip' => 'ftc',
+        'application/vnd.framemaker' => 'fm',
+        'application/vnd.frogans.fnc' => 'fnc',
+        'application/vnd.frogans.ltf' => 'ltf',
+        'application/vnd.fsc.weblaunch' => 'fsc',
+        'application/vnd.fujitsu.oasys' => 'oas',
+        'application/vnd.fujitsu.oasys2' => 'oa2',
+        'application/vnd.fujitsu.oasys3' => 'oa3',
+        'application/vnd.fujitsu.oasysgp' => 'fg5',
+        'application/vnd.fujitsu.oasysprs' => 'bh2',
+        'application/vnd.fujixerox.ddd' => 'ddd',
+        'application/vnd.fujixerox.docuworks' => 'xdw',
+        'application/vnd.fujixerox.docuworks.binder' => 'xbd',
+        'application/vnd.fuzzysheet' => 'fzs',
+        'application/vnd.genomatix.tuxedo' => 'txd',
+        'application/vnd.geogebra.file' => 'ggb',
+        'application/vnd.geogebra.tool' => 'ggt',
+        'application/vnd.geometry-explorer' => 'gex',
+        'application/vnd.geonext' => 'gxt',
+        'application/vnd.geoplan' => 'g2w',
+        'application/vnd.geospace' => 'g3w',
+        'application/vnd.gmx' => 'gmx',
+        'application/vnd.google-earth.kml+xml' => 'kml',
+        'application/vnd.google-earth.kmz' => 'kmz',
+        'application/vnd.grafeq' => 'gqf',
+        'application/vnd.groove-account' => 'gac',
+        'application/vnd.groove-help' => 'ghf',
+        'application/vnd.groove-identity-message' => 'gim',
+        'application/vnd.groove-injector' => 'grv',
+        'application/vnd.groove-tool-message' => 'gtm',
+        'application/vnd.groove-tool-template' => 'tpl',
+        'application/vnd.groove-vcard' => 'vcg',
+        'application/vnd.hal+xml' => 'hal',
+        'application/vnd.handheld-entertainment+xml' => 'zmm',
+        'application/vnd.hbci' => 'hbci',
+        'application/vnd.hhe.lesson-player' => 'les',
+        'application/vnd.hp-hpgl' => 'hpgl',
+        'application/vnd.hp-hpid' => 'hpid',
+        'application/vnd.hp-hps' => 'hps',
+        'application/vnd.hp-jlyt' => 'jlt',
+        'application/vnd.hp-pcl' => 'pcl',
+        'application/vnd.hp-pclxl' => 'pclxl',
+        'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
+        'application/vnd.hzn-3d-crossword' => 'x3d',
+        'application/vnd.ibm.minipay' => 'mpy',
+        'application/vnd.ibm.modcap' => 'afp',
+        'application/vnd.ibm.rights-management' => 'irm',
+        'application/vnd.ibm.secure-container' => 'sc',
+        'application/vnd.iccprofile' => 'icc',
+        'application/vnd.igloader' => 'igl',
+        'application/vnd.immervision-ivp' => 'ivp',
+        'application/vnd.immervision-ivu' => 'ivu',
+        'application/vnd.insors.igm' => 'igm',
+        'application/vnd.intercon.formnet' => 'xpw',
+        'application/vnd.intergeo' => 'i2g',
+        'application/vnd.intu.qbo' => 'qbo',
+        'application/vnd.intu.qfx' => 'qfx',
+        'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
+        'application/vnd.irepository.package+xml' => 'irp',
+        'application/vnd.is-xpr' => 'xpr',
+        'application/vnd.isac.fcs' => 'fcs',
+        'application/vnd.jam' => 'jam',
+        'application/vnd.jcp.javame.midlet-rms' => 'rms',
+        'application/vnd.jisp' => 'jisp',
+        'application/vnd.joost.joda-archive' => 'joda',
+        'application/vnd.kahootz' => 'ktz',
+        'application/vnd.kde.karbon' => 'karbon',
+        'application/vnd.kde.kchart' => 'chrt',
+        'application/vnd.kde.kformula' => 'kfo',
+        'application/vnd.kde.kivio' => 'flw',
+        'application/vnd.kde.kontour' => 'kon',
+        'application/vnd.kde.kpresenter' => 'kpr',
+        'application/vnd.kde.kspread' => 'ksp',
+        'application/vnd.kde.kword' => 'kwd',
+        'application/vnd.kenameaapp' => 'htke',
+        'application/vnd.kidspiration' => 'kia',
+        'application/vnd.kinar' => 'kne',
+        'application/vnd.koan' => 'skp',
+        'application/vnd.kodak-descriptor' => 'sse',
+        'application/vnd.las.las+xml' => 'lasxml',
+        'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
+        'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
+        'application/vnd.lotus-1-2-3' => '123',
+        'application/vnd.lotus-approach' => 'apr',
+        'application/vnd.lotus-freelance' => 'pre',
+        'application/vnd.lotus-notes' => 'nsf',
+        'application/vnd.lotus-organizer' => 'org',
+        'application/vnd.lotus-screencam' => 'scm',
+        'application/vnd.lotus-wordpro' => 'lwp',
+        'application/vnd.macports.portpkg' => 'portpkg',
+        'application/vnd.mcd' => 'mcd',
+        'application/vnd.medcalcdata' => 'mc1',
+        'application/vnd.mediastation.cdkey' => 'cdkey',
+        'application/vnd.mfer' => 'mwf',
+        'application/vnd.mfmp' => 'mfm',
+        'application/vnd.micrografx.flo' => 'flo',
+        'application/vnd.micrografx.igx' => 'igx',
+        'application/vnd.mif' => 'mif',
+        'application/vnd.mobius.daf' => 'daf',
+        'application/vnd.mobius.dis' => 'dis',
+        'application/vnd.mobius.mbk' => 'mbk',
+        'application/vnd.mobius.mqy' => 'mqy',
+        'application/vnd.mobius.msl' => 'msl',
+        'application/vnd.mobius.plc' => 'plc',
+        'application/vnd.mobius.txf' => 'txf',
+        'application/vnd.mophun.application' => 'mpn',
+        'application/vnd.mophun.certificate' => 'mpc',
+        'application/vnd.mozilla.xul+xml' => 'xul',
+        'application/vnd.ms-artgalry' => 'cil',
+        'application/vnd.ms-cab-compressed' => 'cab',
+        'application/vnd.ms-excel' => 'xls',
+        'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
+        'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
+        'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
+        'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
+        'application/vnd.ms-fontobject' => 'eot',
+        'application/vnd.ms-htmlhelp' => 'chm',
+        'application/vnd.ms-ims' => 'ims',
+        'application/vnd.ms-lrm' => 'lrm',
+        'application/vnd.ms-officetheme' => 'thmx',
+        'application/vnd.ms-pki.seccat' => 'cat',
+        'application/vnd.ms-pki.stl' => 'stl',
+        'application/vnd.ms-powerpoint' => 'ppt',
+        'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
+        'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
+        'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
+        'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
+        'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
+        'application/vnd.ms-project' => 'mpp',
+        'application/vnd.ms-word.document.macroenabled.12' => 'docm',
+        'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
+        'application/vnd.ms-works' => 'wps',
+        'application/vnd.ms-wpl' => 'wpl',
+        'application/vnd.ms-xpsdocument' => 'xps',
+        'application/vnd.mseq' => 'mseq',
+        'application/vnd.musician' => 'mus',
+        'application/vnd.muvee.style' => 'msty',
+        'application/vnd.mynfc' => 'taglet',
+        'application/vnd.neurolanguage.nlu' => 'nlu',
+        'application/vnd.noblenet-directory' => 'nnd',
+        'application/vnd.noblenet-sealer' => 'nns',
+        'application/vnd.noblenet-web' => 'nnw',
+        'application/vnd.nokia.n-gage.data' => 'ngdat',
+        'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
+        'application/vnd.nokia.radio-preset' => 'rpst',
+        'application/vnd.nokia.radio-presets' => 'rpss',
+        'application/vnd.novadigm.edm' => 'edm',
+        'application/vnd.novadigm.edx' => 'edx',
+        'application/vnd.novadigm.ext' => 'ext',
+        'application/vnd.oasis.opendocument.chart' => 'odc',
+        'application/vnd.oasis.opendocument.chart-template' => 'otc',
+        'application/vnd.oasis.opendocument.database' => 'odb',
+        'application/vnd.oasis.opendocument.formula' => 'odf',
+        'application/vnd.oasis.opendocument.formula-template' => 'odft',
+        'application/vnd.oasis.opendocument.graphics' => 'odg',
+        'application/vnd.oasis.opendocument.graphics-template' => 'otg',
+        'application/vnd.oasis.opendocument.image' => 'odi',
+        'application/vnd.oasis.opendocument.image-template' => 'oti',
+        'application/vnd.oasis.opendocument.presentation' => 'odp',
+        'application/vnd.oasis.opendocument.presentation-template' => 'otp',
+        'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
+        'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
+        'application/vnd.oasis.opendocument.text' => 'odt',
+        'application/vnd.oasis.opendocument.text-master' => 'odm',
+        'application/vnd.oasis.opendocument.text-template' => 'ott',
+        'application/vnd.oasis.opendocument.text-web' => 'oth',
+        'application/vnd.olpc-sugar' => 'xo',
+        'application/vnd.oma.dd2+xml' => 'dd2',
+        'application/vnd.openofficeorg.extension' => 'oxt',
+        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
+        'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
+        'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
+        'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
+        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
+        'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
+        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
+        'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
+        'application/vnd.osgeo.mapguide.package' => 'mgp',
+        'application/vnd.osgi.dp' => 'dp',
+        'application/vnd.palm' => 'pdb',
+        'application/vnd.pawaafile' => 'paw',
+        'application/vnd.pg.format' => 'str',
+        'application/vnd.pg.osasli' => 'ei6',
+        'application/vnd.picsel' => 'efif',
+        'application/vnd.pmi.widget' => 'wg',
+        'application/vnd.pocketlearn' => 'plf',
+        'application/vnd.powerbuilder6' => 'pbd',
+        'application/vnd.previewsystems.box' => 'box',
+        'application/vnd.proteus.magazine' => 'mgz',
+        'application/vnd.publishare-delta-tree' => 'qps',
+        'application/vnd.pvi.ptid1' => 'ptid',
+        'application/vnd.quark.quarkxpress' => 'qxd',
+        'application/vnd.realvnc.bed' => 'bed',
+        'application/vnd.recordare.musicxml' => 'mxl',
+        'application/vnd.recordare.musicxml+xml' => 'musicxml',
+        'application/vnd.rig.cryptonote' => 'cryptonote',
+        'application/vnd.rim.cod' => 'cod',
+        'application/vnd.rn-realmedia' => 'rm',
+        'application/vnd.route66.link66+xml' => 'link66',
+        'application/vnd.sailingtracker.track' => 'st',
+        'application/vnd.seemail' => 'see',
+        'application/vnd.sema' => 'sema',
+        'application/vnd.semd' => 'semd',
+        'application/vnd.semf' => 'semf',
+        'application/vnd.shana.informed.formdata' => 'ifm',
+        'application/vnd.shana.informed.formtemplate' => 'itp',
+        'application/vnd.shana.informed.interchange' => 'iif',
+        'application/vnd.shana.informed.package' => 'ipk',
+        'application/vnd.simtech-mindmapper' => 'twd',
+        'application/vnd.smaf' => 'mmf',
+        'application/vnd.smart.teacher' => 'teacher',
+        'application/vnd.solent.sdkm+xml' => 'sdkm',
+        'application/vnd.spotfire.dxp' => 'dxp',
+        'application/vnd.spotfire.sfs' => 'sfs',
+        'application/vnd.stardivision.calc' => 'sdc',
+        'application/vnd.stardivision.draw' => 'sda',
+        'application/vnd.stardivision.impress' => 'sdd',
+        'application/vnd.stardivision.math' => 'smf',
+        'application/vnd.stardivision.writer' => 'sdw',
+        'application/vnd.stardivision.writer-global' => 'sgl',
+        'application/vnd.stepmania.package' => 'smzip',
+        'application/vnd.stepmania.stepchart' => 'sm',
+        'application/vnd.sun.xml.calc' => 'sxc',
+        'application/vnd.sun.xml.calc.template' => 'stc',
+        'application/vnd.sun.xml.draw' => 'sxd',
+        'application/vnd.sun.xml.draw.template' => 'std',
+        'application/vnd.sun.xml.impress' => 'sxi',
+        'application/vnd.sun.xml.impress.template' => 'sti',
+        'application/vnd.sun.xml.math' => 'sxm',
+        'application/vnd.sun.xml.writer' => 'sxw',
+        'application/vnd.sun.xml.writer.global' => 'sxg',
+        'application/vnd.sun.xml.writer.template' => 'stw',
+        'application/vnd.sus-calendar' => 'sus',
+        'application/vnd.svd' => 'svd',
+        'application/vnd.symbian.install' => 'sis',
+        'application/vnd.syncml+xml' => 'xsm',
+        'application/vnd.syncml.dm+wbxml' => 'bdm',
+        'application/vnd.syncml.dm+xml' => 'xdm',
+        'application/vnd.tao.intent-module-archive' => 'tao',
+        'application/vnd.tcpdump.pcap' => 'pcap',
+        'application/vnd.tmobile-livetv' => 'tmo',
+        'application/vnd.trid.tpt' => 'tpt',
+        'application/vnd.triscape.mxs' => 'mxs',
+        'application/vnd.trueapp' => 'tra',
+        'application/vnd.ufdl' => 'ufd',
+        'application/vnd.uiq.theme' => 'utz',
+        'application/vnd.umajin' => 'umj',
+        'application/vnd.unity' => 'unityweb',
+        'application/vnd.uoml+xml' => 'uoml',
+        'application/vnd.vcx' => 'vcx',
+        'application/vnd.visio' => 'vsd',
+        'application/vnd.visionary' => 'vis',
+        'application/vnd.vsf' => 'vsf',
+        'application/vnd.wap.wbxml' => 'wbxml',
+        'application/vnd.wap.wmlc' => 'wmlc',
+        'application/vnd.wap.wmlscriptc' => 'wmlsc',
+        'application/vnd.webturbo' => 'wtb',
+        'application/vnd.wolfram.player' => 'nbp',
+        'application/vnd.wordperfect' => 'wpd',
+        'application/vnd.wqd' => 'wqd',
+        'application/vnd.wt.stf' => 'stf',
+        'application/vnd.xara' => 'xar',
+        'application/vnd.xfdl' => 'xfdl',
+        'application/vnd.yamaha.hv-dic' => 'hvd',
+        'application/vnd.yamaha.hv-script' => 'hvs',
+        'application/vnd.yamaha.hv-voice' => 'hvp',
+        'application/vnd.yamaha.openscoreformat' => 'osf',
+        'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
+        'application/vnd.yamaha.smaf-audio' => 'saf',
+        'application/vnd.yamaha.smaf-phrase' => 'spf',
+        'application/vnd.yellowriver-custom-menu' => 'cmp',
+        'application/vnd.zul' => 'zir',
+        'application/vnd.zzazz.deck+xml' => 'zaz',
+        'application/voicexml+xml' => 'vxml',
+        'application/widget' => 'wgt',
+        'application/winhlp' => 'hlp',
+        'application/wsdl+xml' => 'wsdl',
+        'application/wspolicy+xml' => 'wspolicy',
+        'application/x-7z-compressed' => '7z',
+        'application/x-abiword' => 'abw',
+        'application/x-ace-compressed' => 'ace',
+        'application/x-authorware-bin' => 'aab',
+        'application/x-authorware-map' => 'aam',
+        'application/x-authorware-seg' => 'aas',
+        'application/x-bcpio' => 'bcpio',
+        'application/x-bittorrent' => 'torrent',
+        'application/x-bzip' => 'bz',
+        'application/x-bzip2' => 'bz2',
+        'application/x-cdlink' => 'vcd',
+        'application/x-chat' => 'chat',
+        'application/x-chess-pgn' => 'pgn',
+        'application/x-cpio' => 'cpio',
+        'application/x-csh' => 'csh',
+        'application/x-debian-package' => 'deb',
+        'application/x-director' => 'dir',
+        'application/x-doom' => 'wad',
+        'application/x-dtbncx+xml' => 'ncx',
+        'application/x-dtbook+xml' => 'dtb',
+        'application/x-dtbresource+xml' => 'res',
+        'application/x-dvi' => 'dvi',
+        'application/x-font-bdf' => 'bdf',
+        'application/x-font-ghostscript' => 'gsf',
+        'application/x-font-linux-psf' => 'psf',
+        'application/x-font-otf' => 'otf',
+        'application/x-font-pcf' => 'pcf',
+        'application/x-font-snf' => 'snf',
+        'application/x-font-ttf' => 'ttf',
+        'application/x-font-type1' => 'pfa',
+        'application/x-font-woff' => 'woff',
+        'application/x-futuresplash' => 'spl',
+        'application/x-gnumeric' => 'gnumeric',
+        'application/x-gtar' => 'gtar',
+        'application/x-hdf' => 'hdf',
+        'application/x-java-jnlp-file' => 'jnlp',
+        'application/x-latex' => 'latex',
+        'application/x-mobipocket-ebook' => 'prc',
+        'application/x-ms-application' => 'application',
+        'application/x-ms-wmd' => 'wmd',
+        'application/x-ms-wmz' => 'wmz',
+        'application/x-ms-xbap' => 'xbap',
+        'application/x-msaccess' => 'mdb',
+        'application/x-msbinder' => 'obd',
+        'application/x-mscardfile' => 'crd',
+        'application/x-msclip' => 'clp',
+        'application/x-msdownload' => 'exe',
+        'application/x-msmediaview' => 'mvb',
+        'application/x-msmetafile' => 'wmf',
+        'application/x-msmoney' => 'mny',
+        'application/x-mspublisher' => 'pub',
+        'application/x-msschedule' => 'scd',
+        'application/x-msterminal' => 'trm',
+        'application/x-mswrite' => 'wri',
+        'application/x-netcdf' => 'nc',
+        'application/x-pkcs12' => 'p12',
+        'application/x-pkcs7-certificates' => 'p7b',
+        'application/x-pkcs7-certreqresp' => 'p7r',
+        'application/x-rar-compressed' => 'rar',
+        'application/x-sh' => 'sh',
+        'application/x-shar' => 'shar',
+        'application/x-shockwave-flash' => 'swf',
+        'application/x-silverlight-app' => 'xap',
+        'application/x-stuffit' => 'sit',
+        'application/x-stuffitx' => 'sitx',
+        'application/x-sv4cpio' => 'sv4cpio',
+        'application/x-sv4crc' => 'sv4crc',
+        'application/x-tar' => 'tar',
+        'application/x-tcl' => 'tcl',
+        'application/x-tex' => 'tex',
+        'application/x-tex-tfm' => 'tfm',
+        'application/x-texinfo' => 'texinfo',
+        'application/x-ustar' => 'ustar',
+        'application/x-wais-source' => 'src',
+        'application/x-x509-ca-cert' => 'der',
+        'application/x-xfig' => 'fig',
+        'application/x-xpinstall' => 'xpi',
+        'application/xcap-diff+xml' => 'xdf',
+        'application/xenc+xml' => 'xenc',
+        'application/xhtml+xml' => 'xhtml',
+        'application/xml' => 'xml',
+        'application/xml-dtd' => 'dtd',
+        'application/xop+xml' => 'xop',
+        'application/xslt+xml' => 'xslt',
+        'application/xspf+xml' => 'xspf',
+        'application/xv+xml' => 'mxml',
+        'application/yang' => 'yang',
+        'application/yin+xml' => 'yin',
+        'application/zip' => 'zip',
+        'audio/adpcm' => 'adp',
+        'audio/basic' => 'au',
+        'audio/midi' => 'mid',
+        'audio/mp4' => 'mp4a',
+        'audio/mpeg' => 'mpga',
+        'audio/ogg' => 'oga',
+        'audio/vnd.dece.audio' => 'uva',
+        'audio/vnd.digital-winds' => 'eol',
+        'audio/vnd.dra' => 'dra',
+        'audio/vnd.dts' => 'dts',
+        'audio/vnd.dts.hd' => 'dtshd',
+        'audio/vnd.lucent.voice' => 'lvp',
+        'audio/vnd.ms-playready.media.pya' => 'pya',
+        'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
+        'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
+        'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
+        'audio/vnd.rip' => 'rip',
+        'audio/webm' => 'weba',
+        'audio/x-aac' => 'aac',
+        'audio/x-aiff' => 'aif',
+        'audio/x-mpegurl' => 'm3u',
+        'audio/x-ms-wax' => 'wax',
+        'audio/x-ms-wma' => 'wma',
+        'audio/x-pn-realaudio' => 'ram',
+        'audio/x-pn-realaudio-plugin' => 'rmp',
+        'audio/x-wav' => 'wav',
+        'chemical/x-cdx' => 'cdx',
+        'chemical/x-cif' => 'cif',
+        'chemical/x-cmdf' => 'cmdf',
+        'chemical/x-cml' => 'cml',
+        'chemical/x-csml' => 'csml',
+        'chemical/x-xyz' => 'xyz',
+        'image/bmp' => 'bmp',
+        'image/cgm' => 'cgm',
+        'image/g3fax' => 'g3',
+        'image/gif' => 'gif',
+        'image/ief' => 'ief',
+        'image/jpeg' => 'jpeg',
+        'image/ktx' => 'ktx',
+        'image/png' => 'png',
+        'image/prs.btif' => 'btif',
+        'image/svg+xml' => 'svg',
+        'image/tiff' => 'tiff',
+        'image/vnd.adobe.photoshop' => 'psd',
+        'image/vnd.dece.graphic' => 'uvi',
+        'image/vnd.dvb.subtitle' => 'sub',
+        'image/vnd.djvu' => 'djvu',
+        'image/vnd.dwg' => 'dwg',
+        'image/vnd.dxf' => 'dxf',
+        'image/vnd.fastbidsheet' => 'fbs',
+        'image/vnd.fpx' => 'fpx',
+        'image/vnd.fst' => 'fst',
+        'image/vnd.fujixerox.edmics-mmr' => 'mmr',
+        'image/vnd.fujixerox.edmics-rlc' => 'rlc',
+        'image/vnd.ms-modi' => 'mdi',
+        'image/vnd.net-fpx' => 'npx',
+        'image/vnd.wap.wbmp' => 'wbmp',
+        'image/vnd.xiff' => 'xif',
+        'image/webp' => 'webp',
+        'image/x-cmu-raster' => 'ras',
+        'image/x-cmx' => 'cmx',
+        'image/x-freehand' => 'fh',
+        'image/x-icon' => 'ico',
+        'image/x-pcx' => 'pcx',
+        'image/x-pict' => 'pic',
+        'image/x-portable-anymap' => 'pnm',
+        'image/x-portable-bitmap' => 'pbm',
+        'image/x-portable-graymap' => 'pgm',
+        'image/x-portable-pixmap' => 'ppm',
+        'image/x-rgb' => 'rgb',
+        'image/x-xbitmap' => 'xbm',
+        'image/x-xpixmap' => 'xpm',
+        'image/x-xwindowdump' => 'xwd',
+        'message/rfc822' => 'eml',
+        'model/iges' => 'igs',
+        'model/mesh' => 'msh',
+        'model/vnd.collada+xml' => 'dae',
+        'model/vnd.dwf' => 'dwf',
+        'model/vnd.gdl' => 'gdl',
+        'model/vnd.gtw' => 'gtw',
+        'model/vnd.mts' => 'mts',
+        'model/vnd.vtu' => 'vtu',
+        'model/vrml' => 'wrl',
+        'text/calendar' => 'ics',
+        'text/css' => 'css',
+        'text/csv' => 'csv',
+        'text/html' => 'html',
+        'text/n3' => 'n3',
+        'text/plain' => 'txt',
+        'text/prs.lines.tag' => 'dsc',
+        'text/richtext' => 'rtx',
+        'text/sgml' => 'sgml',
+        'text/tab-separated-values' => 'tsv',
+        'text/troff' => 't',
+        'text/turtle' => 'ttl',
+        'text/uri-list' => 'uri',
+        'text/vcard' => 'vcard',
+        'text/vnd.curl' => 'curl',
+        'text/vnd.curl.dcurl' => 'dcurl',
+        'text/vnd.curl.scurl' => 'scurl',
+        'text/vnd.curl.mcurl' => 'mcurl',
+        'text/vnd.dvb.subtitle' => 'sub',
+        'text/vnd.fly' => 'fly',
+        'text/vnd.fmi.flexstor' => 'flx',
+        'text/vnd.graphviz' => 'gv',
+        'text/vnd.in3d.3dml' => '3dml',
+        'text/vnd.in3d.spot' => 'spot',
+        'text/vnd.sun.j2me.app-descriptor' => 'jad',
+        'text/vnd.wap.wml' => 'wml',
+        'text/vnd.wap.wmlscript' => 'wmls',
+        'text/x-asm' => 's',
+        'text/x-c' => 'c',
+        'text/x-fortran' => 'f',
+        'text/x-pascal' => 'p',
+        'text/x-java-source' => 'java',
+        'text/x-setext' => 'etx',
+        'text/x-uuencode' => 'uu',
+        'text/x-vcalendar' => 'vcs',
+        'text/x-vcard' => 'vcf',
+        'video/3gpp' => '3gp',
+        'video/3gpp2' => '3g2',
+        'video/h261' => 'h261',
+        'video/h263' => 'h263',
+        'video/h264' => 'h264',
+        'video/jpeg' => 'jpgv',
+        'video/jpm' => 'jpm',
+        'video/mj2' => 'mj2',
+        'video/mp4' => 'mp4',
+        'video/mpeg' => 'mpeg',
+        'video/ogg' => 'ogv',
+        'video/quicktime' => 'qt',
+        'video/vnd.dece.hd' => 'uvh',
+        'video/vnd.dece.mobile' => 'uvm',
+        'video/vnd.dece.pd' => 'uvp',
+        'video/vnd.dece.sd' => 'uvs',
+        'video/vnd.dece.video' => 'uvv',
+        'video/vnd.dvb.file' => 'dvb',
+        'video/vnd.fvt' => 'fvt',
+        'video/vnd.mpegurl' => 'mxu',
+        'video/vnd.ms-playready.media.pyv' => 'pyv',
+        'video/vnd.uvvu.mp4' => 'uvu',
+        'video/vnd.vivo' => 'viv',
+        'video/webm' => 'webm',
+        'video/x-f4v' => 'f4v',
+        'video/x-fli' => 'fli',
+        'video/x-flv' => 'flv',
+        'video/x-m4v' => 'm4v',
+        'video/x-ms-asf' => 'asf',
+        'video/x-ms-wm' => 'wm',
+        'video/x-ms-wmv' => 'wmv',
+        'video/x-ms-wmx' => 'wmx',
+        'video/x-ms-wvx' => 'wvx',
+        'video/x-msvideo' => 'avi',
+        'video/x-sgi-movie' => 'movie',
+        'x-conference/x-cooltalk' => 'ice',
+    );
+
+    /**
+     * Returns the extension based on the mime type.
+     *
+     * If the mime type is unknown, returns null.
+     *
+     * @return string|null The guessed extension or null if it cannot be guessed
+     */
+    public function guess($mimeType)
+    {
+        return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null;
+    }
+}

+ 121 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php

@@ -0,0 +1,121 @@
+<?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\File\MimeType;
+
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
+
+/**
+ * A singleton mime type guesser.
+ *
+ * By default, all mime type guessers provided by the framework are installed
+ * (if available on the current OS/PHP setup). You can register custom
+ * guessers by calling the register() method on the singleton instance.
+ *
+ * <code>
+ * $guesser = MimeTypeGuesser::getInstance();
+ * $guesser->register(new MyCustomMimeTypeGuesser());
+ * </code>
+ *
+ * The last registered guesser is preferred over previously registered ones.
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class MimeTypeGuesser implements MimeTypeGuesserInterface
+{
+    /**
+     * The singleton instance
+     * @var MimeTypeGuesser
+     */
+    static private $instance = null;
+
+    /**
+     * All registered MimeTypeGuesserInterface instances
+     * @var array
+     */
+    protected $guessers = array();
+
+    /**
+     * Returns the singleton instance
+     *
+     * @return MimeTypeGuesser
+     */
+    static public function getInstance()
+    {
+        if (null === self::$instance) {
+            self::$instance = new self();
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Registers all natively provided mime type guessers
+     */
+    private function __construct()
+    {
+        if (FileBinaryMimeTypeGuesser::isSupported()) {
+            $this->register(new FileBinaryMimeTypeGuesser());
+        }
+
+        if (FileinfoMimeTypeGuesser::isSupported()) {
+            $this->register(new FileinfoMimeTypeGuesser());
+        }
+    }
+
+    /**
+     * Registers a new mime type guesser
+     *
+     * When guessing, this guesser is preferred over previously registered ones.
+     *
+     * @param MimeTypeGuesserInterface $guesser
+     */
+    public function register(MimeTypeGuesserInterface $guesser)
+    {
+        array_unshift($this->guessers, $guesser);
+    }
+
+    /**
+     * Tries to guess the mime type of the given file
+     *
+     * The file is passed to each registered mime type guesser in reverse order
+     * of their registration (last registered is queried first). Once a guesser
+     * returns a value that is not NULL, this method terminates and returns the
+     * value.
+     *
+     * @param  string $path   The path to the file
+     *
+     * @return string         The mime type or NULL, if none could be guessed
+     *
+     * @throws FileException  If the file does not exist
+     */
+    public function guess($path)
+    {
+        if (!is_file($path)) {
+            throw new FileNotFoundException($path);
+        }
+
+        if (!is_readable($path)) {
+            throw new AccessDeniedException($path);
+        }
+
+        if (!$this->guessers) {
+            throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)');
+        }
+
+        foreach ($this->guessers as $guesser) {
+            if (null !== $mimeType = $guesser->guess($path)) {
+                return $mimeType;
+            }
+        }
+    }
+}

+ 32 - 0
vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php

@@ -0,0 +1,32 @@
+<?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\File\MimeType;
+
+/**
+ * Guesses the mime type of a file
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+interface MimeTypeGuesserInterface
+{
+    /**
+     * Guesses the mime type of the file with the given path.
+     *
+     * @param  string $path   The path to the file
+     *
+     * @return string         The mime type or NULL, if none could be guessed
+     *
+     * @throws FileNotFoundException  If the file does not exist
+     * @throws AccessDeniedException  If the file could not be read
+     */
+    function guess($path);
+}

+ 223 - 0
vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php

@@ -0,0 +1,223 @@
+<?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\File;
+
+use Symfony\Component\HttpFoundation\File\Exception\FileException;
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+
+/**
+ * A file uploaded through a form.
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ * @author Florian Eckerstorfer <florian@eckerstorfer.org>
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class UploadedFile extends File
+{
+    /**
+     * Whether the test mode is activated.
+     *
+     * Local files are used in test mode hence the code should not enforce HTTP uploads.
+     *
+     * @var Boolean
+     */
+    private $test = false;
+
+    /**
+     * The original name of the uploaded file.
+     *
+     * @var string
+     */
+    private $originalName;
+
+    /**
+     * The mime type provided by the uploader.
+     *
+     * @var string
+     */
+    private $mimeType;
+
+    /**
+     * The file size provided by the uploader.
+     *
+     * @var string
+     */
+    private $size;
+
+    /**
+     * The UPLOAD_ERR_XXX constant provided by the uploader.
+     *
+     * @var integer
+     */
+    private $error;
+
+    /**
+     * Accepts the information of the uploaded file as provided by the PHP global $_FILES.
+     *
+     * The file object is only created when the uploaded file is valid (i.e. when the
+     * isValid() method returns true). Otherwise the only methods that could be called
+     * on an UploadedFile instance are:
+     *
+     *   * getClientOriginalName,
+     *   * getClientMimeType,
+     *   * isValid,
+     *   * getError.
+     *
+     * Calling any other method on an non-valid instance will cause an unpredictable result.
+     *
+     * @param string  $path         The full temporary path to the file
+     * @param string  $originalName The original file name
+     * @param string  $mimeType     The type of the file as provided by PHP
+     * @param integer $size         The file size
+     * @param integer $error        The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants)
+     * @param Boolean $test         Whether the test mode is active
+     *
+     * @throws FileException         If file_uploads is disabled
+     * @throws FileNotFoundException If the file does not exist
+     *
+     * @api
+     */
+    public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
+    {
+        if (!ini_get('file_uploads')) {
+            throw new FileException(sprintf('Unable to create UploadedFile because "file_uploads" is disabled in your php.ini file (%s)', get_cfg_var('cfg_file_path')));
+        }
+
+        $this->originalName = basename($originalName);
+        $this->mimeType = $mimeType ?: 'application/octet-stream';
+        $this->size = $size;
+        $this->error = $error ?: UPLOAD_ERR_OK;
+        $this->test = (Boolean) $test;
+
+        parent::__construct($path, UPLOAD_ERR_OK === $this->error);
+    }
+
+    /**
+     * Returns the original file name.
+     *
+     * It is extracted from the request from which the file has been uploaded.
+     * Then is should not be considered as a safe value.
+     *
+     * @return string|null The original name
+     *
+     * @api
+     */
+    public function getClientOriginalName()
+    {
+        return $this->originalName;
+    }
+
+    /**
+     * Returns the file mime type.
+     *
+     * It is extracted from the request from which the file has been uploaded.
+     * Then is should not be considered as a safe value.
+     *
+     * @return string|null The mime type
+     *
+     * @api
+     */
+    public function getClientMimeType()
+    {
+        return $this->mimeType;
+    }
+
+    /**
+     * Returns the file size.
+     *
+     * It is extracted from the request from which the file has been uploaded.
+     * Then is should not be considered as a safe value.
+     *
+     * @return integer|null The file size
+     *
+     * @api
+     */
+    public function getClientSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * Returns the upload error.
+     *
+     * If the upload was successful, the constant UPLOAD_ERR_OK is returned.
+     * Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
+     *
+     * @return integer The upload error
+     *
+     * @api
+     */
+    public function getError()
+    {
+        return $this->error;
+    }
+
+    /**
+     * Returns whether the file was uploaded successfully.
+     *
+     * @return Boolean  True if no error occurred during uploading
+     *
+     * @api
+     */
+    public function isValid()
+    {
+        return $this->error === UPLOAD_ERR_OK;
+    }
+
+    /**
+     * Moves the file to a new location.
+     *
+     * @param string $directory The destination folder
+     * @param string $name      The new file name
+     *
+     * @return File A File object representing the new file
+     *
+     * @throws FileException if the file has not been uploaded via Http
+     *
+     * @api
+     */
+    public function move($directory, $name = null)
+    {
+        if ($this->isValid() && ($this->test || is_uploaded_file($this->getPathname()))) {
+            return parent::move($directory, $name);
+        }
+
+        throw new FileException(sprintf('The file "%s" has not been uploaded via Http', $this->getPathname()));
+    }
+
+    /**
+     * Returns the maximum size of an uploaded file as configured in php.ini
+     *
+     * @return type The maximum size of an uploaded file in bytes
+     */
+    static public function getMaxFilesize()
+    {
+        $max = trim(ini_get('upload_max_filesize'));
+
+        if ('' === $max) {
+            return PHP_INT_MAX;
+        }
+
+        switch (strtolower(substr($max, -1))) {
+            case 'g':
+                $max *= 1024;
+            case 'm':
+                $max *= 1024;
+            case 'k':
+                $max *= 1024;
+        }
+
+        return (integer) $max;
+    }
+}

+ 158 - 0
vendor/Symfony/Component/HttpFoundation/FileBag.php

@@ -0,0 +1,158 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+
+/**
+ * FileBag is a container for HTTP headers.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ *
+ * @api
+ */
+class FileBag extends ParameterBag
+{
+    static private $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
+
+    /**
+     * Constructor.
+     *
+     * @param array $parameters An array of HTTP files
+     *
+     * @api
+     */
+    public function __construct(array $parameters = array())
+    {
+        $this->replace($parameters);
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see Symfony\Component\HttpFoundation\ParameterBag::replace()
+     *
+     * @api
+     */
+    public function replace(array $files = array())
+    {
+        $this->parameters = array();
+        $this->add($files);
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see Symfony\Component\HttpFoundation\ParameterBag::set()
+     *
+     * @api
+     */
+    public function set($key, $value)
+    {
+        if (is_array($value) || $value instanceof UploadedFile) {
+            parent::set($key, $this->convertFileInformation($value));
+        } else {
+            throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.');
+        }
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see Symfony\Component\HttpFoundation\ParameterBag::add()
+     *
+     * @api
+     */
+    public function add(array $files = array())
+    {
+        foreach ($files as $key => $file) {
+            $this->set($key, $file);
+        }
+    }
+
+    /**
+     * Converts uploaded files to UploadedFile instances.
+     *
+     * @param  array|UploadedFile $file A (multi-dimensional) array of uploaded file information
+     *
+     * @return array A (multi-dimensional) array of UploadedFile instances
+     */
+    protected function convertFileInformation($file)
+    {
+        if ($file instanceof UploadedFile) {
+            return $file;
+        }
+
+        $file = $this->fixPhpFilesArray($file);
+        if (is_array($file)) {
+            $keys = array_keys($file);
+            sort($keys);
+
+            if ($keys == self::$fileKeys) {
+                if (UPLOAD_ERR_NO_FILE == $file['error']) {
+                    $file = null;
+                } else {
+                    $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
+                }
+            } else {
+                $file = array_map(array($this, 'convertFileInformation'), $file);
+            }
+        }
+
+        return $file;
+    }
+
+    /**
+     * Fixes a malformed PHP $_FILES array.
+     *
+     * PHP has a bug that the format of the $_FILES array differs, depending on
+     * whether the uploaded file fields had normal field names or array-like
+     * field names ("normal" vs. "parent[child]").
+     *
+     * This method fixes the array to look like the "normal" $_FILES array.
+     *
+     * It's safe to pass an already converted array, in which case this method
+     * just returns the original array unmodified.
+     *
+     * @param  array $data
+     *
+     * @return array
+     */
+    protected function fixPhpFilesArray($data)
+    {
+        if (!is_array($data)) {
+            return $data;
+        }
+
+        $keys = array_keys($data);
+        sort($keys);
+
+        if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) {
+            return $data;
+        }
+
+        $files = $data;
+        foreach (self::$fileKeys as $k) {
+            unset($files[$k]);
+        }
+
+        foreach (array_keys($data['name']) as $key) {
+            $files[$key] = $this->fixPhpFilesArray(array(
+                'error'    => $data['error'][$key],
+                'name'     => $data['name'][$key],
+                'type'     => $data['type'][$key],
+                'tmp_name' => $data['tmp_name'][$key],
+                'size'     => $data['size'][$key]
+            ));
+        }
+
+        return $files;
+    }
+}

+ 306 - 0
vendor/Symfony/Component/HttpFoundation/HeaderBag.php

@@ -0,0 +1,306 @@
+<?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;
+
+/**
+ * HeaderBag is a container for HTTP headers.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class HeaderBag
+{
+    protected $headers;
+    protected $cacheControl;
+
+    /**
+     * Constructor.
+     *
+     * @param array $headers An array of HTTP headers
+     *
+     * @api
+     */
+    public function __construct(array $headers = array())
+    {
+        $this->cacheControl = array();
+        $this->headers = array();
+        foreach ($headers as $key => $values) {
+            $this->set($key, $values);
+        }
+    }
+
+    /**
+     * Returns the headers as a string.
+     *
+     * @return string The headers
+     */
+    public function __toString()
+    {
+        if (!$this->headers) {
+            return '';
+        }
+
+        $beautifier = function ($name) {
+            return preg_replace_callback('/\-(.)/', function ($match) { return '-'.strtoupper($match[1]); }, ucfirst($name));
+        };
+
+        $max = max(array_map('strlen', array_keys($this->headers))) + 1;
+        $content = '';
+        ksort($this->headers);
+        foreach ($this->headers as $name => $values) {
+            foreach ($values as $value) {
+                $content .= sprintf("%-{$max}s %s\r\n", $beautifier($name).':', $value);
+            }
+        }
+
+        return $content;
+    }
+
+    /**
+     * Returns the headers.
+     *
+     * @return array An array of headers
+     *
+     * @api
+     */
+    public function all()
+    {
+        return $this->headers;
+    }
+
+    /**
+     * Returns the parameter keys.
+     *
+     * @return array An array of parameter keys
+     *
+     * @api
+     */
+    public function keys()
+    {
+        return array_keys($this->headers);
+    }
+
+    /**
+     * Replaces the current HTTP headers by a new set.
+     *
+     * @param array  $headers An array of HTTP headers
+     *
+     * @api
+     */
+    public function replace(array $headers = array())
+    {
+        $this->headers = array();
+        $this->add($headers);
+    }
+
+    /**
+     * Adds new headers the current HTTP headers set.
+     *
+     * @param array  $headers An array of HTTP headers
+     *
+     * @api
+     */
+    public function add(array $headers)
+    {
+        foreach ($headers as $key => $values) {
+            $this->set($key, $values);
+        }
+    }
+
+    /**
+     * Returns a header value by name.
+     *
+     * @param string  $key     The header name
+     * @param mixed   $default The default value
+     * @param Boolean $first   Whether to return the first value or all header values
+     *
+     * @return string|array The first header value if $first is true, an array of values otherwise
+     *
+     * @api
+     */
+    public function get($key, $default = null, $first = true)
+    {
+        $key = strtr(strtolower($key), '_', '-');
+
+        if (!array_key_exists($key, $this->headers)) {
+            if (null === $default) {
+                return $first ? null : array();
+            }
+
+            return $first ? $default : array($default);
+        }
+
+        if ($first) {
+            return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
+        }
+
+        return $this->headers[$key];
+    }
+
+    /**
+     * Sets a header by name.
+     *
+     * @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)
+     *
+     * @api
+     */
+    public function set($key, $values, $replace = true)
+    {
+        $key = strtr(strtolower($key), '_', '-');
+
+        $values = (array) $values;
+
+        if (true === $replace || !isset($this->headers[$key])) {
+            $this->headers[$key] = $values;
+        } else {
+            $this->headers[$key] = array_merge($this->headers[$key], $values);
+        }
+
+        if ('cache-control' === $key) {
+            $this->cacheControl = $this->parseCacheControl($values[0]);
+        }
+    }
+
+    /**
+     * Returns true if the HTTP header is defined.
+     *
+     * @param string $key The HTTP header
+     *
+     * @return Boolean true if the parameter exists, false otherwise
+     *
+     * @api
+     */
+    public function has($key)
+    {
+        return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
+    }
+
+    /**
+     * Returns true if the given HTTP header contains the given value.
+     *
+     * @param string $key   The HTTP header name
+     * @param string $value The HTTP value
+     *
+     * @return Boolean true if the value is contained in the header, false otherwise
+     *
+     * @api
+     */
+    public function contains($key, $value)
+    {
+        return in_array($value, $this->get($key, null, false));
+    }
+
+    /**
+     * Removes a header.
+     *
+     * @param string $key The HTTP header name
+     *
+     * @api
+     */
+    public function remove($key)
+    {
+        $key = strtr(strtolower($key), '_', '-');
+
+        unset($this->headers[$key]);
+
+        if ('cache-control' === $key) {
+            $this->cacheControl = array();
+        }
+    }
+
+    /**
+     * Returns the HTTP header value converted to a date.
+     *
+     * @param string    $key     The parameter key
+     * @param \DateTime $default The default value
+     *
+     * @return \DateTime The filtered value
+     *
+     * @api
+     */
+    public function getDate($key, \DateTime $default = null)
+    {
+        if (null === $value = $this->get($key)) {
+            return $default;
+        }
+
+        if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
+            throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
+        }
+
+        return $date;
+    }
+
+    public function addCacheControlDirective($key, $value = true)
+    {
+        $this->cacheControl[$key] = $value;
+
+        $this->set('Cache-Control', $this->getCacheControlHeader());
+    }
+
+    public function hasCacheControlDirective($key)
+    {
+        return array_key_exists($key, $this->cacheControl);
+    }
+
+    public function getCacheControlDirective($key)
+    {
+        return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
+    }
+
+    public function removeCacheControlDirective($key)
+    {
+        unset($this->cacheControl[$key]);
+
+        $this->set('Cache-Control', $this->getCacheControlHeader());
+    }
+
+    protected function getCacheControlHeader()
+    {
+        $parts = array();
+        ksort($this->cacheControl);
+        foreach ($this->cacheControl as $key => $value) {
+            if (true === $value) {
+                $parts[] = $key;
+            } else {
+                if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
+                    $value = '"'.$value.'"';
+                }
+
+                $parts[] = "$key=$value";
+            }
+        }
+
+        return implode(', ', $parts);
+    }
+
+    /**
+     * Parses a Cache-Control HTTP header.
+     *
+     * @param string $header The value of the Cache-Control HTTP header
+     *
+     * @return array An array representing the attribute values
+     */
+    protected function parseCacheControl($header)
+    {
+        $cacheControl = array();
+        preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
+        foreach ($matches as $match) {
+            $cacheControl[strtolower($match[1])] = isset($match[2]) && $match[2] ? $match[2] : (isset($match[3]) ? $match[3] : true);
+        }
+
+        return $cacheControl;
+    }
+}

+ 49 - 0
vendor/Symfony/Component/HttpFoundation/JsonResponse.php

@@ -0,0 +1,49 @@
+<?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;
+
+/**
+ * Response represents an HTTP response in JSON format.
+ *
+ * @author Igor Wiedler <igor@wiedler.ch>
+ */
+class JsonResponse extends Response
+{
+    /**
+     * Constructor.
+     *
+     * @param mixed   $data    The response data
+     * @param integer $status  The response status code
+     * @param array   $headers An array of response headers
+     */
+    public function __construct($data = array(), $status = 200, $headers = array())
+    {
+        // root should be JSON object, not array
+        if (is_array($data) && 0 === count($data)) {
+            $data = new \ArrayObject();
+        }
+
+        parent::__construct(
+            json_encode($data),
+            $status,
+            array_merge(array('Content-Type' => 'application/json'), $headers)
+        );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    static public function create($data = array(), $status = 200, $headers = array())
+    {
+        return new static($data, $status, $headers);
+    }
+}

+ 19 - 0
vendor/Symfony/Component/HttpFoundation/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2004-2012 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
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 27 - 0
vendor/Symfony/Component/HttpFoundation/LaravelRequest.php

@@ -0,0 +1,27 @@
+<?php namespace Symfony\Component\HttpFoundation;
+
+class LaravelRequest extends Request {
+
+    /**
+     * Creates a new request with values from PHP's super globals.
+     *
+     * @return Request A new request
+     *
+     * @api
+     */
+    static public function createFromGlobals()
+    {
+        $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
+
+        if (0 === strpos($request->server->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
+            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
+        ) {
+            parse_str($request->getContent(), $data);
+            if (magic_quotes()) $data = array_strip_slashes($data);
+            $request->request = new ParameterBag($data);
+        }
+
+        return $request;
+    }
+
+}

+ 281 - 0
vendor/Symfony/Component/HttpFoundation/ParameterBag.php

@@ -0,0 +1,281 @@
+<?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;
+
+/**
+ * ParameterBag is a container for key/value pairs.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class ParameterBag
+{
+    /**
+     * Parameter storage.
+     *
+     * @var array
+     */
+    protected $parameters;
+
+    /**
+     * Constructor.
+     *
+     * @param array $parameters An array of parameters
+     *
+     * @api
+     */
+    public function __construct(array $parameters = array())
+    {
+        $this->parameters = $parameters;
+    }
+
+    /**
+     * Returns the parameters.
+     *
+     * @return array An array of parameters
+     *
+     * @api
+     */
+    public function all()
+    {
+        return $this->parameters;
+    }
+
+    /**
+     * Returns the parameter keys.
+     *
+     * @return array An array of parameter keys
+     *
+     * @api
+     */
+    public function keys()
+    {
+        return array_keys($this->parameters);
+    }
+
+    /**
+     * Replaces the current parameters by a new set.
+     *
+     * @param array $parameters An array of parameters
+     *
+     * @api
+     */
+    public function replace(array $parameters = array())
+    {
+        $this->parameters = $parameters;
+    }
+
+    /**
+     * Adds parameters.
+     *
+     * @param array $parameters An array of parameters
+     *
+     * @api
+     */
+    public function add(array $parameters = array())
+    {
+        $this->parameters = array_replace($this->parameters, $parameters);
+    }
+
+    /**
+     * Returns a parameter by name.
+     *
+     * @param string  $path    The key
+     * @param mixed   $default The default value if the parameter key does not exist
+     * @param boolean $deep If true, a path like foo[bar] will find deeper items
+     *
+     * @api
+     */
+    public function get($path, $default = null, $deep = false)
+    {
+        if (!$deep || false === $pos = strpos($path, '[')) {
+            return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default;
+        }
+
+        $root = substr($path, 0, $pos);
+        if (!array_key_exists($root, $this->parameters)) {
+            return $default;
+        }
+
+        $value = $this->parameters[$root];
+        $currentKey = null;
+        for ($i=$pos,$c=strlen($path); $i<$c; $i++) {
+            $char = $path[$i];
+
+            if ('[' === $char) {
+                if (null !== $currentKey) {
+                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i));
+                }
+
+                $currentKey = '';
+            } elseif (']' === $char) {
+                if (null === $currentKey) {
+                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i));
+                }
+
+                if (!is_array($value) || !array_key_exists($currentKey, $value)) {
+                    return $default;
+                }
+
+                $value = $value[$currentKey];
+                $currentKey = null;
+            } else {
+                if (null === $currentKey) {
+                    throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i));
+                }
+
+                $currentKey .= $char;
+            }
+        }
+
+        if (null !== $currentKey) {
+            throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".'));
+        }
+
+        return $value;
+    }
+
+    /**
+     * Sets a parameter by name.
+     *
+     * @param string $key   The key
+     * @param mixed  $value The value
+     *
+     * @api
+     */
+    public function set($key, $value)
+    {
+        $this->parameters[$key] = $value;
+    }
+
+    /**
+     * Returns true if the parameter is defined.
+     *
+     * @param string $key The key
+     *
+     * @return Boolean true if the parameter exists, false otherwise
+     *
+     * @api
+     */
+    public function has($key)
+    {
+        return array_key_exists($key, $this->parameters);
+    }
+
+    /**
+     * Removes a parameter.
+     *
+     * @param string $key The key
+     *
+     * @api
+     */
+    public function remove($key)
+    {
+        unset($this->parameters[$key]);
+    }
+
+    /**
+     * Returns the alphabetic characters of the parameter value.
+     *
+     * @param string  $key     The parameter key
+     * @param mixed   $default The default value if the parameter key does not exist
+     * @param boolean $deep If true, a path like foo[bar] will find deeper items
+     *
+     * @return string The filtered value
+     *
+     * @api
+     */
+    public function getAlpha($key, $default = '', $deep = false)
+    {
+        return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep));
+    }
+
+    /**
+     * Returns the alphabetic characters and digits of the parameter value.
+     *
+     * @param string  $key     The parameter key
+     * @param mixed   $default The default value if the parameter key does not exist
+     * @param boolean $deep If true, a path like foo[bar] will find deeper items
+     *
+     * @return string The filtered value
+     *
+     * @api
+     */
+    public function getAlnum($key, $default = '', $deep = false)
+    {
+        return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep));
+    }
+
+    /**
+     * Returns the digits of the parameter value.
+     *
+     * @param string  $key     The parameter key
+     * @param mixed   $default The default value if the parameter key does not exist
+     * @param boolean $deep If true, a path like foo[bar] will find deeper items
+     *
+     * @return string The filtered value
+     *
+     * @api
+     */
+    public function getDigits($key, $default = '', $deep = false)
+    {
+        // we need to remove - and + because they're allowed in the filter
+        return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT));
+    }
+
+    /**
+     * Returns the parameter value converted to integer.
+     *
+     * @param string  $key     The parameter key
+     * @param mixed   $default The default value if the parameter key does not exist
+     * @param boolean $deep If true, a path like foo[bar] will find deeper items
+     *
+     * @return string The filtered value
+     *
+     * @api
+     */
+    public function getInt($key, $default = 0, $deep = false)
+    {
+        return (int) $this->get($key, $default, $deep);
+    }
+
+    /**
+     * Filter key.
+     *
+     * @param string  $key     Key.
+     * @param mixed   $default Default = null.
+     * @param boolean $deep    Default = false.
+     * @param integer $filter  FILTER_* constant.
+     * @param mixed   $options Filter options.
+     *
+     * @see http://php.net/manual/en/function.filter-var.php
+     *
+     * @return mixed
+     */
+    public function filter($key, $default = null, $deep = false, $filter=FILTER_DEFAULT, $options=array())
+    {
+        $value = $this->get($key, $default, $deep);
+
+        // Always turn $options into an array - this allows filter_var option shortcuts.
+        if (!is_array($options) && $options) {
+            $options = array('flags' => $options);
+        }
+
+        // Add a convenience check for arrays.
+        if (is_array($value) && !isset($options['flags'])) {
+            $options['flags'] = FILTER_REQUIRE_ARRAY;
+        }
+
+        return filter_var($value, $filter, $options);
+    }
+}

+ 47 - 0
vendor/Symfony/Component/HttpFoundation/README.md

@@ -0,0 +1,47 @@
+HttpFoundation Component
+========================
+
+HttpFoundation defines an object-oriented layer for the HTTP specification.
+
+It provides an abstraction for requests, responses, uploaded files, cookies,
+sessions, ...
+
+In this example, we get a Request object from the current PHP global
+variables:
+
+    use Symfony\Component\HttpFoundation\Request;
+    use Symfony\Component\HttpFoundation\Response;
+
+    $request = Request::createFromGlobals();
+    echo $request->getPathInfo();
+
+You can also create a Request directly -- that's interesting for unit testing:
+
+    $request = Request::create('/?foo=bar', 'GET');
+    echo $request->getPathInfo();
+
+And here is how to create and send a Response:
+
+    $response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));
+    $response->send();
+
+The Request and the Response classes have many other methods that implement
+the HTTP specification.
+
+Loading
+-------
+
+If you are using PHP 5.3.x you must add the following to your autoloader:
+
+    // SessionHandlerInterface
+    if (!interface_exists('SessionHandlerInterface')) {
+        $loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs');
+    }
+
+
+Resources
+---------
+
+Unit tests:
+
+https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/HttpFoundation

+ 83 - 0
vendor/Symfony/Component/HttpFoundation/RedirectResponse.php

@@ -0,0 +1,83 @@
+<?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;
+
+/**
+ * RedirectResponse represents an HTTP response doing a redirect.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class RedirectResponse extends Response
+{
+    protected $targetUrl;
+
+    /**
+     * Creates a redirect response so that it conforms to the rules defined for a redirect status code.
+     *
+     * @param string  $url     The URL to redirect to
+     * @param integer $status  The status code (302 by default)
+     * @param array   $headers The headers (Location is always set to the given url)
+     *
+     * @see http://tools.ietf.org/html/rfc2616#section-10.3
+     *
+     * @api
+     */
+    public function __construct($url, $status = 302, $headers = array())
+    {
+        if (empty($url)) {
+            throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
+        }
+
+        $this->targetUrl = $url;
+
+        parent::__construct(
+            sprintf('<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <meta http-equiv="refresh" content="1;url=%1$s" />
+
+        <title>Redirecting to %1$s</title>
+    </head>
+    <body>
+        Redirecting to <a href="%1$s">%1$s</a>.
+    </body>
+</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8')),
+            $status,
+            array_merge($headers, array('Location' => $url))
+        );
+
+        if (!$this->isRedirect()) {
+            throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    static public function create($url = '', $status = 302, $headers = array())
+    {
+        return new static($url, $status, $headers);
+    }
+
+    /**
+     * Returns the target URL.
+     *
+     * @return string target URL
+     */
+    public function getTargetUrl()
+    {
+        return $this->targetUrl;
+    }
+}

+ 1413 - 0
vendor/Symfony/Component/HttpFoundation/Request.php

@@ -0,0 +1,1413 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+
+/**
+ * Request represents an HTTP request.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Request
+{
+    static protected $trustProxy = false;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\ParameterBag
+     *
+     * @api
+     */
+    public $attributes;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\ParameterBag
+     *
+     * @api
+     */
+    public $request;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\ParameterBag
+     *
+     * @api
+     */
+    public $query;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\ServerBag
+     *
+     * @api
+     */
+    public $server;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\FileBag
+     *
+     * @api
+     */
+    public $files;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\ParameterBag
+     *
+     * @api
+     */
+    public $cookies;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\HeaderBag
+     *
+     * @api
+     */
+    public $headers;
+
+    /**
+     * @var string
+     */
+    protected $content;
+
+    /**
+     * @var string
+     */
+    protected $languages;
+
+    /**
+     * @var string
+     */
+    protected $charsets;
+
+    /**
+     * @var string
+     */
+    protected $acceptableContentTypes;
+
+    /**
+     * @var string
+     */
+    protected $pathInfo;
+
+    /**
+     * @var string
+     */
+    protected $requestUri;
+
+    /**
+     * @var string
+     */
+    protected $baseUrl;
+
+    /**
+     * @var string
+     */
+    protected $basePath;
+
+    /**
+     * @var string
+     */
+    protected $method;
+
+    /**
+     * @var string
+     */
+    protected $format;
+
+    /**
+     * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
+     */
+    protected $session;
+
+    /**
+     * @var string
+     */
+    protected $locale;
+
+    /**
+     * @var string
+     */
+    protected $defaultLocale = 'en';
+
+    /**
+     * @var string
+     */
+    static protected $formats;
+
+    /**
+     * Constructor.
+     *
+     * @param array  $query      The GET parameters
+     * @param array  $request    The POST parameters
+     * @param array  $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
+     * @param array  $cookies    The COOKIE parameters
+     * @param array  $files      The FILES parameters
+     * @param array  $server     The SERVER parameters
+     * @param string $content    The raw body data
+     *
+     * @api
+     */
+    public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
+    {
+        $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
+    }
+
+    /**
+     * Sets the parameters for this request.
+     *
+     * This method also re-initializes all properties.
+     *
+     * @param array  $query      The GET parameters
+     * @param array  $request    The POST parameters
+     * @param array  $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
+     * @param array  $cookies    The COOKIE parameters
+     * @param array  $files      The FILES parameters
+     * @param array  $server     The SERVER parameters
+     * @param string $content    The raw body data
+     *
+     * @api
+     */
+    public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
+    {
+        $this->request = new ParameterBag($request);
+        $this->query = new ParameterBag($query);
+        $this->attributes = new ParameterBag($attributes);
+        $this->cookies = new ParameterBag($cookies);
+        $this->files = new FileBag($files);
+        $this->server = new ServerBag($server);
+        $this->headers = new HeaderBag($this->server->getHeaders());
+
+        $this->content = $content;
+        $this->languages = null;
+        $this->charsets = null;
+        $this->acceptableContentTypes = null;
+        $this->pathInfo = null;
+        $this->requestUri = null;
+        $this->baseUrl = null;
+        $this->basePath = null;
+        $this->method = null;
+        $this->format = null;
+    }
+
+    /**
+     * Creates a new request with values from PHP's super globals.
+     *
+     * @return Request A new request
+     *
+     * @api
+     */
+    static public function createFromGlobals()
+    {
+        $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
+
+        if (0 === strpos($request->server->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
+            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
+        ) {
+            parse_str($request->getContent(), $data);
+            $request->request = new ParameterBag($data);
+        }
+
+        return $request;
+    }
+
+    /**
+     * Creates a Request based on a given URI and configuration.
+     *
+     * @param string $uri        The URI
+     * @param string $method     The HTTP method
+     * @param array  $parameters The request (GET) or query (POST) parameters
+     * @param array  $cookies    The request cookies ($_COOKIE)
+     * @param array  $files      The request files ($_FILES)
+     * @param array  $server     The server parameters ($_SERVER)
+     * @param string $content    The raw body data
+     *
+     * @return Request A Request instance
+     *
+     * @api
+     */
+    static public function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
+    {
+        $defaults = array(
+            'SERVER_NAME'          => 'localhost',
+            'SERVER_PORT'          => 80,
+            'HTTP_HOST'            => 'localhost',
+            'HTTP_USER_AGENT'      => 'Symfony/2.X',
+            'HTTP_ACCEPT'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
+            'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
+            'HTTP_ACCEPT_CHARSET'  => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
+            'REMOTE_ADDR'          => '127.0.0.1',
+            'SCRIPT_NAME'          => '',
+            'SCRIPT_FILENAME'      => '',
+            'SERVER_PROTOCOL'      => 'HTTP/1.1',
+            'REQUEST_TIME'         => time(),
+        );
+
+        $components = parse_url($uri);
+        if (isset($components['host'])) {
+            $defaults['SERVER_NAME'] = $components['host'];
+            $defaults['HTTP_HOST'] = $components['host'];
+        }
+
+        if (isset($components['scheme'])) {
+            if ('https' === $components['scheme']) {
+                $defaults['HTTPS'] = 'on';
+                $defaults['SERVER_PORT'] = 443;
+            }
+        }
+
+        if (isset($components['port'])) {
+            $defaults['SERVER_PORT'] = $components['port'];
+            $defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port'];
+        }
+
+        if (isset($components['user'])) {
+            $defaults['PHP_AUTH_USER'] = $components['user'];
+        }
+
+        if (isset($components['pass'])) {
+            $defaults['PHP_AUTH_PW'] = $components['pass'];
+        }
+
+        if (!isset($components['path'])) {
+            $components['path'] = '';
+        }
+
+        switch (strtoupper($method)) {
+            case 'POST':
+            case 'PUT':
+            case 'DELETE':
+                $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+            case 'PATCH':
+                $request = $parameters;
+                $query = array();
+                break;
+            default:
+                $request = array();
+                $query = $parameters;
+                break;
+        }
+
+        if (isset($components['query'])) {
+            $queryString = html_entity_decode($components['query']);
+            parse_str($queryString, $qs);
+            if (is_array($qs)) {
+                $query = array_replace($qs, $query);
+            }
+        }
+        $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,
+        ));
+
+        return new static($query, $request, array(), $cookies, $files, $server, $content);
+    }
+
+    /**
+     * Clones a request and overrides some of its parameters.
+     *
+     * @param array $query      The GET parameters
+     * @param array $request    The POST parameters
+     * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
+     * @param array $cookies    The COOKIE parameters
+     * @param array $files      The FILES parameters
+     * @param array $server     The SERVER parameters
+     *
+     * @api
+     */
+    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
+    {
+        $dup = clone $this;
+        if ($query !== null) {
+            $dup->query = new ParameterBag($query);
+        }
+        if ($request !== null) {
+            $dup->request = new ParameterBag($request);
+        }
+        if ($attributes !== null) {
+            $dup->attributes = new ParameterBag($attributes);
+        }
+        if ($cookies !== null) {
+            $dup->cookies = new ParameterBag($cookies);
+        }
+        if ($files !== null) {
+            $dup->files = new FileBag($files);
+        }
+        if ($server !== null) {
+            $dup->server = new ServerBag($server);
+            $dup->headers = new HeaderBag($dup->server->getHeaders());
+        }
+        $dup->languages = null;
+        $dup->charsets = null;
+        $dup->acceptableContentTypes = null;
+        $dup->pathInfo = null;
+        $dup->requestUri = null;
+        $dup->baseUrl = null;
+        $dup->basePath = null;
+        $dup->method = null;
+        $dup->format = null;
+
+        return $dup;
+    }
+
+    /**
+     * Clones the current request.
+     *
+     * Note that the session is not cloned as duplicated requests
+     * are most of the time sub-requests of the main one.
+     */
+    public function __clone()
+    {
+        $this->query      = clone $this->query;
+        $this->request    = clone $this->request;
+        $this->attributes = clone $this->attributes;
+        $this->cookies    = clone $this->cookies;
+        $this->files      = clone $this->files;
+        $this->server     = clone $this->server;
+        $this->headers    = clone $this->headers;
+    }
+
+    /**
+     * Returns the request as a string.
+     *
+     * @return string The request
+     */
+    public function __toString()
+    {
+        return
+            sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
+            $this->headers."\r\n".
+            $this->getContent();
+    }
+
+    /**
+     * Overrides the PHP global variables according to this request instance.
+     *
+     * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE, and $_FILES.
+     *
+     * @api
+     */
+    public function overrideGlobals()
+    {
+        $_GET = $this->query->all();
+        $_POST = $this->request->all();
+        $_SERVER = $this->server->all();
+        $_COOKIE = $this->cookies->all();
+        // FIXME: populate $_FILES
+
+        foreach ($this->headers->all() as $key => $value) {
+            $key = strtoupper(str_replace('-', '_', $key));
+            if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
+                $_SERVER[$key] = implode(', ', $value);
+            } else {
+                $_SERVER['HTTP_'.$key] = implode(', ', $value);
+            }
+        }
+
+        // FIXME: should read variables_order and request_order
+        // to know which globals to merge and in which order
+        $_REQUEST = array_merge($_GET, $_POST);
+    }
+
+    /**
+     * Trusts $_SERVER entries coming from proxies.
+     *
+     * You should only call this method if your application
+     * is hosted behind a reverse proxy that you manage.
+     *
+     * @api
+     */
+    static public function trustProxyData()
+    {
+        self::$trustProxy = true;
+    }
+
+    /**
+     * Returns true if $_SERVER entries coming from proxies are trusted,
+     * false otherwise.
+     *
+     * @return boolean
+     */
+    static public function isProxyTrusted()
+    {
+        return self::$trustProxy;
+    }
+
+    /**
+     * Gets a "parameter" value.
+     *
+     * This method is mainly useful for libraries that want to provide some flexibility.
+     *
+     * Order of precedence: GET, PATH, POST, COOKIE
+     *
+     * Avoid using this method in controllers:
+     *
+     *  * slow
+     *  * prefer to get from a "named" source
+     *
+     * It is better to explicity get request parameters from the appropriate
+     * public property instead (query, request, attributes, ...).
+     *
+     * @param string    $key        the key
+     * @param mixed     $default    the default value
+     * @param type      $deep       is parameter deep in multidimensional array
+     *
+     * @return mixed
+     */
+    public function get($key, $default = null, $deep = false)
+    {
+        return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep);
+    }
+
+    /**
+     * Gets the Session.
+     *
+     * @return SessionInterface|null The session
+     *
+     * @api
+     */
+    public function getSession()
+    {
+        return $this->session;
+    }
+
+    /**
+     * Whether the request contains a Session which was started in one of the
+     * previous requests.
+     *
+     * @return boolean
+     *
+     * @api
+     */
+    public function hasPreviousSession()
+    {
+        // the check for $this->session avoids malicious users trying to fake a session cookie with proper name
+        $sessionName = $this->hasSession() ? $this->session->getName() : null;
+
+        return $this->cookies->has($sessionName) && $this->hasSession();
+    }
+
+    /**
+     * Whether the request contains a Session object.
+     *
+     * @return boolean
+     *
+     * @api
+     */
+    public function hasSession()
+    {
+        return null !== $this->session;
+    }
+
+    /**
+     * Sets the Session.
+     *
+     * @param SessionInterface $session The Session
+     *
+     * @api
+     */
+    public function setSession(SessionInterface $session)
+    {
+        $this->session = $session;
+    }
+
+    /**
+     * Returns the client IP address.
+     *
+     * @return string The client IP address
+     *
+     * @api
+     */
+    public function getClientIp()
+    {
+        if (self::$trustProxy) {
+            if ($this->server->has('HTTP_CLIENT_IP')) {
+                return $this->server->get('HTTP_CLIENT_IP');
+            } elseif ($this->server->has('HTTP_X_FORWARDED_FOR')) {
+                $clientIp = explode(',', $this->server->get('HTTP_X_FORWARDED_FOR'), 2);
+
+                return isset($clientIp[0]) ? trim($clientIp[0]) : '';
+            }
+        }
+
+        return $this->server->get('REMOTE_ADDR');
+    }
+
+    /**
+     * Returns current script name.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getScriptName()
+    {
+        return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
+    }
+
+    /**
+     * Returns the path being requested relative to the executed script.
+     *
+     * The path info always starts with a /.
+     *
+     * Suppose this request is instantiated from /mysite on localhost:
+     *
+     *  * http://localhost/mysite              returns an empty string
+     *  * http://localhost/mysite/about        returns '/about'
+     *  * http://localhost/mysite/about?var=1  returns '/about'
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getPathInfo()
+    {
+        if (null === $this->pathInfo) {
+            $this->pathInfo = $this->preparePathInfo();
+        }
+
+        return $this->pathInfo;
+    }
+
+    /**
+     * Returns the root path from which this request is executed.
+     *
+     * Suppose that an index.php file instantiates this request object:
+     *
+     *  * http://localhost/index.php        returns an empty string
+     *  * http://localhost/index.php/page   returns an empty string
+     *  * http://localhost/web/index.php    return '/web'
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getBasePath()
+    {
+        if (null === $this->basePath) {
+            $this->basePath = $this->prepareBasePath();
+        }
+
+        return $this->basePath;
+    }
+
+    /**
+     * Returns the root url from which this request is executed.
+     *
+     * The base URL never ends with a /.
+     *
+     * This is similar to getBasePath(), except that it also includes the
+     * script filename (e.g. index.php) if one exists.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getBaseUrl()
+    {
+        if (null === $this->baseUrl) {
+            $this->baseUrl = $this->prepareBaseUrl();
+        }
+
+        return $this->baseUrl;
+    }
+
+    /**
+     * Gets the request's scheme.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getScheme()
+    {
+        return $this->isSecure() ? 'https' : 'http';
+    }
+
+    /**
+     * Returns the port on which the request is made.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getPort()
+    {
+        if (self::$trustProxy && $this->headers->has('X-Forwarded-Port')) {
+            return $this->headers->get('X-Forwarded-Port');
+        } else {
+            return $this->server->get('SERVER_PORT');
+        }
+    }
+
+    /**
+     * Returns the user.
+     *
+     * @return string|null
+     */
+    public function getUser()
+    {
+        return $this->server->get('PHP_AUTH_USER');
+    }
+
+    /**
+     * Returns the password.
+     *
+     * @return string|null
+     */
+    public function getPassword()
+    {
+        return $this->server->get('PHP_AUTH_PW');
+    }
+
+    /**
+     * Returns the HTTP host being requested.
+     *
+     * The port name will be appended to the host if it's non-standard.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getHttpHost()
+    {
+        $scheme = $this->getScheme();
+        $port   = $this->getPort();
+
+        if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
+            return $this->getHost();
+        }
+
+        return $this->getHost().':'.$port;
+    }
+
+    /**
+     * Returns the requested URI.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getRequestUri()
+    {
+        if (null === $this->requestUri) {
+            $this->requestUri = $this->prepareRequestUri();
+        }
+
+        return $this->requestUri;
+    }
+
+    /**
+     * Generates a normalized URI for the Request.
+     *
+     * @return string A normalized URI for the Request
+     *
+     * @see getQueryString()
+     *
+     * @api
+     */
+    public function getUri()
+    {
+        $qs = $this->getQueryString();
+        if (null !== $qs) {
+            $qs = '?'.$qs;
+        }
+
+        $auth = '';
+        if ($user = $this->getUser()) {
+            $auth = $user;
+        }
+
+        if ($pass = $this->getPassword()) {
+           $auth .= ":$pass";
+        }
+
+        if ('' !== $auth) {
+           $auth .= '@';
+        }
+
+        return $this->getScheme().'://'.$auth.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs;
+    }
+
+    /**
+     * Generates a normalized URI for the given path.
+     *
+     * @param string $path A path to use instead of the current one
+     *
+     * @return string The normalized URI for the path
+     *
+     * @api
+     */
+    public function getUriForPath($path)
+    {
+        return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$path;
+    }
+
+    /**
+     * Generates the normalized query string for the Request.
+     *
+     * It builds a normalized query string, where keys/value pairs are alphabetized
+     * and have consistent escaping.
+     *
+     * @return string|null A normalized query string for the Request
+     *
+     * @api
+     */
+    public function getQueryString()
+    {
+        if (!$qs = $this->server->get('QUERY_STRING')) {
+            return null;
+        }
+
+        $parts = array();
+        $order = array();
+
+        foreach (explode('&', $qs) as $segment) {
+            if (false === strpos($segment, '=')) {
+                $parts[] = $segment;
+                $order[] = $segment;
+            } else {
+                $tmp = explode('=', rawurldecode($segment), 2);
+                $parts[] = rawurlencode($tmp[0]).'='.rawurlencode($tmp[1]);
+                $order[] = $tmp[0];
+            }
+        }
+        array_multisort($order, SORT_ASC, $parts);
+
+        return implode('&', $parts);
+    }
+
+    /**
+     * Checks whether the request is secure or not.
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isSecure()
+    {
+        return (
+            (strtolower($this->server->get('HTTPS')) == 'on' || $this->server->get('HTTPS') == 1)
+            ||
+            (self::$trustProxy && strtolower($this->headers->get('SSL_HTTPS')) == 'on' || $this->headers->get('SSL_HTTPS') == 1)
+            ||
+            (self::$trustProxy && strtolower($this->headers->get('X_FORWARDED_PROTO')) == 'https')
+        );
+    }
+
+    /**
+     * Returns the host name.
+     *
+     * @return string
+     *
+     * @api
+     */
+    public function getHost()
+    {
+        if (self::$trustProxy && $host = $this->headers->get('X_FORWARDED_HOST')) {
+            $elements = explode(',', $host);
+
+            $host = trim($elements[count($elements) - 1]);
+        } else {
+            if (!$host = $this->headers->get('HOST')) {
+                if (!$host = $this->server->get('SERVER_NAME')) {
+                    $host = $this->server->get('SERVER_ADDR', '');
+                }
+            }
+        }
+
+        // Remove port number from host
+        $host = preg_replace('/:\d+$/', '', $host);
+
+        return trim($host);
+    }
+
+    /**
+     * Sets the request method.
+     *
+     * @param string $method
+     *
+     * @api
+     */
+    public function setMethod($method)
+    {
+        $this->method = null;
+        $this->server->set('REQUEST_METHOD', $method);
+    }
+
+    /**
+     * Gets the request method.
+     *
+     * The method is always an uppercased string.
+     *
+     * @return string The request method
+     *
+     * @api
+     */
+    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', 'POST')));
+            }
+        }
+
+        return $this->method;
+    }
+
+    /**
+     * Gets the mime type associated with the format.
+     *
+     * @param  string $format  The format
+     *
+     * @return string The associated mime type (null if not found)
+     *
+     * @api
+     */
+    public function getMimeType($format)
+    {
+        if (null === static::$formats) {
+            static::initializeFormats();
+        }
+
+        return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
+    }
+
+    /**
+     * Gets the format associated with the mime type.
+     *
+     * @param  string $mimeType  The associated mime type
+     *
+     * @return string The format (null if not found)
+     *
+     * @api
+     */
+    public function getFormat($mimeType)
+    {
+        if (false !== $pos = strpos($mimeType, ';')) {
+            $mimeType = substr($mimeType, 0, $pos);
+        }
+
+        if (null === static::$formats) {
+            static::initializeFormats();
+        }
+
+        foreach (static::$formats as $format => $mimeTypes) {
+            if (in_array($mimeType, (array) $mimeTypes)) {
+                return $format;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Associates a format with mime types.
+     *
+     * @param string       $format     The format
+     * @param string|array $mimeTypes  The associated mime types (the preferred one must be the first as it will be used as the content type)
+     *
+     * @api
+     */
+    public function setFormat($format, $mimeTypes)
+    {
+        if (null === static::$formats) {
+            static::initializeFormats();
+        }
+
+        static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
+    }
+
+    /**
+     * Gets the request format.
+     *
+     * Here is the process to determine the format:
+     *
+     *  * format defined by the user (with setRequestFormat())
+     *  * _format request parameter
+     *  * $default
+     *
+     * @param string  $default     The default format
+     *
+     * @return string The request format
+     *
+     * @api
+     */
+    public function getRequestFormat($default = 'html')
+    {
+        if (null === $this->format) {
+            $this->format = $this->get('_format', $default);
+        }
+
+        return $this->format;
+    }
+
+    /**
+     * Sets the request format.
+     *
+     * @param string $format The request format.
+     *
+     * @api
+     */
+    public function setRequestFormat($format)
+    {
+        $this->format = $format;
+    }
+
+    /**
+     * Gets the format associated with the request.
+     *
+     * @return string The format (null if no content type is present)
+     *
+     * @api
+     */
+    public function getContentType()
+    {
+        return $this->getFormat($this->server->get('CONTENT_TYPE'));
+    }
+
+    /**
+     * Sets the default locale.
+     *
+     * @param string $locale
+     *
+     * @api
+     */
+    public function setDefaultLocale($locale)
+    {
+        $this->setPhpDefaultLocale($this->defaultLocale = $locale);
+    }
+
+    /**
+     * Sets the locale.
+     *
+     * @param string $locale
+     *
+     * @api
+     */
+    public function setLocale($locale)
+    {
+        $this->setPhpDefaultLocale($this->locale = $locale);
+    }
+
+    /**
+     * Get the locale.
+     *
+     * @return string
+     */
+    public function getLocale()
+    {
+        return null === $this->locale ? $this->defaultLocale : $this->locale;
+    }
+
+    /**
+     * Checks whether the method is safe or not.
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isMethodSafe()
+    {
+        return in_array($this->getMethod(), array('GET', 'HEAD'));
+    }
+
+    /**
+     * Returns the request body content.
+     *
+     * @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.
+     */
+    public function getContent($asResource = false)
+    {
+        if (false === $this->content || (true === $asResource && null !== $this->content)) {
+            throw new \LogicException('getContent() can only be called once when using the resource return type.');
+        }
+
+        if (true === $asResource) {
+            $this->content = false;
+
+            return fopen('php://input', 'rb');
+        }
+
+        if (null === $this->content) {
+            $this->content = file_get_contents('php://input');
+        }
+
+        return $this->content;
+    }
+
+    /**
+     * Gets the Etags.
+     *
+     * @return array The entity tags
+     */
+    public function getETags()
+    {
+        return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
+    }
+
+    public function isNoCache()
+    {
+        return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
+    }
+
+    /**
+     * Returns the preferred language.
+     *
+     * @param  array  $locales  An array of ordered available locales
+     *
+     * @return string|null The preferred locale
+     *
+     * @api
+     */
+    public function getPreferredLanguage(array $locales = null)
+    {
+        $preferredLanguages = $this->getLanguages();
+
+        if (empty($locales)) {
+            return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
+        }
+
+        if (!$preferredLanguages) {
+            return $locales[0];
+        }
+
+        $preferredLanguages = array_values(array_intersect($preferredLanguages, $locales));
+
+        return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
+    }
+
+    /**
+     * Gets a list of languages acceptable by the client browser.
+     *
+     * @return array Languages ordered in the user browser preferences
+     *
+     * @api
+     */
+    public function getLanguages()
+    {
+        if (null !== $this->languages) {
+            return $this->languages;
+        }
+
+        $languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language'));
+        $this->languages = array();
+        foreach ($languages as $lang => $q) {
+            if (strstr($lang, '-')) {
+                $codes = explode('-', $lang);
+                if ($codes[0] == 'i') {
+                    // Language not listed in ISO 639 that are not variants
+                    // of any listed language, which can be registered with the
+                    // i-prefix, such as i-cherokee
+                    if (count($codes) > 1) {
+                        $lang = $codes[1];
+                    }
+                } else {
+                    for ($i = 0, $max = count($codes); $i < $max; $i++) {
+                        if ($i == 0) {
+                            $lang = strtolower($codes[0]);
+                        } else {
+                            $lang .= '_'.strtoupper($codes[$i]);
+                        }
+                    }
+                }
+            }
+
+            $this->languages[] = $lang;
+        }
+
+        return $this->languages;
+    }
+
+    /**
+     * Gets a list of charsets acceptable by the client browser.
+     *
+     * @return array List of charsets in preferable order
+     *
+     * @api
+     */
+    public function getCharsets()
+    {
+        if (null !== $this->charsets) {
+            return $this->charsets;
+        }
+
+        return $this->charsets = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept-Charset')));
+    }
+
+    /**
+     * Gets a list of content types acceptable by the client browser
+     *
+     * @return array List of content types in preferable order
+     *
+     * @api
+     */
+    public function getAcceptableContentTypes()
+    {
+        if (null !== $this->acceptableContentTypes) {
+            return $this->acceptableContentTypes;
+        }
+
+        return $this->acceptableContentTypes = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept')));
+    }
+
+    /**
+     * 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.
+     *
+     * @return Boolean true if the request is an XMLHttpRequest, false otherwise
+     *
+     * @api
+     */
+    public function isXmlHttpRequest()
+    {
+        return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
+    }
+
+    /**
+     * Splits an Accept-* HTTP header.
+     *
+     * @param string $header  Header to split
+     *
+     * @return array Array indexed by the values of the Accept-* header in preferred order
+     */
+    public function splitHttpAcceptHeader($header)
+    {
+        if (!$header) {
+            return array();
+        }
+
+        $values = 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     = (float) substr(trim($match[1]), 2);
+                $value = trim(substr($value, 0, -strlen($match[0])));
+            } else {
+                $q = 1;
+            }
+
+            if (0 < $q) {
+                $values[trim($value)] = $q;
+            }
+        }
+
+        arsort($values);
+        reset($values);
+
+        return $values;
+    }
+
+    /*
+     * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
+     *
+     * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd).
+     *
+     * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+     */
+
+    protected function prepareRequestUri()
+    {
+        $requestUri = '';
+
+        if ($this->headers->has('X_REWRITE_URL') && false !== stripos(PHP_OS, 'WIN')) {
+            // check this first so IIS will catch
+            $requestUri = $this->headers->get('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');
+        } 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
+            $schemeAndHttpHost = $this->getScheme().'://'.$this->getHttpHost();
+            if (strpos($requestUri, $schemeAndHttpHost) === 0) {
+                $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
+            }
+        } elseif ($this->server->has('ORIG_PATH_INFO')) {
+            // IIS 5.0, PHP as CGI
+            $requestUri = $this->server->get('ORIG_PATH_INFO');
+            if ($this->server->get('QUERY_STRING')) {
+                $requestUri .= '?'.$this->server->get('QUERY_STRING');
+            }
+        }
+
+        return $requestUri;
+    }
+
+    /**
+     * Prepares the base URL.
+     *
+     * @return string
+     */
+    protected function prepareBaseUrl()
+    {
+        $filename = basename($this->server->get('SCRIPT_FILENAME'));
+
+        if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
+            $baseUrl = $this->server->get('SCRIPT_NAME');
+        } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
+            $baseUrl = $this->server->get('PHP_SELF');
+        } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
+            $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility
+        } else {
+            // Backtrack up the script_filename to find the portion matching
+            // php_self
+            $path    = $this->server->get('PHP_SELF', '');
+            $file    = $this->server->get('SCRIPT_FILENAME', '');
+            $segs    = explode('/', trim($file, '/'));
+            $segs    = array_reverse($segs);
+            $index   = 0;
+            $last    = count($segs);
+            $baseUrl = '';
+            do {
+                $seg     = $segs[$index];
+                $baseUrl = '/'.$seg.$baseUrl;
+                ++$index;
+            } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
+        }
+
+        // Does the baseUrl have anything in common with the request_uri?
+        $requestUri = $this->getRequestUri();
+
+        if ($baseUrl && 0 === strpos($requestUri, $baseUrl)) {
+            // full $baseUrl matches
+            return $baseUrl;
+        }
+
+        if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) {
+            // directory portion of $baseUrl matches
+            return rtrim(dirname($baseUrl), '/');
+        }
+
+        $truncatedRequestUri = $requestUri;
+        if (($pos = strpos($requestUri, '?')) !== false) {
+            $truncatedRequestUri = substr($requestUri, 0, $pos);
+        }
+
+        $basename = basename($baseUrl);
+        if (empty($basename) || !strpos($truncatedRequestUri, $basename)) {
+            // no match whatsoever; set it blank
+            return '';
+        }
+
+        // If using mod_rewrite or ISAPI_Rewrite strip the script filename
+        // out of baseUrl. $pos !== 0 makes sure it is not matching a value
+        // from PATH_INFO or QUERY_STRING
+        if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
+            $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
+        }
+
+        return rtrim($baseUrl, '/');
+    }
+
+    /**
+     * Prepares the base path.
+     *
+     * @return string base path
+     */
+    protected function prepareBasePath()
+    {
+        $filename = basename($this->server->get('SCRIPT_FILENAME'));
+        $baseUrl = $this->getBaseUrl();
+        if (empty($baseUrl)) {
+            return '';
+        }
+
+        if (basename($baseUrl) === $filename) {
+            $basePath = dirname($baseUrl);
+        } else {
+            $basePath = $baseUrl;
+        }
+
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $basePath = str_replace('\\', '/', $basePath);
+        }
+
+        return rtrim($basePath, '/');
+    }
+
+    /**
+     * Prepares the path info.
+     *
+     * @return string path info
+     */
+    protected function preparePathInfo()
+    {
+        $baseUrl = $this->getBaseUrl();
+
+        if (null === ($requestUri = $this->getRequestUri())) {
+            return '/';
+        }
+
+        $pathInfo = '/';
+
+        // Remove the query string from REQUEST_URI
+        if ($pos = strpos($requestUri, '?')) {
+            $requestUri = substr($requestUri, 0, $pos);
+        }
+
+        if ((null !== $baseUrl) && (false === ($pathInfo = substr(urldecode($requestUri), strlen(urldecode($baseUrl)))))) {
+            // If substr() returns false then PATH_INFO is set to an empty string
+            return '/';
+        } elseif (null === $baseUrl) {
+            return $requestUri;
+        }
+
+        return (string) $pathInfo;
+    }
+
+    /**
+     * Initializes HTTP request formats.
+     */
+    static protected function initializeFormats()
+    {
+        static::$formats = array(
+            'html' => array('text/html', 'application/xhtml+xml'),
+            'txt'  => array('text/plain'),
+            'js'   => array('application/javascript', 'application/x-javascript', 'text/javascript'),
+            'css'  => array('text/css'),
+            'json' => array('application/json', 'application/x-json'),
+            'xml'  => array('text/xml', 'application/xml', 'application/x-xml'),
+            'rdf'  => array('application/rdf+xml'),
+            'atom' => array('application/atom+xml'),
+            'rss'  => array('application/rss+xml'),
+        );
+    }
+
+    /**
+     * Sets the default PHP locale.
+     *
+     * @param string $locale
+     */
+    private function setPhpDefaultLocale($locale)
+    {
+        // if either the class Locale doesn't exist, or an exception is thrown when
+        // setting the default locale, the intl module is not installed, and
+        // the call can be ignored:
+        try {
+            if (class_exists('Locale', false)) {
+                \Locale::setDefault($locale);
+            }
+        } catch (\Exception $e) {
+        }
+    }
+}

+ 221 - 0
vendor/Symfony/Component/HttpFoundation/RequestMatcher.php

@@ -0,0 +1,221 @@
+<?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;
+
+/**
+ * RequestMatcher compares a pre-defined set of checks against a Request instance.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class RequestMatcher implements RequestMatcherInterface
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string
+     */
+    private $host;
+
+    /**
+     * @var string
+     */
+    private $methods;
+
+    /**
+     * @var string
+     */
+    private $ip;
+
+    /**
+     * Attributes.
+     *
+     * @var array
+     */
+    private $attributes;
+
+    public function __construct($path = null, $host = null, $methods = null, $ip = null, array $attributes = array())
+    {
+        $this->path = $path;
+        $this->host = $host;
+        $this->methods = $methods;
+        $this->ip = $ip;
+        $this->attributes = $attributes;
+    }
+
+    /**
+     * Adds a check for the URL host name.
+     *
+     * @param string $regexp A Regexp
+     */
+    public function matchHost($regexp)
+    {
+        $this->host = $regexp;
+    }
+
+    /**
+     * Adds a check for the URL path info.
+     *
+     * @param string $regexp A Regexp
+     */
+    public function matchPath($regexp)
+    {
+        $this->path = $regexp;
+    }
+
+    /**
+     * Adds a check for the client IP.
+     *
+     * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
+     */
+    public function matchIp($ip)
+    {
+        $this->ip = $ip;
+    }
+
+    /**
+     * Adds a check for the HTTP method.
+     *
+     * @param string|array $method An HTTP method or an array of HTTP methods
+     */
+    public function matchMethod($method)
+    {
+        $this->methods = array_map('strtoupper', is_array($method) ? $method : array($method));
+    }
+
+    /**
+     * Adds a check for request attribute.
+     *
+     * @param string $key    The request attribute name
+     * @param string $regexp A Regexp
+     */
+    public function matchAttribute($key, $regexp)
+    {
+        $this->attributes[$key] = $regexp;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @api
+     */
+    public function matches(Request $request)
+    {
+        if (null !== $this->methods && !in_array($request->getMethod(), $this->methods)) {
+            return false;
+        }
+
+        foreach ($this->attributes as $key => $pattern) {
+            if (!preg_match('#'.str_replace('#', '\\#', $pattern).'#', $request->attributes->get($key))) {
+                return false;
+            }
+        }
+
+        if (null !== $this->path) {
+            $path = str_replace('#', '\\#', $this->path);
+
+            if (!preg_match('#'.$path.'#', $request->getPathInfo())) {
+                return false;
+            }
+        }
+
+        if (null !== $this->host && !preg_match('#'.str_replace('#', '\\#', $this->host).'#', $request->getHost())) {
+            return false;
+        }
+
+        if (null !== $this->ip && !$this->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 <dsp at php dot net>
+     * @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 (!defined('AF_INET6')) {
+            throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".');
+        }
+
+        list($address, $netmask) = explode('/', $ip, 2);
+
+        $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;
+    }
+}

+ 33 - 0
vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * RequestMatcherInterface is an interface for strategies to match a Request.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+interface RequestMatcherInterface
+{
+    /**
+     * Decides whether the rule(s) implemented by the strategy matches the supplied request.
+     *
+     * @param  Request $request The request to check for a match
+     *
+     * @return Boolean true if the request matches, false otherwise
+     *
+     * @api
+     */
+    function matches(Request $request);
+}

+ 98 - 0
vendor/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php

@@ -0,0 +1,98 @@
+<?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.
+ */
+
+/**
+ * SessionHandlerInterface
+ *
+ * Provides forward compatability with PHP 5.4
+ *
+ * Extensive documentation can be found at php.net, see links:
+ *
+ * @see http://php.net/sessionhandlerinterface
+ * @see http://php.net/session.customhandler
+ * @see http://php.net/session-set-save-handler
+ *
+ * @author Drak <drak@zikula.org>
+ */
+interface SessionHandlerInterface
+{
+    /**
+     * Open session.
+     *
+     * @see http://php.net/sessionhandlerinterface.open
+     *
+     * @param string $savePath    Save path.
+     * @param string $sessionName Session Name.
+     *
+     * @throws \RuntimeException If something goes wrong starting the session.
+     *
+     * @return boolean
+     */
+    function open($savePath, $sessionName);
+
+    /**
+     * Close session.
+     *
+     * @see http://php.net/sessionhandlerinterface.close
+     *
+     * @return boolean
+     */
+    function close();
+
+    /**
+     * Read session.
+     *
+     * @see http://php.net/sessionhandlerinterface.read
+     *
+     * @throws \RuntimeException On fatal error but not "record not found".
+     *
+     * @return string String as stored in persistent storage or empty string in all other cases.
+     */
+    function read($sessionId);
+
+    /**
+     * Commit session to storage.
+     *
+     * @see http://php.net/sessionhandlerinterface.write
+     *
+     * @param string $sessionId Session ID.
+     * @param string $data      Session serialized data to save.
+     *
+     * @return boolean
+     */
+    function write($sessionId, $data);
+
+    /**
+     * Destroys this session.
+     *
+     * @see http://php.net/sessionhandlerinterface.destroy
+     *
+     * @param string $sessionId Session ID.
+     *
+     * @throws \RuntimeException On fatal error.
+     *
+     * @return boolean
+     */
+    function destroy($sessionId);
+
+    /**
+     * Garbage collection for storage.
+     *
+     * @see http://php.net/sessionhandlerinterface.gc
+     *
+     * @param integer $lifetime Max lifetime in seconds to keep sessions stored.
+     *
+     * @throws \RuntimeException On fatal error.
+     *
+     * @return boolean
+     */
+    function gc($lifetime);
+}

+ 1112 - 0
vendor/Symfony/Component/HttpFoundation/Response.php

@@ -0,0 +1,1112 @@
+<?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;
+
+/**
+ * Response represents an HTTP response.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class Response
+{
+    /**
+     * @var \Symfony\Component\HttpFoundation\ResponseHeaderBag
+     */
+    public $headers;
+
+    /**
+     * @var string
+     */
+    protected $content;
+
+    /**
+     * @var string
+     */
+    protected $version;
+
+    /**
+     * @var integer
+     */
+    protected $statusCode;
+
+    /**
+     * @var string
+     */
+    protected $statusText;
+
+    /**
+     * @var string
+     */
+    protected $charset;
+
+    /**
+     * Status codes translation table.
+     *
+     * The list of codes is complete according to the
+     * {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry}
+     * (last updated 2012-02-13).
+     *
+     * Unless otherwise noted, the status code is defined in RFC2616.
+     *
+     * @var array
+     */
+    static public $statusTexts = array(
+        100 => 'Continue',
+        101 => 'Switching Protocols',
+        102 => 'Processing',            // RFC2518
+        200 => 'OK',
+        201 => 'Created',
+        202 => 'Accepted',
+        203 => 'Non-Authoritative Information',
+        204 => 'No Content',
+        205 => 'Reset Content',
+        206 => 'Partial Content',
+        207 => 'Multi-Status',          // RFC4918
+        208 => 'Already Reported',      // RFC5842
+        226 => 'IM Used',               // RFC3229
+        300 => 'Multiple Choices',
+        301 => 'Moved Permanently',
+        302 => 'Found',
+        303 => 'See Other',
+        304 => 'Not Modified',
+        305 => 'Use Proxy',
+        306 => 'Reserved',
+        307 => 'Temporary Redirect',
+        400 => 'Bad Request',
+        401 => 'Unauthorized',
+        402 => 'Payment Required',
+        403 => 'Forbidden',
+        404 => 'Not Found',
+        405 => 'Method Not Allowed',
+        406 => 'Not Acceptable',
+        407 => 'Proxy Authentication Required',
+        408 => 'Request Timeout',
+        409 => 'Conflict',
+        410 => 'Gone',
+        411 => 'Length Required',
+        412 => 'Precondition Failed',
+        413 => 'Request Entity Too Large',
+        414 => 'Request-URI Too Long',
+        415 => 'Unsupported Media Type',
+        416 => 'Requested Range Not Satisfiable',
+        417 => 'Expectation Failed',
+        418 => 'I\'m a teapot',
+        422 => 'Unprocessable Entity',  // RFC4918
+        423 => 'Locked',                // RFC4918
+        424 => 'Failed Dependency',     // RFC4918
+        425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
+        426 => 'Upgrade Required',      // RFC2817
+        428 => 'Precondition Required', // RFC-nottingham-http-new-status-04
+        429 => 'Too Many Requests',     // RFC-nottingham-http-new-status-04
+        431 => 'Request Header Fields Too Large',   // RFC-nottingham-http-new-status-04
+        500 => 'Internal Server Error',
+        501 => 'Not Implemented',
+        502 => 'Bad Gateway',
+        503 => 'Service Unavailable',
+        504 => 'Gateway Timeout',
+        505 => 'HTTP Version Not Supported',
+        506 => 'Variant Also Negotiates (Experimental)', // [RFC2295]
+        507 => 'Insufficient Storage',  // RFC4918
+        508 => 'Loop Detected',         // RFC5842
+        510 => 'Not Extended',          // RFC2774
+        511 => 'Network Authentication Required',   // RFC-nottingham-http-new-status-04
+    );
+
+    /**
+     * Constructor.
+     *
+     * @param string  $content The response content
+     * @param integer $status  The response status code
+     * @param array   $headers An array of response headers
+     *
+     * @api
+     */
+    public function __construct($content = '', $status = 200, $headers = array())
+    {
+        $this->headers = new ResponseHeaderBag($headers);
+        $this->setContent($content);
+        $this->setStatusCode($status);
+        $this->setProtocolVersion('1.0');
+        if (!$this->headers->has('Date')) {
+            $this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
+        }
+    }
+
+    /**
+     * Factory method for chainability
+     *
+     * Example:
+     *
+     *     return Response::create($body, 200)
+     *         ->setSharedMaxAge(300);
+     *
+     * @param string  $content The response content
+     * @param integer $status  The response status code
+     * @param array   $headers An array of response headers
+     *
+     * @return Response
+     */
+    static public function create($content = '', $status = 200, $headers = array())
+    {
+        return new static($content, $status, $headers);
+    }
+
+    /**
+     * Returns the Response as an HTTP string.
+     *
+     * The string representation of the Resonse is the same as the
+     * one that will be sent to the client only if the prepare() method
+     * has been called before.
+     *
+     * @return string The Response as an HTTP string
+     *
+     * @see prepare()
+     */
+    public function __toString()
+    {
+        return
+            sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n".
+            $this->headers."\r\n".
+            $this->getContent();
+    }
+
+    /**
+     * Clones the current Response instance.
+     */
+    public function __clone()
+    {
+        $this->headers = clone $this->headers;
+    }
+
+    /**
+     * Prepares the Response before it is sent to the client.
+     *
+     * This method tweaks the Response to ensure that it is
+     * compliant with RFC 2616. Most of the changes are based on
+     * the Request that is "associated" with this Response.
+     *
+     * @param Request $request A Request instance
+     */
+    public function prepare(Request $request)
+    {
+        $headers = $this->headers;
+
+        if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) {
+            $this->setContent('');
+        }
+
+        // Content-type based on the Request
+        if (!$headers->has('Content-Type')) {
+            $format = $request->getRequestFormat();
+            if (null !== $format && $mimeType = $request->getMimeType($format)) {
+                $headers->set('Content-Type', $mimeType);
+            }
+        }
+
+        // Fix Content-Type
+        $charset = $this->charset ?: 'UTF-8';
+        if (!$headers->has('Content-Type')) {
+            $headers->set('Content-Type', 'text/html; charset='.$charset);
+        } elseif (0 === strpos($headers->get('Content-Type'), 'text/') && false === strpos($headers->get('Content-Type'), 'charset')) {
+            // add the charset
+            $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
+        }
+
+        // Fix Content-Length
+        if ($headers->has('Transfer-Encoding')) {
+            $headers->remove('Content-Length');
+        }
+
+        if ('HEAD' === $request->getMethod()) {
+            // cf. RFC2616 14.13
+            $length = $headers->get('Content-Length');
+            $this->setContent('');
+            if ($length) {
+                $headers->set('Content-Length', $length);
+            }
+        }
+    }
+
+    /**
+     * Sends HTTP headers.
+     *
+     * @return Response
+     */
+    public function sendHeaders()
+    {
+        // headers have already been sent by the developer
+        if (headers_sent()) {
+            return $this;
+        }
+
+        // status
+        header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText));
+
+        // headers
+        foreach ($this->headers->all() as $name => $values) {
+            foreach ($values as $value) {
+                header($name.': '.$value, false);
+            }
+        }
+
+        // cookies
+        foreach ($this->headers->getCookies() as $cookie) {
+            setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sends content for the current web response.
+     *
+     * @return Response
+     */
+    public function sendContent()
+    {
+        echo $this->content;
+
+        return $this;
+    }
+
+    /**
+     * Sends HTTP headers and content.
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function send()
+    {
+        $this->sendHeaders();
+        $this->sendContent();
+
+        if (function_exists('fastcgi_finish_request')) {
+            fastcgi_finish_request();
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets the response content.
+     *
+     * Valid types are strings, numbers, and objects that implement a __toString() method.
+     *
+     * @param mixed $content
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setContent($content)
+    {
+        if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
+            throw new \UnexpectedValueException('The Response content must be a string or object implementing __toString(), "'.gettype($content).'" given.');
+        }
+
+        $this->content = (string) $content;
+
+        return $this;
+    }
+
+    /**
+     * Gets the current response content.
+     *
+     * @return string Content
+     *
+     * @api
+     */
+    public function getContent()
+    {
+        return $this->content;
+    }
+
+    /**
+     * Sets the HTTP protocol version (1.0 or 1.1).
+     *
+     * @param string $version The HTTP protocol version
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setProtocolVersion($version)
+    {
+        $this->version = $version;
+
+        return $this;
+    }
+
+    /**
+     * Gets the HTTP protocol version.
+     *
+     * @return string The HTTP protocol version
+     *
+     * @api
+     */
+    public function getProtocolVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * Sets the response status code.
+     *
+     * @param integer $code HTTP status code
+     * @param string  $text HTTP status text
+     *
+     * @return Response
+     *
+     * @throws \InvalidArgumentException When the HTTP status code is not valid
+     *
+     * @api
+     */
+    public function setStatusCode($code, $text = null)
+    {
+        $this->statusCode = (int) $code;
+        if ($this->isInvalid()) {
+            throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
+        }
+
+        $this->statusText = false === $text ? '' : (null === $text ? self::$statusTexts[$this->statusCode] : $text);
+
+        return $this;
+    }
+
+    /**
+     * Retrieves the status code for the current web response.
+     *
+     * @return string Status code
+     *
+     * @api
+     */
+    public function getStatusCode()
+    {
+        return $this->statusCode;
+    }
+
+    /**
+     * Sets the response charset.
+     *
+     * @param string $charset Character set
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setCharset($charset)
+    {
+        $this->charset = $charset;
+
+        return $this;
+    }
+
+    /**
+     * Retrieves the response charset.
+     *
+     * @return string Character set
+     *
+     * @api
+     */
+    public function getCharset()
+    {
+        return $this->charset;
+    }
+
+    /**
+     * Returns true if the response is worth caching under any circumstance.
+     *
+     * Responses marked "private" with an explicit Cache-Control directive are
+     * considered uncacheable.
+     *
+     * Responses with neither a freshness lifetime (Expires, max-age) nor cache
+     * validator (Last-Modified, ETag) are considered uncacheable.
+     *
+     * @return Boolean true if the response is worth caching, false otherwise
+     *
+     * @api
+     */
+    public function isCacheable()
+    {
+        if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) {
+            return false;
+        }
+
+        if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
+            return false;
+        }
+
+        return $this->isValidateable() || $this->isFresh();
+    }
+
+    /**
+     * Returns true if the response is "fresh".
+     *
+     * 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.
+     *
+     * @return Boolean true if the response is fresh, false otherwise
+     *
+     * @api
+     */
+    public function isFresh()
+    {
+        return $this->getTtl() > 0;
+    }
+
+    /**
+     * Returns true if the response includes headers that can be used to validate
+     * the response with the origin server using a conditional GET request.
+     *
+     * @return Boolean true if the response is validateable, false otherwise
+     *
+     * @api
+     */
+    public function isValidateable()
+    {
+        return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
+    }
+
+    /**
+     * Marks the response as "private".
+     *
+     * It makes the response ineligible for serving other clients.
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setPrivate()
+    {
+        $this->headers->removeCacheControlDirective('public');
+        $this->headers->addCacheControlDirective('private');
+
+        return $this;
+    }
+
+    /**
+     * Marks the response as "public".
+     *
+     * It makes the response eligible for serving other clients.
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setPublic()
+    {
+        $this->headers->addCacheControlDirective('public');
+        $this->headers->removeCacheControlDirective('private');
+
+        return $this;
+    }
+
+    /**
+     * Returns true if the response must be revalidated by caches.
+     *
+     * This method indicates that the response must not be served stale by a
+     * cache in any circumstance without first revalidating with the origin.
+     * When present, the TTL of the response should not be overridden to be
+     * greater than the value provided by the origin.
+     *
+     * @return Boolean true if the response must be revalidated by a cache, false otherwise
+     *
+     * @api
+     */
+    public function mustRevalidate()
+    {
+        return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('must-proxy-revalidate');
+    }
+
+    /**
+     * Returns the Date header as a DateTime instance.
+     *
+     * @return \DateTime A \DateTime instance
+     *
+     * @throws \RuntimeException When the header is not parseable
+     *
+     * @api
+     */
+    public function getDate()
+    {
+        return $this->headers->getDate('Date');
+    }
+
+    /**
+     * Sets the Date header.
+     *
+     * @param \DateTime $date A \DateTime instance
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setDate(\DateTime $date)
+    {
+        $date->setTimezone(new \DateTimeZone('UTC'));
+        $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT');
+
+        return $this;
+    }
+
+    /**
+     * Returns the age of the response.
+     *
+     * @return integer The age of the response in seconds
+     */
+    public function getAge()
+    {
+        if ($age = $this->headers->get('Age')) {
+            return $age;
+        }
+
+        return max(time() - $this->getDate()->format('U'), 0);
+    }
+
+    /**
+     * Marks the response stale by setting the Age header to be equal to the maximum age of the response.
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function expire()
+    {
+        if ($this->isFresh()) {
+            $this->headers->set('Age', $this->getMaxAge());
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the value of the Expires header as a DateTime instance.
+     *
+     * @return \DateTime A DateTime instance
+     *
+     * @api
+     */
+    public function getExpires()
+    {
+        return $this->headers->getDate('Expires');
+    }
+
+    /**
+     * Sets the Expires HTTP header with a DateTime instance.
+     *
+     * If passed a null value, it removes the header.
+     *
+     * @param \DateTime $date A \DateTime instance
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setExpires(\DateTime $date = null)
+    {
+        if (null === $date) {
+            $this->headers->remove('Expires');
+        } else {
+            $date = clone $date;
+            $date->setTimezone(new \DateTimeZone('UTC'));
+            $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets 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
+     * back on an expires header. It returns null when no maximum age can be established.
+     *
+     * @return integer|null Number of seconds
+     *
+     * @api
+     */
+    public function getMaxAge()
+    {
+        if ($age = $this->headers->getCacheControlDirective('s-maxage')) {
+            return $age;
+        }
+
+        if ($age = $this->headers->getCacheControlDirective('max-age')) {
+            return $age;
+        }
+
+        if (null !== $this->getExpires()) {
+            return $this->getExpires()->format('U') - $this->getDate()->format('U');
+        }
+
+        return null;
+    }
+
+    /**
+     * Sets the number of seconds after which the response should no longer be considered fresh.
+     *
+     * This methods sets the Cache-Control max-age directive.
+     *
+     * @param integer $value Number of seconds
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setMaxAge($value)
+    {
+        $this->headers->addCacheControlDirective('max-age', $value);
+
+        return $this;
+    }
+
+    /**
+     * Sets the number of seconds after which the response should no longer be considered fresh by shared caches.
+     *
+     * This methods sets the Cache-Control s-maxage directive.
+     *
+     * @param integer $value Number of seconds
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setSharedMaxAge($value)
+    {
+        $this->setPublic();
+        $this->headers->addCacheControlDirective('s-maxage', $value);
+
+        return $this;
+    }
+
+    /**
+     * Returns the response's time-to-live in seconds.
+     *
+     * It returns null when no freshness information is present in the response.
+     *
+     * When the responses TTL is <= 0, the response may not be served from cache without first
+     * revalidating with the origin.
+     *
+     * @return integer The TTL in seconds
+     *
+     * @api
+     */
+    public function getTtl()
+    {
+        if ($maxAge = $this->getMaxAge()) {
+            return $maxAge - $this->getAge();
+        }
+
+        return null;
+    }
+
+    /**
+     * Sets the response's time-to-live for shared caches.
+     *
+     * This method adjusts the Cache-Control/s-maxage directive.
+     *
+     * @param integer $seconds Number of seconds
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setTtl($seconds)
+    {
+        $this->setSharedMaxAge($this->getAge() + $seconds);
+
+        return $this;
+    }
+
+    /**
+     * Sets the response's time-to-live for private/client caches.
+     *
+     * This method adjusts the Cache-Control/max-age directive.
+     *
+     * @param integer $seconds Number of seconds
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setClientTtl($seconds)
+    {
+        $this->setMaxAge($this->getAge() + $seconds);
+
+        return $this;
+    }
+
+    /**
+     * Returns the Last-Modified HTTP header as a DateTime instance.
+     *
+     * @return \DateTime A DateTime instance
+     *
+     * @api
+     */
+    public function getLastModified()
+    {
+        return $this->headers->getDate('Last-Modified');
+    }
+
+    /**
+     * Sets the Last-Modified HTTP header with a DateTime instance.
+     *
+     * If passed a null value, it removes the header.
+     *
+     * @param \DateTime $date A \DateTime instance
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setLastModified(\DateTime $date = null)
+    {
+        if (null === $date) {
+            $this->headers->remove('Last-Modified');
+        } else {
+            $date = clone $date;
+            $date->setTimezone(new \DateTimeZone('UTC'));
+            $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the literal value of the ETag HTTP header.
+     *
+     * @return string The ETag HTTP header
+     *
+     * @api
+     */
+    public function getEtag()
+    {
+        return $this->headers->get('ETag');
+    }
+
+    /**
+     * Sets the ETag value.
+     *
+     * @param string  $etag The ETag unique identifier
+     * @param Boolean $weak Whether you want a weak ETag or not
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setEtag($etag = null, $weak = false)
+    {
+        if (null === $etag) {
+            $this->headers->remove('Etag');
+        } else {
+            if (0 !== strpos($etag, '"')) {
+                $etag = '"'.$etag.'"';
+            }
+
+            $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets the response's cache headers (validation and/or expiration).
+     *
+     * Available options are: etag, last_modified, max_age, s_maxage, private, and public.
+     *
+     * @param array $options An array of cache options
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setCache(array $options)
+    {
+        if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) {
+            throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff))));
+        }
+
+        if (isset($options['etag'])) {
+            $this->setEtag($options['etag']);
+        }
+
+        if (isset($options['last_modified'])) {
+            $this->setLastModified($options['last_modified']);
+        }
+
+        if (isset($options['max_age'])) {
+            $this->setMaxAge($options['max_age']);
+        }
+
+        if (isset($options['s_maxage'])) {
+            $this->setSharedMaxAge($options['s_maxage']);
+        }
+
+        if (isset($options['public'])) {
+            if ($options['public']) {
+                $this->setPublic();
+            } else {
+                $this->setPrivate();
+            }
+        }
+
+        if (isset($options['private'])) {
+            if ($options['private']) {
+                $this->setPrivate();
+            } else {
+                $this->setPublic();
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Modifies the response so that it conforms to the rules defined for a 304 status code.
+     *
+     * This sets the status, removes the body, and discards any headers
+     * that MUST NOT be included in 304 responses.
+     *
+     * @return Response
+     *
+     * @see http://tools.ietf.org/html/rfc2616#section-10.3.5
+     *
+     * @api
+     */
+    public function setNotModified()
+    {
+        $this->setStatusCode(304);
+        $this->setContent(null);
+
+        // remove headers that MUST NOT be included with 304 Not Modified responses
+        foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
+            $this->headers->remove($header);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns true if the response includes a Vary header.
+     *
+     * @return Boolean true if the response includes a Vary header, false otherwise
+     *
+     * @api
+     */
+    public function hasVary()
+    {
+        return (Boolean) $this->headers->get('Vary');
+    }
+
+    /**
+     * Returns an array of header names given in the Vary header.
+     *
+     * @return array An array of Vary names
+     *
+     * @api
+     */
+    public function getVary()
+    {
+        if (!$vary = $this->headers->get('Vary')) {
+            return array();
+        }
+
+        return is_array($vary) ? $vary : preg_split('/[\s,]+/', $vary);
+    }
+
+    /**
+     * Sets the Vary header.
+     *
+     * @param string|array $headers
+     * @param Boolean      $replace Whether to replace the actual value of not (true by default)
+     *
+     * @return Response
+     *
+     * @api
+     */
+    public function setVary($headers, $replace = true)
+    {
+        $this->headers->set('Vary', $headers, $replace);
+
+        return $this;
+    }
+
+    /**
+     * Determines if the Response validators (ETag, Last-Modified) match
+     * a conditional value specified in the Request.
+     *
+     * If the Response is not modified, it sets the status code to 304 and
+     * removes the actual content by calling the setNotModified() method.
+     *
+     * @param Request $request A Request instance
+     *
+     * @return Boolean true if the Response validators match the Request, false otherwise
+     *
+     * @api
+     */
+    public function isNotModified(Request $request)
+    {
+        $lastModified = $request->headers->get('If-Modified-Since');
+        $notModified = false;
+        if ($etags = $request->getEtags()) {
+            $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified);
+        } elseif ($lastModified) {
+            $notModified = $lastModified == $this->headers->get('Last-Modified');
+        }
+
+        if ($notModified) {
+            $this->setNotModified();
+        }
+
+        return $notModified;
+    }
+
+    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+    /**
+     * Is response invalid?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isInvalid()
+    {
+        return $this->statusCode < 100 || $this->statusCode >= 600;
+    }
+
+    /**
+     * Is response informative?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isInformational()
+    {
+        return $this->statusCode >= 100 && $this->statusCode < 200;
+    }
+
+    /**
+     * Is response successful?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isSuccessful()
+    {
+        return $this->statusCode >= 200 && $this->statusCode < 300;
+    }
+
+    /**
+     * Is the response a redirect?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isRedirection()
+    {
+        return $this->statusCode >= 300 && $this->statusCode < 400;
+    }
+
+    /**
+     * Is there a client error?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isClientError()
+    {
+        return $this->statusCode >= 400 && $this->statusCode < 500;
+    }
+
+    /**
+     * Was there a server side error?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isServerError()
+    {
+        return $this->statusCode >= 500 && $this->statusCode < 600;
+    }
+
+    /**
+     * Is the response OK?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isOk()
+    {
+        return 200 === $this->statusCode;
+    }
+
+    /**
+     * Is the reponse forbidden?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isForbidden()
+    {
+        return 403 === $this->statusCode;
+    }
+
+    /**
+     * Is the response a not found error?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isNotFound()
+    {
+        return 404 === $this->statusCode;
+    }
+
+    /**
+     * Is the response a redirect of some form?
+     *
+     * @param string $location
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isRedirect($location = null)
+    {
+        return in_array($this->statusCode, array(201, 301, 302, 303, 307)) && (null === $location ?: $location == $this->headers->get('Location'));
+    }
+
+    /**
+     * Is the response empty?
+     *
+     * @return Boolean
+     *
+     * @api
+     */
+    public function isEmpty()
+    {
+        return in_array($this->statusCode, array(201, 204, 304));
+    }
+}

+ 293 - 0
vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php

@@ -0,0 +1,293 @@
+<?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();
+
+    /**
+     * 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";
+        }
+
+        return parent::__toString().$cookies;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @api
+     */
+    public function replace(array $headers = 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);
+
+        // ensure the cache-control header has sensible defaults
+        if (in_array(strtr(strtolower($key), '_', '-'), array('cache-control', 'etag', 'last-modified', 'expires'))) {
+            $computed = $this->computeCacheControlValue();
+            $this->headers['cache-control'] = array($computed);
+            $this->computedCacheControl = $this->parseCacheControl($computed);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @api
+     */
+    public function remove($key)
+    {
+        parent::remove($key);
+
+        if ('cache-control' === strtr(strtolower($key), '_', '-')) {
+            $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 (preg_match('#[/\\\\]#', $filename) || preg_match('#[/\\\\]#', $filenameFallback)) {
+            throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
+        }
+
+        $output = sprintf('%s; filename="%s"', $disposition, str_replace(array('\\', '"'), array('\\\\', '\\"'), $filenameFallback));
+
+        if ($filename != $filenameFallback) {
+            $output .= sprintf("; filename*=utf-8''%s", str_replace(array("'", '(', ')', '*'), array('%27', '%28', '%29', '%2A'), urlencode($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;
+    }
+}

+ 48 - 0
vendor/Symfony/Component/HttpFoundation/ServerBag.php

@@ -0,0 +1,48 @@
+<?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;
+
+/**
+ * ServerBag is a container for HTTP headers from the $_SERVER variable.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ */
+class ServerBag extends ParameterBag
+{
+    /**
+     * Gets the HTTP headers.
+     *
+     * @return string
+     */
+    public function getHeaders()
+    {
+        $headers = array();
+        foreach ($this->parameters as $key => $value) {
+            if (0 === strpos($key, 'HTTP_')) {
+                $headers[substr($key, 5)] = $value;
+            }
+            // CONTENT_* are not prefixed with HTTP_
+            elseif (in_array($key, array('CONTENT_LENGTH', 'CONTENT_MD5', 'CONTENT_TYPE'))) {
+                $headers[$key] = $this->parameters[$key];
+            }
+        }
+
+        // PHP_AUTH_USER/PHP_AUTH_PW
+        if (isset($this->parameters['PHP_AUTH_USER'])) {
+            $pass = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : '';
+            $headers['AUTHORIZATION'] = 'Basic '.base64_encode($this->parameters['PHP_AUTH_USER'].':'.$pass);
+        }
+
+        return $headers;
+    }
+}

+ 137 - 0
vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php

@@ -0,0 +1,137 @@
+<?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\Session\Attribute;
+
+/**
+ * This class relates to session attribute storage
+ */
+class AttributeBag implements AttributeBagInterface
+{
+    private $name = 'attributes';
+
+    /**
+     * @var string
+     */
+    private $storageKey;
+
+    /**
+     * @var array
+     */
+    protected $attributes = array();
+
+    /**
+     * Constructor.
+     *
+     * @param string $storageKey The key used to store flashes in the session.
+     */
+    public function __construct($storageKey = '_sf2_attributes')
+    {
+        $this->storageKey = $storageKey;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function initialize(array &$attributes)
+    {
+        $this->attributes = &$attributes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStorageKey()
+    {
+        return $this->storageKey;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($name)
+    {
+        return array_key_exists($name, $this->attributes);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($name, $default = null)
+    {
+        return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function set($name, $value)
+    {
+        $this->attributes[$name] = $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function all()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function replace(array $attributes)
+    {
+        $this->attributes = array();
+        foreach ($attributes as $key => $value) {
+            $this->set($key, $value);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($name)
+    {
+        $retval = null;
+        if (array_key_exists($name, $this->attributes)) {
+            $retval = $this->attributes[$name];
+            unset($this->attributes[$name]);
+        }
+
+        return $retval;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        $return = $this->attributes;
+        $this->attributes = array();
+
+        return $return;
+    }
+}

+ 72 - 0
vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php

@@ -0,0 +1,72 @@
+<?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\Session\Attribute;
+
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+
+/**
+ * Attributes store.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+interface AttributeBagInterface extends SessionBagInterface
+{
+    /**
+     * Checks if an attribute is defined.
+     *
+     * @param string $name The attribute name
+     *
+     * @return Boolean true if the attribute is defined, false otherwise
+     */
+    function has($name);
+
+    /**
+     * Returns an attribute.
+     *
+     * @param string $name    The attribute name
+     * @param mixed  $default The default value if not found.
+     *
+     * @return mixed
+     */
+    function get($name, $default = null);
+
+    /**
+     * Sets an attribute.
+     *
+     * @param string $name
+     * @param mixed  $value
+     */
+    function set($name, $value);
+
+    /**
+     * Returns attributes.
+     *
+     * @return array Attributes
+     */
+    function all();
+
+    /**
+     * Sets attributes.
+     *
+     * @param array $attributes Attributes
+     */
+    function replace(array $attributes);
+
+    /**
+     * Removes an attribute.
+     *
+     * @param string $name
+     *
+     * @return mixed The removed value
+     */
+    function remove($name);
+}

+ 154 - 0
vendor/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php

@@ -0,0 +1,154 @@
+<?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\Session\Attribute;
+
+/**
+ * This class provides structured storage of session attributes using
+ * a name spacing character in the key.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NamespacedAttributeBag extends AttributeBag
+{
+    /**
+     * Namespace character.
+     *
+     * @var string
+     */
+    private $namespaceCharacter;
+
+    /**
+     * Constructor.
+     *
+     * @param string $storageKey         Session storage key.
+     * @param string $namespaceCharacter Namespace character to use in keys.
+     */
+    public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/')
+    {
+        $this->namespaceCharacter = $namespaceCharacter;
+        parent::__construct($storageKey);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($name)
+    {
+        $attributes = $this->resolveAttributePath($name);
+        $name = $this->resolveKey($name);
+
+        return array_key_exists($name, $attributes);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($name, $default = null)
+    {
+        $attributes = $this->resolveAttributePath($name);
+        $name = $this->resolveKey($name);
+
+        return array_key_exists($name, $attributes) ? $attributes[$name] : $default;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function set($name, $value)
+    {
+        $attributes = & $this->resolveAttributePath($name, true);
+        $name = $this->resolveKey($name);
+        $attributes[$name] = $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($name)
+    {
+        $retval = null;
+        $attributes = & $this->resolveAttributePath($name);
+        $name = $this->resolveKey($name);
+        if (array_key_exists($name, $attributes)) {
+            $retval = $attributes[$name];
+            unset($attributes[$name]);
+        }
+
+        return $retval;
+    }
+
+    /**
+     * Resolves a path in attributes property and returns it as a reference.
+     *
+     * This method allows structured namespacing of session attributes.
+     *
+     * @param string  $name         Key name
+     * @param boolean $writeContext Write context, default false
+     *
+     * @return array
+     */
+    protected function &resolveAttributePath($name, $writeContext = false)
+    {
+        $array = & $this->attributes;
+        $name = (strpos($name, $this->namespaceCharacter) === 0) ? substr($name, 1) : $name;
+
+        // Check if there is anything to do, else return
+        if (!$name) {
+            return $array;
+        }
+
+        $parts = explode($this->namespaceCharacter, $name);
+        if (count($parts) < 2) {
+            if (!$writeContext) {
+                return $array;
+            }
+
+            $array[$parts[0]] = array();
+
+            return $array;
+        }
+
+        unset($parts[count($parts)-1]);
+
+        foreach ($parts as $part) {
+            if (!array_key_exists($part, $array)) {
+                if (!$writeContext) {
+                    return $array;
+                }
+
+                $array[$part] = array();
+            }
+
+            $array = & $array[$part];
+        }
+
+        return $array;
+    }
+
+    /**
+     * Resolves the key from the name.
+     *
+     * This is the last part in a dot separated string.
+     *
+     * @param string $name
+     *
+     * @return string
+     */
+    protected function resolveKey($name)
+    {
+        if (strpos($name, $this->namespaceCharacter) !== false) {
+            $name = substr($name, strrpos($name, $this->namespaceCharacter)+1, strlen($name));
+        }
+
+        return $name;
+    }
+}

+ 171 - 0
vendor/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php

@@ -0,0 +1,171 @@
+<?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\Session\Flash;
+
+/**
+ * AutoExpireFlashBag flash message container.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class AutoExpireFlashBag implements FlashBagInterface
+{
+    private $name = 'flashes';
+
+    /**
+     * Flash messages.
+     *
+     * @var array
+     */
+    private $flashes = array();
+
+    /**
+     * The storage key for flashes in the session
+     *
+     * @var string
+     */
+    private $storageKey;
+
+    /**
+     * Constructor.
+     *
+     * @param string $storageKey The key used to store flashes in the session.
+     */
+    public function __construct($storageKey = '_sf2_flashes')
+    {
+        $this->storageKey = $storageKey;
+        $this->flashes = array('display' => array(), 'new' => array());
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function initialize(array &$flashes)
+    {
+        $this->flashes = &$flashes;
+
+        // The logic: messages from the last request will be stored in new, so we move them to previous
+        // This request we will show what is in 'display'.  What is placed into 'new' this time round will
+        // be moved to display next time round.
+        $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array();
+        $this->flashes['new'] = array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function peek($type, $default = null)
+    {
+        return $this->has($type) ? $this->flashes['display'][$type] : $default;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function peekAll()
+    {
+        return array_key_exists('display', $this->flashes) ? (array)$this->flashes['display'] : array();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($type, $default = null)
+    {
+        $return = $default;
+
+        if (!$this->has($type)) {
+            return $return;
+        }
+
+        if (isset($this->flashes['display'][$type])) {
+            $return = $this->flashes['display'][$type];
+            unset($this->flashes['display'][$type]);
+        }
+
+        return $return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function all()
+    {
+        $return = $this->flashes['display'];
+        $this->flashes = array('new' => array(), 'display' => array());
+
+        return $return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setAll(array $messages)
+    {
+        $this->flashes['new'] = $messages;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function set($type, $message)
+    {
+        $this->flashes['new'][$type] = $message;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($type)
+    {
+        return array_key_exists($type, $this->flashes['display']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function keys()
+    {
+        return array_keys($this->flashes['display']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStorageKey()
+    {
+        return $this->storageKey;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        $return = $this->all();
+        $this->flashes = array('display' => array(), 'new' => array());
+
+        return $return;
+    }
+}

+ 158 - 0
vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php

@@ -0,0 +1,158 @@
+<?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\Session\Flash;
+
+/**
+ * FlashBag flash message container.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class FlashBag implements FlashBagInterface
+{
+    private $name = 'flashes';
+
+    /**
+     * Flash messages.
+     *
+     * @var array
+     */
+    private $flashes = array();
+
+    /**
+     * The storage key for flashes in the session
+     *
+     * @var string
+     */
+    private $storageKey;
+
+    /**
+     * Constructor.
+     *
+     * @param string $storageKey The key used to store flashes in the session.
+     */
+    public function __construct($storageKey = '_sf2_flashes')
+    {
+        $this->storageKey = $storageKey;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function initialize(array &$flashes)
+    {
+        $this->flashes = &$flashes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function peek($type, $default = null)
+    {
+        return $this->has($type) ? $this->flashes[$type] : $default;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function peekAll()
+    {
+        return $this->flashes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($type, $default = null)
+    {
+        if (!$this->has($type)) {
+            return $default;
+        }
+
+        $return = $this->flashes[$type];
+
+        unset($this->flashes[$type]);
+
+        return $return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function all()
+    {
+        $return = $this->peekAll();
+        $this->flashes = array();
+
+        return $return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function set($type, $message)
+    {
+        $this->flashes[$type] = $message;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setAll(array $messages)
+    {
+        $this->flashes = $messages;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($type)
+    {
+        return array_key_exists($type, $this->flashes);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function keys()
+    {
+        return array_keys($this->flashes);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStorageKey()
+    {
+        return $this->storageKey;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        return $this->all();
+    }
+}

+ 85 - 0
vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php

@@ -0,0 +1,85 @@
+<?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\Session\Flash;
+
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+
+/**
+ * FlashBagInterface.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+interface FlashBagInterface extends SessionBagInterface
+{
+    /**
+     * Registers a message for a given type.
+     *
+     * @param string $type
+     * @param string $message
+     */
+    function set($type, $message);
+
+    /**
+     * Gets flash message for a given type.
+     *
+     * @param string $type    Message category type.
+     * @param string $default Default value if $type doee not exist.
+     *
+     * @return string
+     */
+    function peek($type, $default = null);
+
+    /**
+     * Gets all flash messages.
+     *
+     * @return array
+     */
+    function peekAll();
+
+    /**
+     * Gets and clears flash from the stack.
+     *
+     * @param string $type
+     * @param string $default Default value if $type doee not exist.
+     *
+     * @return string
+     */
+    function get($type, $default = null);
+
+    /**
+     * Gets and clears flashes from the stack.
+     *
+     * @return array
+     */
+    function all();
+
+    /**
+     * Sets all flash messages.
+     */
+    function setAll(array $messages);
+
+    /**
+     * Has flash messages for a given type?
+     *
+     * @param string $type
+     *
+     * @return boolean
+     */
+    function has($type);
+
+    /**
+     * Returns a list of all defined types.
+     *
+     * @return array
+     */
+    function keys();
+}

+ 300 - 0
vendor/Symfony/Component/HttpFoundation/Session/Session.php

@@ -0,0 +1,300 @@
+<?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\Session;
+
+use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
+use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
+use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+
+/**
+ * Session.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Drak <drak@zikula.org>
+ *
+ * @api
+ */
+class Session implements SessionInterface
+{
+    /**
+     * Storage driver.
+     *
+     * @var SessionStorageInterface
+     */
+    protected $storage;
+
+    /**
+     * @var string
+     */
+    private $flashName;
+
+    /**
+     * @var string
+     */
+    private $attributeName;
+
+    /**
+     * Constructor.
+     *
+     * @param SessionStorageInterface $storage    A SessionStorageInterface instance.
+     * @param AttributeBagInterface   $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
+     * @param FlashBagInterface       $flashes    A FlashBagInterface instance (defaults null for default FlashBag)
+     */
+    public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
+    {
+        $this->storage = $storage ?: new NativeSessionStorage();
+
+        $attributeBag = $attributes ?: new AttributeBag();
+        $this->attributeName = $attributeBag->getName();
+        $this->registerBag($attributeBag);
+
+        $flashBag = $flashes ?: new FlashBag();
+        $this->flashName = $flashBag->getName();
+        $this->registerBag($flashBag);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        return $this->storage->start();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($name)
+    {
+        return $this->storage->getBag($this->attributeName)->has($name);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($name, $default = null)
+    {
+        return $this->storage->getBag($this->attributeName)->get($name, $default);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function set($name, $value)
+    {
+        $this->storage->getBag($this->attributeName)->set($name, $value);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function all()
+    {
+        return $this->storage->getBag($this->attributeName)->all();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function replace(array $attributes)
+    {
+        $this->storage->getBag($this->attributeName)->replace($attributes);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($name)
+    {
+        return $this->storage->getBag($this->attributeName)->remove($name);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        $this->storage->getBag($this->attributeName)->clear();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function invalidate()
+    {
+        $this->storage->clear();
+
+        return $this->storage->regenerate(true);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function migrate($destroy = false)
+    {
+        return $this->storage->regenerate($destroy);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        $this->storage->save();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getId()
+    {
+        return $this->storage->getId();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setId($id)
+    {
+        $this->storage->setId($id);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->storage->getName();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setName($name)
+    {
+        $this->storage->setName($name);
+    }
+
+    /**
+     * Registers a SessionBagInterface with the session.
+     *
+     * @param SessionBagInterface $bag
+     */
+    public function registerBag(SessionBagInterface $bag)
+    {
+        $this->storage->registerBag($bag);
+    }
+
+    /**
+     * Get's a bag instance.
+     *
+     * @param string $name
+     *
+     * @return SessionBagInterface
+     */
+    public function getBag($name)
+    {
+        return $this->storage->getBag($name);
+    }
+
+    /**
+     * Gets the flashbag interface.
+     *
+     * @return FlashBagInterface
+     */
+    public function getFlashBag()
+    {
+        return $this->getBag($this->flashName);
+    }
+
+    // the following methods are kept for compatibility with Symfony 2.0 (they will be removed for Symfony 2.3)
+
+    /**
+     * @return array
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function getFlashes()
+    {
+        return $this->getBag('flashes')->all();
+    }
+
+    /**
+     * @param array $values
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function setFlashes($values)
+    {
+       $this->getBag('flashes')->setAll($values);
+    }
+
+    /**
+     * @param string $name
+     * @param string $default
+     *
+     * @return string
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function getFlash($name, $default = null)
+    {
+       return $this->getBag('flashes')->get($name, $default);
+    }
+
+    /**
+     * @param string $name
+     * @param string $value
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function setFlash($name, $value)
+    {
+       $this->getBag('flashes')->set($name, $value);
+    }
+
+    /**
+     * @param string $name
+     *
+     * @return Boolean
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function hasFlash($name)
+    {
+       return $this->getBag('flashes')->has($name);
+    }
+
+    /**
+     * @param string $name
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function removeFlash($name)
+    {
+       $this->getBag('flashes')->get($name);
+    }
+
+    /**
+     * @return array
+     *
+     * @deprecated since 2.1, will be removed from 2.3
+     */
+    public function clearFlashes()
+    {
+       return $this->getBag('flashes')->clear();
+    }
+}

+ 48 - 0
vendor/Symfony/Component/HttpFoundation/Session/SessionBagInterface.php

@@ -0,0 +1,48 @@
+<?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\Session;
+
+/**
+ * Session Bag store.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+interface SessionBagInterface
+{
+    /**
+     * Gets this bag's name
+     *
+     * @return string
+     */
+    function getName();
+
+    /**
+     * Initializes the Bag
+     *
+     * @param array $array
+     */
+    function initialize(array &$array);
+
+    /**
+     * Gets the storage key for this bag.
+     *
+     * @return string
+     */
+    function getStorageKey();
+
+    /**
+     * Clears out data from bag.
+     *
+     * @return mixed Whatever data was contained.
+     */
+    function clear();
+}

+ 167 - 0
vendor/Symfony/Component/HttpFoundation/Session/SessionInterface.php

@@ -0,0 +1,167 @@
+<?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\Session;
+
+/**
+ * Interface for the session.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+interface SessionInterface
+{
+    /**
+     * Starts the session storage.
+     *
+     * @return Boolean True if session started.
+     *
+     * @throws \RuntimeException If session fails to start.
+     *
+     * @api
+     */
+    function start();
+
+    /**
+     * Returns the session ID.
+     *
+     * @return string The session ID.
+     *
+     * @api
+     */
+    function getId();
+
+    /**
+     * Sets the session ID
+     *
+     * @param string $id
+     *
+     * @api
+     */
+    function setId($id);
+
+    /**
+     * Returns the session name.
+     *
+     * @return mixed The session name.
+     *
+     * @api
+     */
+    function getName();
+
+    /**
+     * Sets the session name.
+     *
+     * @param string $name
+     *
+     * @api
+     */
+    function setName($name);
+
+    /**
+     * Invalidates the current session.
+     *
+     * Clears all session attributes and flashes and regenerates the
+     * session and deletes the old session from persistence.
+     *
+     * @return Boolean True if session invalidated, false if error.
+     *
+     * @api
+     */
+    function invalidate();
+
+    /**
+     * Migrates the current session to a new session id while maintaining all
+     * session attributes.
+     *
+     * @param Boolean $destroy Whether to delete the old session or leave it to garbage collection.
+     *
+     * @return Boolean True if session migrated, false if error.
+     *
+     * @api
+     */
+    function migrate($destroy = false);
+
+    /**
+     * Force the session to be saved and closed.
+     *
+     * This method is generally not required for real sessions as
+     * the session will be automatically saved at the end of
+     * code execution.
+     */
+    function save();
+
+    /**
+     * Checks if an attribute is defined.
+     *
+     * @param string $name The attribute name
+     *
+     * @return Boolean true if the attribute is defined, false otherwise
+     *
+     * @api
+     */
+    function has($name);
+
+    /**
+     * Returns an attribute.
+     *
+     * @param string $name    The attribute name
+     * @param mixed  $default The default value if not found.
+     *
+     * @return mixed
+     *
+     * @api
+     */
+    function get($name, $default = null);
+
+    /**
+     * Sets an attribute.
+     *
+     * @param string $name
+     * @param mixed  $value
+     *
+     * @api
+     */
+    function set($name, $value);
+
+    /**
+     * Returns attributes.
+     *
+     * @return array Attributes
+     *
+     * @api
+     */
+    function all();
+
+    /**
+     * Sets attributes.
+     *
+     * @param array $attributes Attributes
+     */
+    function replace(array $attributes);
+
+    /**
+     * Removes an attribute.
+     *
+     * @param string $name
+     *
+     * @return mixed The removed value
+     *
+     * @api
+     */
+    function remove($name);
+
+    /**
+     * Clears all attributes.
+     *
+     * @api
+     */
+    function clear();
+}

+ 139 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php

@@ -0,0 +1,139 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * MemcacheSessionHandler.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class MemcacheSessionHandler implements \SessionHandlerInterface
+{
+    /**
+     * Memcache driver.
+     *
+     * @var \Memcache
+     */
+    private $memcache;
+
+    /**
+     * Configuration options.
+     *
+     * @var array
+     */
+    private $memcacheOptions;
+
+    /**
+     * Key prefix for shared environments.
+     *
+     * @var string
+     */
+    private $prefix;
+
+    /**
+     * Constructor.
+     *
+     * @param \Memcache $memcache        A \Memcache instance
+     * @param array     $memcacheOptions An associative array of Memcache options
+     * @param array     $options         Session configuration options.
+     */
+    public function __construct(\Memcache $memcache, array $memcacheOptions = array(), array $options = array())
+    {
+        $this->memcache = $memcache;
+
+        // defaults
+        if (!isset($memcacheOptions['serverpool'])) {
+            $memcacheOptions['serverpool'] = array(array(
+                'host' => '127.0.0.1',
+                'port' => 11211,
+                'timeout' => 1,
+                'persistent' => false,
+                'weight' => 1,
+                'retry_interval' => 15,
+            ));
+        }
+
+        $memcacheOptions['expiretime'] = isset($memcacheOptions['expiretime']) ? (int)$memcacheOptions['expiretime'] : 86400;
+        $this->prefix = isset($memcacheOptions['prefix']) ? $memcacheOptions['prefix'] : 'sf2s';
+
+        $this->memcacheOptions = $memcacheOptions;
+    }
+
+    protected function addServer(array $server)
+    {
+        if (!array_key_exists('host', $server)) {
+            throw new \InvalidArgumentException('host key must be set');
+        }
+
+        $server['port'] = isset($server['port']) ? (int)$server['port'] : 11211;
+        $server['timeout'] = isset($server['timeout']) ? (int)$server['timeout'] : 1;
+        $server['persistent'] = isset($server['persistent']) ? (bool)$server['persistent'] : false;
+        $server['weight'] = isset($server['weight']) ? (int)$server['weight'] : 1;
+        $server['retry_interval'] = isset($server['retry_interval']) ? (int)$server['retry_interval'] : 15;
+
+        $this->memcache->addserver($server['host'], $server['port'], $server['persistent'],$server['weight'],$server['timeout'],$server['retry_interval']);
+
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function open($savePath, $sessionName)
+    {
+        foreach ($this->memcacheOptions['serverpool'] as $server) {
+            $this->addServer($server);
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        return $this->memcache->close();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($sessionId)
+    {
+        return $this->memcache->get($this->prefix.$sessionId) ?: '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($sessionId, $data)
+    {
+        return $this->memcache->set($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function destroy($sessionId)
+    {
+        return $this->memcache->delete($this->prefix.$sessionId);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function gc($lifetime)
+    {
+        // not required here because memcache will auto expire the records anyhow.
+        return true;
+    }
+}

+ 130 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php

@@ -0,0 +1,130 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * MemcachedSessionHandler.
+ *
+ * Memcached based session storage handler based on the Memcached class
+ * provided by the PHP memcached extension.
+ *
+ * @see http://php.net/memcached
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class MemcachedSessionHandler implements \SessionHandlerInterface
+{
+    /**
+     * Memcached driver.
+     *
+     * @var \Memcached
+     */
+    private $memcached;
+
+    /**
+     * Configuration options.
+     *
+     * @var array
+     */
+    private $memcachedOptions;
+
+    /**
+     * Constructor.
+     *
+     * @param \Memcached $memcached        A \Memcached instance
+     * @param array      $memcachedOptions An associative array of Memcached options
+     * @param array      $options          Session configuration options.
+     */
+    public function __construct(\Memcached $memcached, array $memcachedOptions = array(), array $options = array())
+    {
+        $this->memcached = $memcached;
+
+        // defaults
+        if (!isset($memcachedOptions['serverpool'])) {
+            $memcachedOptions['serverpool'][] = array(
+                'host' => '127.0.0.1',
+                'port' => 11211,
+                'weight' => 1);
+        }
+
+        $memcachedOptions['expiretime'] = isset($memcachedOptions['expiretime']) ? (int)$memcachedOptions['expiretime'] : 86400;
+
+        $this->memcached->setOption(\Memcached::OPT_PREFIX_KEY, isset($memcachedOptions['prefix']) ? $memcachedOptions['prefix'] : 'sf2s');
+
+        $this->memcachedOptions = $memcachedOptions;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function open($savePath, $sessionName)
+    {
+        return $this->memcached->addServers($this->memcachedOptions['serverpool']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($sessionId)
+    {
+        return $this->memcached->get($sessionId) ?: '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($sessionId, $data)
+    {
+        return $this->memcached->set($sessionId, $data, $this->memcachedOptions['expiretime']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function destroy($sessionId)
+    {
+        return $this->memcached->delete($sessionId);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function gc($lifetime)
+    {
+        // not required here because memcached will auto expire the records anyhow.
+        return true;
+    }
+
+    /**
+     * Adds a server to the memcached handler.
+     *
+     * @param array $server
+     */
+    protected function addServer(array $server)
+    {
+        if (array_key_exists('host', $server)) {
+            throw new \InvalidArgumentException('host key must be set');
+        }
+        $server['port'] = isset($server['port']) ? (int)$server['port'] : 11211;
+        $server['timeout'] = isset($server['timeout']) ? (int)$server['timeout'] : 1;
+        $server['presistent'] = isset($server['presistent']) ? (bool)$server['presistent'] : false;
+        $server['weight'] = isset($server['weight']) ? (bool)$server['weight'] : 1;
+    }
+}

+ 41 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php

@@ -0,0 +1,41 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * NativeFileSessionHandler.
+ *
+ * Native session handler using PHP's built in file storage.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeFileSessionHandler extends NativeSessionHandler
+{
+    /**
+     * Constructor.
+     *
+     * @param string $savePath Path of directory to save session files.  Default null will leave setting as defined by PHP.
+     */
+    public function __construct($savePath = null)
+    {
+        if (null === $savePath) {
+            $savePath = ini_get('session.save_path');
+        }
+
+        if ($savePath && !is_dir($savePath)) {
+            mkdir($savePath, 0777, true);
+        }
+
+        ini_set('session.save_handler', 'files');
+        ini_set('session.save_path', $savePath);
+    }
+}

+ 65 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php

@@ -0,0 +1,65 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * NativeMemcacheSessionHandler.
+ *
+ * Driver for the memcache session save hadlers provided by the memcache PHP extension.
+ *
+ * @see http://php.net/memcache
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeMemcacheSessionHandler extends NativeSessionHandler
+{
+    /**
+     * Constructor.
+     *
+     * @param string $savePath Path of memcache server.
+     * @param array  $options  Session configuration options.
+     */
+    public function __construct($savePath = 'tcp://127.0.0.1:11211?persistent=0', array $options = array())
+    {
+        if (!extension_loaded('memcache')) {
+            throw new \RuntimeException('PHP does not have "memcache" session module registered');
+        }
+
+        if (null === $savePath) {
+            $savePath = ini_get('session.save_path');
+        }
+
+        ini_set('session.save_handler', 'memcache');
+        ini_set('session.save_path', $savePath);
+
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set any memcached ini values.
+     *
+     * @see http://php.net/memcache.ini
+     */
+    protected function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array($key, array(
+                'memcache.allow_failover', 'memcache.max_failover_attempts',
+                'memcache.chunk_size', 'memcache.default_port', 'memcache.hash_strategy',
+                'memcache.hash_function', 'memcache.protocol', 'memcache.redundancy',
+                'memcache.session_redundancy', 'memcache.compress_threshold',
+                'memcache.lock_timeout'))) {
+                ini_set($key, $value);
+            }
+        }
+    }
+}

+ 64 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php

@@ -0,0 +1,64 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * NativeMemcachedSessionHandler.
+ *
+ * Driver for the memcached session save hadlers provided by the memcached PHP extension.
+ *
+ * @see http://php.net/memcached.sessions
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeMemcachedSessionHandler extends NativeSessionHandler
+{
+    /**
+     * Constructor.
+     *
+     * @param string $savePath Comma separated list of servers: e.g. memcache1.example.com:11211,memcache2.example.com:11211
+     * @param array  $options  Session configuration options.
+     */
+    public function __construct($savePath = '127.0.0.1:11211', array $options = array())
+    {
+        if (!extension_loaded('memcached')) {
+            throw new \RuntimeException('PHP does not have "memcached" session module registered');
+        }
+
+        if (null === $savePath) {
+            $savePath = ini_get('session.save_path');
+        }
+
+        ini_set('session.save_handler', 'memcached');
+        ini_set('session.save_path', $savePath);
+
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set any memcached ini values.
+     *
+     * @see https://github.com/php-memcached-dev/php-memcached/blob/master/memcached.ini
+     */
+    protected function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array($key, array(
+                'memcached.sess_locking', 'memcached.sess_lock_wait',
+                'memcached.sess_prefix', 'memcached.compression_type',
+                'memcached.compression_factor', 'memcached.compression_threshold',
+                'memcached.serializer'))) {
+                ini_set($key, $value);
+            }
+        }
+    }
+}

+ 24 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php

@@ -0,0 +1,24 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * Adds SessionHandler functionality if available.
+ *
+ * @see http://php.net/sessionhandler
+ */
+
+if (version_compare(phpversion(), '5.4.0', '>=')) {
+    class NativeSessionHandler extends \SessionHandler {}
+} else {
+    class NativeSessionHandler {}
+}

+ 58 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandler.php

@@ -0,0 +1,58 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * NativeSqliteSessionHandler.
+ *
+ * Driver for the sqlite session save hadlers provided by the SQLite PHP extension.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeSqliteSessionHandler extends NativeSessionHandler
+{
+    /**
+     * Constructor.
+     *
+     * @param string $savePath Path to SQLite database file itself.
+     * @param array  $options  Session configuration options.
+     */
+    public function __construct($savePath, array $options = array())
+    {
+        if (!extension_loaded('sqlite')) {
+            throw new \RuntimeException('PHP does not have "sqlite" session module registered');
+        }
+
+        if (null === $savePath) {
+            $savePath = ini_get('session.save_path');
+        }
+
+        ini_set('session.save_handler', 'sqlite');
+        ini_set('session.save_path', $savePath);
+
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set any sqlite ini values.
+     *
+     * @see http://php.net/sqlite.configuration
+     */
+    protected function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array($key, array('sqlite.assoc_case'))) {
+                ini_set($key, $value);
+            }
+        }
+    }
+}

+ 72 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php

@@ -0,0 +1,72 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * NullSessionHandler.
+ *
+ * Can be used in unit testing or in a sitation where persisted sessions are not desired.
+ *
+ * @author Drak <drak@zikula.org>
+ *
+ * @api
+ */
+class NullSessionHandler implements \SessionHandlerInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function open($savePath, $sessionName)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($sessionId)
+    {
+        return '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($sessionId, $data)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function destroy($sessionId)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function gc($lifetime)
+    {
+        return true;
+    }
+}

+ 221 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php

@@ -0,0 +1,221 @@
+<?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\Session\Storage\Handler;
+
+/**
+ * PdoSessionHandler.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Michael Williams <michael.williams@funsational.com>
+ */
+class PdoSessionHandler implements \SessionHandlerInterface
+{
+    /**
+     * PDO instance.
+     *
+     * @var \PDO
+     */
+    private $pdo;
+
+    /**
+     * Database options.
+     *
+     *
+     * @var array
+     */
+    private $dbOptions;
+
+    /**
+     * Constructor.
+     *
+     * @param \PDO  $pdo       A \PDO instance
+     * @param array $dbOptions An associative array of DB options
+     * @param array $options   Session configuration options
+     *
+     * @throws \InvalidArgumentException When "db_table" option is not provided
+     */
+    public function __construct(\PDO $pdo, array $dbOptions = array(), array $options = array())
+    {
+        if (!array_key_exists('db_table', $dbOptions)) {
+            throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.');
+        }
+
+        $this->pdo = $pdo;
+        $this->dbOptions = array_merge(array(
+            'db_id_col'   => 'sess_id',
+            'db_data_col' => 'sess_data',
+            'db_time_col' => 'sess_time',
+        ), $dbOptions);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function open($path, $name)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function destroy($id)
+    {
+        // get table/column
+        $dbTable  = $this->dbOptions['db_table'];
+        $dbIdCol = $this->dbOptions['db_id_col'];
+
+        // delete the record associated with this id
+        $sql = "DELETE FROM $dbTable WHERE $dbIdCol = :id";
+
+        try {
+            $stmt = $this->pdo->prepare($sql);
+            $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
+            $stmt->execute();
+        } catch (\PDOException $e) {
+            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function gc($lifetime)
+    {
+        // get table/column
+        $dbTable    = $this->dbOptions['db_table'];
+        $dbTimeCol = $this->dbOptions['db_time_col'];
+
+        // delete the session records that have expired
+        $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < (:time - $lifetime)";
+
+        try {
+            $stmt = $this->pdo->prepare($sql);
+            $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
+            $stmt->execute();
+        } catch (\PDOException $e) {
+            throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($id)
+    {
+        // get table/columns
+        $dbTable    = $this->dbOptions['db_table'];
+        $dbDataCol = $this->dbOptions['db_data_col'];
+        $dbIdCol   = $this->dbOptions['db_id_col'];
+
+        try {
+            $sql = "SELECT $dbDataCol FROM $dbTable WHERE $dbIdCol = :id";
+
+            $stmt = $this->pdo->prepare($sql);
+            $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
+
+            $stmt->execute();
+            // it is recommended to use fetchAll so that PDO can close the DB cursor
+            // we anyway expect either no rows, or one row with one column. fetchColumn, seems to be buggy #4777
+            $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM);
+
+            if (count($sessionRows) == 1) {
+                return base64_decode($sessionRows[0][0]);
+            }
+
+            // session does not exist, create it
+            $this->createNewSession($id);
+
+            return '';
+        } catch (\PDOException $e) {
+            throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($id, $data)
+    {
+        // get table/column
+        $dbTable   = $this->dbOptions['db_table'];
+        $dbDataCol = $this->dbOptions['db_data_col'];
+        $dbIdCol   = $this->dbOptions['db_id_col'];
+        $dbTimeCol = $this->dbOptions['db_time_col'];
+
+        $sql = ('mysql' === $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME))
+            ? "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) "
+              ."ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = CASE WHEN $dbTimeCol = :time THEN (VALUES($dbTimeCol) + 1) ELSE VALUES($dbTimeCol) END"
+            : "UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id";
+
+        try {
+            //session data can contain non binary safe characters so we need to encode it
+            $encoded = base64_encode($data);
+            $stmt = $this->pdo->prepare($sql);
+            $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
+            $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
+            $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
+            $stmt->execute();
+
+            if (!$stmt->rowCount()) {
+                // No session exists in the database to update. This happens when we have called
+                // session_regenerate_id()
+                $this->createNewSession($id, $data);
+            }
+        } catch (\PDOException $e) {
+            throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
+        }
+
+        return true;
+    }
+
+    /**
+     * Creates a new session with the given $id and $data
+     *
+     * @param string $id
+     * @param string $data
+     *
+     * @return boolean True.
+     */
+    private function createNewSession($id, $data = '')
+    {
+        // get table/column
+        $dbTable    = $this->dbOptions['db_table'];
+        $dbDataCol = $this->dbOptions['db_data_col'];
+        $dbIdCol   = $this->dbOptions['db_id_col'];
+        $dbTimeCol = $this->dbOptions['db_time_col'];
+
+        $sql = "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time)";
+
+        //session data can contain non binary safe characters so we need to encode it
+        $encoded = base64_encode($data);
+        $stmt = $this->pdo->prepare($sql);
+        $stmt->bindParam(':id', $id, \PDO::PARAM_STR);
+        $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
+        $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
+        $stmt->execute();
+
+        return true;
+    }
+}

+ 218 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php

@@ -0,0 +1,218 @@
+<?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\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+
+/**
+ * MockArraySessionStorage mocks the session for unit tests.
+ *
+ * No PHP session is actually started since a session can be initialized
+ * and shutdown only once per PHP execution cycle.
+ *
+ * When doing functional testing, you should use MockFileSessionStorage instead.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Drak <drak@zikula.org>
+ */
+class MockArraySessionStorage implements SessionStorageInterface
+{
+    /**
+     * @var string
+     */
+    protected $id = '';
+
+    /**
+     * @var string
+     */
+    protected $name;
+
+    /**
+     * @var boolean
+     */
+    protected $started = false;
+
+    /**
+     * @var boolean
+     */
+    protected $closed = false;
+
+    /**
+     * @var array
+     */
+    protected $data = array();
+
+    /**
+     * Constructor.
+     *
+     * @param string $name Session name
+     */
+    public function __construct($name = 'MOCKSESSID')
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * Sets the session data.
+     *
+     * @param array $array
+     */
+    public function setSessionData(array $array)
+    {
+        $this->data = $array;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        if ($this->started && !$this->closed) {
+            return true;
+        }
+
+        if (empty($this->id)) {
+            $this->id = $this->generateId();
+        }
+
+        $this->loadSession();
+
+        return true;
+    }
+
+
+    /**
+     * {@inheritdoc}
+     */
+    public function regenerate($destroy = false)
+    {
+        if (!$this->started) {
+            $this->start();
+        }
+
+        $this->id = $this->generateId();
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setId($id)
+    {
+        if ($this->started) {
+            throw new \LogicException('Cannot set session ID after the session has started.');
+        }
+
+        $this->id = $id;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        // nothing to do since we don't persist the session data
+        $this->closed = false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        // clear out the bags
+        foreach ($this->bags as $bag) {
+            $bag->clear();
+        }
+
+        // clear out the session
+        $this->data = array();
+
+        // reconnect the bags to the session
+        $this->loadSession();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function registerBag(SessionBagInterface $bag)
+    {
+        $this->bags[$bag->getName()] = $bag;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getBag($name)
+    {
+        if (!isset($this->bags[$name])) {
+            throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
+        }
+
+        if (!$this->started) {
+            $this->start();
+        }
+
+        return $this->bags[$name];
+    }
+
+    /**
+     * Generates a session ID.
+     *
+     * This doesn't need to be particularly cryptographically secure since this is just
+     * a mock.
+     *
+     * @return string
+     */
+    protected function generateId()
+    {
+        return sha1(uniqid(mt_rand()));
+    }
+
+    protected function loadSession()
+    {
+        foreach ($this->bags as $bag) {
+            $key = $bag->getStorageKey();
+            $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
+            $bag->initialize($this->data[$key]);
+        }
+
+        $this->started = true;
+        $this->closed = false;
+    }
+}

+ 126 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php

@@ -0,0 +1,126 @@
+<?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\Session\Storage;
+
+/**
+ * MockFileSessionStorage is used to mock sessions for
+ * functional testing when done in a single PHP process.
+ *
+ * No PHP session is actually started since a session can be initialized
+ * and shutdown only once per PHP execution cycle and this class does
+ * not pollute any session related globals, including session_*() functions
+ * or session.* PHP ini directives.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class MockFileSessionStorage extends MockArraySessionStorage
+{
+    /**
+     * @var string
+     */
+    private $savePath;
+
+    /**
+     * Constructor.
+     *
+     * @param string $savePath Path of directory to save session files.
+     * @param string $name     Session name.
+     */
+    public function __construct($savePath = null, $name = 'MOCKSESSID')
+    {
+        if (null === $savePath) {
+            $savePath = sys_get_temp_dir();
+        }
+
+        if (!is_dir($savePath)) {
+            mkdir($savePath, 0777, true);
+        }
+
+        $this->savePath = $savePath;
+
+        parent::__construct($name);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        if ($this->started) {
+            return true;
+        }
+
+        if (!$this->id) {
+            $this->id = $this->generateId();
+        }
+
+        $this->read();
+
+        $this->started = true;
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function regenerate($destroy = false)
+    {
+        if ($destroy) {
+            $this->destroy();
+        }
+
+        $this->id = $this->generateId();
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        file_put_contents($this->getFilePath(), serialize($this->data));
+    }
+
+    /**
+     * Deletes a session from persistent storage.
+     * Deliberately leaves session data in memory intact.
+     */
+    private function destroy()
+    {
+        if (is_file($this->getFilePath())) {
+            unlink($this->getFilePath());
+        }
+    }
+
+    /**
+     * Calculate path to file.
+     *
+     * @return string File path
+     */
+    private function getFilePath()
+    {
+        return $this->savePath.'/'.$this->id.'.mocksess';
+    }
+
+    /**
+     * Reads session from storage and loads session.
+     */
+    private function read()
+    {
+        $filePath = $this->getFilePath();
+        $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array();
+
+        $this->loadSession();
+    }
+}

+ 347 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php

@@ -0,0 +1,347 @@
+<?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\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
+use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
+use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
+
+/**
+ * This provides a base class for session attribute storage.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeSessionStorage implements SessionStorageInterface
+{
+    /**
+     * Array of SessionBagInterface
+     *
+     * @var array
+     */
+    protected $bags;
+
+    /**
+     * @var boolean
+     */
+    protected $started = false;
+
+    /**
+     * @var boolean
+     */
+    protected $closed = false;
+
+    /**
+     * @var AbstractProxy
+     */
+    protected $saveHandler;
+
+    /**
+     * Constructor.
+     *
+     * Depending on how you want the storage driver to behave you probably
+     * want top override this constructor entirely.
+     *
+     * List of options for $options array with their defaults.
+     * @see http://php.net/session.configuration for options
+     * but we omit 'session.' from the beginning of the keys for convenience.
+     *
+     * auto_start, "0"
+     * cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely).
+     * cookie_domain, ""
+     * cookie_httponly, ""
+     * cookie_lifetime, "0"
+     * cookie_path, "/"
+     * cookie_secure, ""
+     * entropy_file, ""
+     * entropy_length, "0"
+     * gc_divisor, "100"
+     * gc_maxlifetime, "1440"
+     * gc_probability, "1"
+     * hash_bits_per_character, "4"
+     * hash_function, "0"
+     * name, "PHPSESSID"
+     * referer_check, ""
+     * serialize_handler, "php"
+     * use_cookies, "1"
+     * use_only_cookies, "1"
+     * use_trans_sid, "0"
+     * upload_progress.enabled, "1"
+     * upload_progress.cleanup, "1"
+     * upload_progress.prefix, "upload_progress_"
+     * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS"
+     * upload_progress.freq, "1%"
+     * upload_progress.min-freq, "1"
+     * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
+     *
+     * @param array  $options Session configuration options.
+     * @param object $handler SessionHandlerInterface.
+     */
+    public function __construct(array $options = array(), $handler = null)
+    {
+        // sensible defaults
+        ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class.
+        ini_set('session.cache_limiter', ''); // disable by default because it's managed by HeaderBag (if used)
+        ini_set('session.use_cookies', 1);
+
+        if (version_compare(phpversion(), '5.4.0', '>=')) {
+            session_register_shutdown();
+        } else {
+            register_shutdown_function('session_write_close');
+        }
+
+        $this->setOptions($options);
+        $this->setSaveHandler($handler);
+    }
+
+    /**
+     * Gets the save handler instance.
+     *
+     * @return AbstractProxy
+     */
+    public function getSaveHandler()
+    {
+        return $this->saveHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function start()
+    {
+        if ($this->started && !$this->closed) {
+            return true;
+        }
+
+        // catch condition where session was started automatically by PHP
+        if (!$this->started && !$this->closed && $this->saveHandler->isActive()
+            && $this->saveHandler->isSessionHandlerInterface()) {
+            $this->loadSession();
+
+            return true;
+        }
+
+        if (ini_get('session.use_cookies') && headers_sent()) {
+            throw new \RuntimeException('Failed to start the session because headers have already been sent.');
+        }
+
+        // start the session
+        if (!session_start()) {
+            throw new \RuntimeException('Failed to start the session');
+        }
+
+        $this->loadSession();
+
+        if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
+            $this->saveHandler->setActive(false);
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getId()
+    {
+        if (!$this->started) {
+            return ''; // returning empty is consistent with session_id() behaviour
+        }
+
+        return $this->saveHandler->getId();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setId($id)
+    {
+        return $this->saveHandler->setId($id);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->saveHandler->getName();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setName($name)
+    {
+        $this->saveHandler->setName($name);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function regenerate($destroy = false)
+    {
+        return session_regenerate_id($destroy);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        session_write_close();
+
+        if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
+            $this->saveHandler->setActive(false);
+        }
+
+        $this->closed = true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function clear()
+    {
+        // clear out the bags
+        foreach ($this->bags as $bag) {
+            $bag->clear();
+        }
+
+        // clear out the session
+        $_SESSION = array();
+
+        // reconnect the bags to the session
+        $this->loadSession();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function registerBag(SessionBagInterface $bag)
+    {
+        $this->bags[$bag->getName()] = $bag;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getBag($name)
+    {
+        if (!isset($this->bags[$name])) {
+            throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
+        }
+
+        if (ini_get('session.auto_start') && !$this->started) {
+            $this->start();
+        } elseif ($this->saveHandler->isActive() && !$this->started) {
+            $this->loadSession();
+        }
+
+        return $this->bags[$name];
+    }
+
+    /**
+     * Sets session.* ini variables.
+     *
+     * For convenience we omit 'session.' from the beginning of the keys.
+     * Explicitly ignores other ini keys.
+     *
+     * @param array $options Session ini directives array(key => value).
+     *
+     * @see http://php.net/session.configuration
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array($key, array(
+                'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
+                'cookie_lifetime', 'cookie_path', 'cookie_secure',
+                'entropy_file', 'entropy_length', 'gc_divisor',
+                'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
+                'hash_function', 'name', 'referer_check',
+                'serialize_handler', 'use_cookies',
+                'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
+                'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
+                'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) {
+                ini_set('session.'.$key, $value);
+            }
+        }
+    }
+
+    /**
+     * 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.
+     *
+     *     ini_set('session.save_handlers', 'files');
+     *     ini_set('session.save_path', /tmp');
+     *
+     * @see http://php.net/session-set-save-handler
+     * @see http://php.net/sessionhandlerinterface
+     * @see http://php.net/sessionhandler
+     *
+     * @param object $saveHandler Default null means NativeProxy.
+     */
+    public function setSaveHandler($saveHandler = null)
+    {
+        // Wrap $saveHandler in proxy
+        if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
+            $saveHandler = new SessionHandlerProxy($saveHandler);
+        } elseif (!$saveHandler instanceof AbstractProxy) {
+            $saveHandler = new NativeProxy($saveHandler);
+        }
+
+        $this->saveHandler = $saveHandler;
+
+        if ($this->saveHandler instanceof \SessionHandlerInterface) {
+            if (version_compare(phpversion(), '5.4.0', '>=')) {
+                session_set_save_handler($this->saveHandler, false);
+            } else {
+                session_set_save_handler(
+                    array($this->saveHandler, 'open'),
+                    array($this->saveHandler, 'close'),
+                    array($this->saveHandler, 'read'),
+                    array($this->saveHandler, 'write'),
+                    array($this->saveHandler, 'destroy'),
+                    array($this->saveHandler, 'gc')
+                );
+            }
+        }
+    }
+
+    /**
+     * Load the session with attributes.
+     *
+     * After starting the session, PHP retrieves the session from whatever handlers
+     * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()).
+     * PHP takes the return value from the read() handler, unserializes it
+     * and populates $_SESSION with the result automatically.
+     *
+     * @param array|null $session
+     */
+    protected function loadSession(array &$session = null)
+    {
+        if (null === $session) {
+            $session = &$_SESSION;
+        }
+
+        foreach ($this->bags as $bag) {
+            $key = $bag->getStorageKey();
+            $session[$key] = isset($session[$key]) ? $session[$key] : array();
+            $bag->initialize($session[$key]);
+        }
+
+        $this->started = true;
+        $this->closed = false;
+    }
+}

+ 135 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php

@@ -0,0 +1,135 @@
+<?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\Session\Storage\Proxy;
+
+/**
+ * AbstractProxy.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+abstract class AbstractProxy
+{
+    /**
+     * Flag if handler wraps an internal PHP session handler (using \SessionHandler).
+     *
+     * @var boolean
+     */
+    protected $wrapper = false;
+
+    /**
+     * @var boolean
+     */
+    protected $active = false;
+
+    /**
+     * @var string
+     */
+    protected $saveHandlerName;
+
+    /**
+     * Gets the session.save_handler name.
+     *
+     * @return string
+     */
+    public function getSaveHandlerName()
+    {
+        return $this->saveHandlerName;
+    }
+
+    /**
+     * Is this proxy handler and instance of \SessionHandlerInterface.
+     *
+     * @return boolean
+     */
+    public function isSessionHandlerInterface()
+    {
+        return ($this instanceof \SessionHandlerInterface);
+    }
+
+    /**
+     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
+     *
+     * @return bool
+     */
+    public function isWrapper()
+    {
+        return $this->wrapper;
+    }
+
+    /**
+     * Has a session started?
+     *
+     * @return bool
+     */
+    public function isActive()
+    {
+        return $this->active;
+    }
+
+    /**
+     * Sets the active flag.
+     *
+     * @param bool $flag
+     */
+    public function setActive($flag)
+    {
+        $this->active = (bool) $flag;
+    }
+
+    /**
+     * Gets the session ID.
+     *
+     * @return string
+     */
+    public function getId()
+    {
+        return session_id();
+    }
+
+    /**
+     * Sets the session ID.
+     *
+     * @param string $id
+     */
+    public function setId($id)
+    {
+        if ($this->isActive()) {
+            throw new \LogicException('Cannot change the ID of an active session');
+        }
+
+        session_id($id);
+    }
+
+    /**
+     * Gets the session name.
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return session_name();
+    }
+
+    /**
+     * Sets the session name.
+     *
+     * @param string $name
+     */
+    public function setName($name)
+    {
+        if ($this->isActive()) {
+            throw new \LogicException('Cannot change the name of an active session');
+        }
+
+        session_name($name);
+    }
+}

+ 41 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php

@@ -0,0 +1,41 @@
+<?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\Session\Storage\Proxy;
+
+/**
+ * NativeProxy.
+ *
+ * This proxy is built-in session handlers in PHP 5.3.x
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class NativeProxy extends AbstractProxy
+{
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        // this makes an educated guess as to what the handler is since it should already be set.
+        $this->saveHandlerName = ini_get('session.save_handler');
+    }
+
+    /**
+     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
+     *
+     * @return bool False.
+     */
+    public function isWrapper()
+    {
+        return false;
+    }
+}

+ 95 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php

@@ -0,0 +1,95 @@
+<?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\Session\Storage\Proxy;
+
+/**
+ * SessionHandler proxy.
+ *
+ * @author Drak <drak@zikula.org>
+ */
+class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface
+{
+    /**
+     * @var \SessionHandlerInterface
+     */
+    protected $handler;
+
+    /**
+     * Constructor.
+     *
+     * @param \SessionHandlerInterface $handler
+     */
+    public function __construct(\SessionHandlerInterface $handler)
+    {
+        $this->handler = $handler;
+        $this->wrapper = ($handler instanceof \SessionHandler);
+        $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user';
+    }
+
+    // \SessionHandlerInterface
+
+    /**
+     * {@inheritdoc}
+     */
+    public function open($savePath, $sessionName)
+    {
+        $return = (bool)$this->handler->open($savePath, $sessionName);
+
+        if (true === $return) {
+            $this->active = true;
+        }
+
+        return $return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+        $this->active = false;
+
+        return (bool) $this->handler->close();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($id)
+    {
+        return (string) $this->handler->read($id);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($id, $data)
+    {
+        return (bool) $this->handler->write($id, $data);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function destroy($id)
+    {
+        return (bool) $this->handler->destroy($id);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function gc($maxlifetime)
+    {
+        return (bool) $this->handler->gc($maxlifetime);
+    }
+}

+ 126 - 0
vendor/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php

@@ -0,0 +1,126 @@
+<?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\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
+
+/**
+ * StorageInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Drak <drak@zikula.org>
+ *
+ * @api
+ */
+interface SessionStorageInterface
+{
+    /**
+     * Starts the session.
+     *
+     * @throws \RuntimeException If something goes wrong starting the session.
+     *
+     * @return boolean True if started.
+     *
+     * @api
+     */
+    function start();
+
+    /**
+     * Returns the session ID
+     *
+     * @return string The session ID or empty.
+     *
+     * @api
+     */
+    function getId();
+
+    /**
+     * Sets the session ID
+     *
+     * @param string $id
+     *
+     * @api
+     */
+    function setId($id);
+
+    /**
+     * Returns the session name
+     *
+     * @return mixed The session name.
+     *
+     * @api
+     */
+    function getName();
+
+    /**
+     * Sets the session name
+     *
+     * @param string $name
+     *
+     * @api
+     */
+    function setName($name);
+
+    /**
+     * Regenerates id that represents this storage.
+     *
+     * This method must invoke session_regenerate_id($destroy) unless
+     * this interface is used for a storage object designed for unit
+     * or functional testing where a real PHP session would interfere
+     * with testing.
+     *
+     * Note regenerate+destroy should not clear the session data in memory
+     * only delete the session data from persistent storage.
+     *
+     * @param  Boolean $destroy Destroy session when regenerating?
+     *
+     * @return Boolean True if session regenerated, false if error
+     *
+     * @throws \RuntimeException If an error occurs while regenerating this storage
+     *
+     * @api
+     */
+    function regenerate($destroy = false);
+
+    /**
+     * Force the session to be saved and closed.
+     *
+     * This method must invoke session_write_close() unless this interface is
+     * used for a storage object design for unit or functional testing where
+     * a real PHP session would interfere with testing, in which case it
+     * it should actually persist the session data if required.
+     */
+    function save();
+
+    /**
+     * Clear all session data in memory.
+     */
+    function clear();
+
+    /**
+     * Gets a SessionBagInterface by name.
+     *
+     * @param string $name
+     *
+     * @return SessionBagInterface
+     *
+     * @throws \InvalidArgumentException If the bag does not exist
+     */
+    function getBag($name);
+
+    /**
+     * Registers a SessionBagInterface for use.
+     *
+     * @param SessionBagInterface $bag
+     */
+    function registerBag(SessionBagInterface $bag);
+}

+ 129 - 0
vendor/Symfony/Component/HttpFoundation/StreamedResponse.php

@@ -0,0 +1,129 @@
+<?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;
+
+/**
+ * StreamedResponse represents a streamed HTTP response.
+ *
+ * A StreamedResponse uses a callback for its content.
+ *
+ * The callback should use the standard PHP functions like echo
+ * to stream the response back to the client. The flush() method
+ * can also be used if needed.
+ *
+ * @see flush()
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class StreamedResponse extends Response
+{
+    protected $callback;
+    protected $streamed;
+
+    /**
+     * Constructor.
+     *
+     * @param mixed   $callback A valid PHP callback
+     * @param integer $status   The response status code
+     * @param array   $headers  An array of response headers
+     *
+     * @api
+     */
+    public function __construct($callback = null, $status = 200, $headers = array())
+    {
+        parent::__construct(null, $status, $headers);
+
+        if (null !== $callback) {
+            $this->setCallback($callback);
+        }
+        $this->streamed = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public static function create($callback = null, $status = 200, $headers = array())
+    {
+        return new static($callback, $status, $headers);
+    }
+
+    /**
+     * Sets the PHP callback associated with this Response.
+     *
+     * @param mixed $callback A valid PHP callback
+     */
+    public function setCallback($callback)
+    {
+        if (!is_callable($callback)) {
+            throw new \LogicException('The Response callback must be a valid PHP callable.');
+        }
+        $this->callback = $callback;
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    public function prepare(Request $request)
+    {
+        if ('1.0' != $request->server->get('SERVER_PROTOCOL')) {
+            $this->setProtocolVersion('1.1');
+        }
+
+        $this->headers->set('Cache-Control', 'no-cache');
+
+        parent::prepare($request);
+    }
+
+    /**
+     * @{inheritdoc}
+     *
+     * This method only sends the content once.
+     */
+    public function sendContent()
+    {
+        if ($this->streamed) {
+            return;
+        }
+
+        $this->streamed = true;
+
+        if (null === $this->callback) {
+            throw new \LogicException('The Response callback must not be null.');
+        }
+
+        call_user_func($this->callback);
+    }
+
+    /**
+     * @{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 StreamedResponse instance.');
+        }
+    }
+
+    /**
+     * @{inheritdoc}
+     *
+     * @return false
+     */
+    public function getContent()
+    {
+        return false;
+    }
+}

+ 33 - 0
vendor/Symfony/Component/HttpFoundation/composer.json

@@ -0,0 +1,33 @@
+{
+    "name": "symfony/http-foundation",
+    "type": "library",
+    "description": "Symfony HttpFoundation Component",
+    "keywords": [],
+    "homepage": "http://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "fabien@symfony.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "http://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.2"
+    },
+    "autoload": {
+        "psr-0": {
+            "Symfony\\Component\\HttpFoundation": "",
+            "SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stubs"
+        }
+    },
+    "target-dir": "Symfony/Component/HttpFoundation",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.1-dev"
+        }
+    }
+}