From d004015ce35c70d086719d19e62500f4bea98872 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 6 Feb 2012 23:09:43 -0500 Subject: [PATCH] Issue #1424924 by Rob Loach: Introduce Composer for Symfony component management. --- core/composer.json | 12 + core/includes/bootstrap.inc | 25 +-- .../File/MimeType/ContentTypeMimeTypeGuesser.php | 62 ----- .../ClassLoader/ApcUniversalClassLoader.php | 2 +- .../ClassLoader/ClassCollectionLoader.php | 6 +- .../Component/ClassLoader/ClassMapGenerator.php | 135 +++++++++++ .../ClassLoader/DebugUniversalClassLoader.php | 1 + .../Symfony/Component/ClassLoader/LICENSE | 0 .../Component/ClassLoader/MapClassLoader.php | 0 .../Symfony/Component/ClassLoader/README.md | 60 +++++ .../Component/ClassLoader/UniversalClassLoader.php | 54 ++++- .../Symfony/Component/ClassLoader/composer.json | 8 +- .../Component/HttpFoundation/ApacheRequest.php | 2 +- .../Symfony/Component/HttpFoundation/Cookie.php | 4 - .../File/Exception/AccessDeniedException.php | 0 .../File/Exception/FileException.php | 0 .../File/Exception/FileNotFoundException.php | 0 .../File/Exception/UnexpectedTypeException.php | 0 .../File/Exception/UploadException.php | 0 .../Symfony/Component/HttpFoundation/File/File.php | 129 +++++++++++ .../File/MimeType/ExtensionGuesser.php | 100 ++++++++ .../File/MimeType/ExtensionGuesserInterface.php | 26 +++ .../File/MimeType/FileBinaryMimeTypeGuesser.php | 22 ++- .../File/MimeType/FileinfoMimeTypeGuesser.php | 0 .../File/MimeType/MimeTypeExtensionGuesser.php} | 108 +--------- .../File/MimeType/MimeTypeGuesser.php | 18 +- .../File/MimeType/MimeTypeGuesserInterface.php | 4 +- .../Component/HttpFoundation/File/UploadedFile.php | 4 +- .../Symfony/Component/HttpFoundation/FileBag.php | 1 + .../Symfony/Component/HttpFoundation/HeaderBag.php | 0 .../Symfony/Component/HttpFoundation/LICENSE | 0 .../Component/HttpFoundation/ParameterBag.php | 57 ++++- .../Symfony/Component/HttpFoundation/README.md | 36 +++ .../Component/HttpFoundation/RedirectResponse.php | 0 .../Symfony/Component/HttpFoundation/Request.php | 238 +++++++++++++++++--- .../Component/HttpFoundation/RequestMatcher.php | 56 ++++- .../HttpFoundation/RequestMatcherInterface.php | 0 .../Symfony/Component/HttpFoundation/Response.php | 156 ++++++++++--- .../Component/HttpFoundation/ResponseHeaderBag.php | 65 +++++- .../Symfony/Component/HttpFoundation/ServerBag.php | 7 +- .../Symfony/Component/HttpFoundation/Session.php | 55 +----- .../SessionStorage/ArraySessionStorage.php | 23 ++ .../SessionStorage/FilesystemSessionStorage.php | 22 ++- .../SessionStorage/NativeSessionStorage.php | 0 .../SessionStorage/PdoSessionStorage.php | 26 ++- .../SessionStorage/SessionStorageInterface.php | 0 .../Component/HttpFoundation/StreamedResponse.php | 121 ++++++++++ .../Symfony/Component/HttpFoundation/composer.json | 8 +- 48 files changed, 1294 insertions(+), 359 deletions(-) create mode 100644 core/composer.json delete mode 100644 core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php (96%) rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/ClassCollectionLoader.php (97%) create mode 100644 core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php (96%) rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/LICENSE (100%) rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/MapClassLoader.php (100%) create mode 100644 core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/README.md rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/UniversalClassLoader.php (80%) rename core/vendor/{ => symfony/class-loader}/Symfony/Component/ClassLoader/composer.json (74%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/ApacheRequest.php (89%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/Cookie.php (96%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/Exception/FileException.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/Exception/UploadException.php (100%) create mode 100644 core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/File.php create mode 100644 core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php create mode 100644 core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php (74%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php (100%) rename core/vendor/{Symfony/Component/HttpFoundation/File/File.php => symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php} (85%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php (91%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php (90%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/File/UploadedFile.php (98%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/FileBag.php (99%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/HeaderBag.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/LICENSE (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/ParameterBag.php (74%) create mode 100644 core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/README.md rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/RedirectResponse.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/Request.php (87%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/RequestMatcher.php (80%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/RequestMatcherInterface.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/Response.php (85%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/ResponseHeaderBag.php (69%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/ServerBag.php (91%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/Session.php (81%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php (80%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php (91%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php (100%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php (92%) rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php (100%) create mode 100644 core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/StreamedResponse.php rename core/vendor/{ => symfony/http-foundation}/Symfony/Component/HttpFoundation/composer.json (74%) diff --git a/core/composer.json b/core/composer.json new file mode 100644 index 0000000..bcb1563 --- /dev/null +++ b/core/composer.json @@ -0,0 +1,12 @@ +{ + "require": { + "php": ">=5.3.2", + "symfony/class-loader": "2.1.*", + "symfony/http-foundation": "2.1.*" + }, + "autoload": { + "psr-0": { + "Drupal\\Core": "lib/" + } + } +} diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index dcea7f4..e03e32e 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -2301,20 +2301,13 @@ function _drupal_bootstrap_configuration() { $loader = drupal_classloader(); // Register explicit vendor namespaces. - $loader->registerNamespaces(array( - // All Symfony-borrowed code lives in /core/vendor/Symfony. - 'Symfony' => DRUPAL_ROOT . '/core/vendor', - )); - // Register the Drupal namespace for classes in core as a fallback. - // This allows to register additional namespaces within the Drupal namespace - // (e.g., for modules) and avoids an additional file_exists() on the Drupal - // core namespace, since the class loader can already determine the best - // namespace match based on a string comparison. It further allows modules to - // register/overload namespaces in Drupal core. - $loader->registerNamespaceFallbacks(array( - // All Drupal-namespaced code in core lives in /core/lib/Drupal. - 'Drupal' => DRUPAL_ROOT . '/core/lib', - )); + $coreDir = DRUPAL_ROOT . '/core/'; + $namespaces = array( + 'Symfony\\Component\\HttpFoundation' => $coreDir . 'vendor/symfony/http-foundation/', + 'Symfony\\Component\\ClassLoader' => $coreDir . 'vendor/symfony/class-loader/', + 'Drupal\\Core' => $coreDir . 'lib/', + ); + $loader->registerNamespaces($namespaces); } /** @@ -3058,7 +3051,7 @@ function drupal_get_complete_schema($rebuild = FALSE) { */ function drupal_classloader() { // Include the Symfony ClassLoader for loading PSR-0-compatible classes. - require_once DRUPAL_ROOT . '/core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php'; + require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php'; // By default, use the UniversalClassLoader which is best for development, // as it does not break when code is moved on the file system. However, as it @@ -3070,7 +3063,7 @@ function drupal_classloader() { switch (variable_get('autoloader_mode', 'default')) { case 'apc': if (function_exists('apc_store')) { - require_once DRUPAL_ROOT . '/core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; + require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; $loader = new ApcUniversalClassLoader('drupal.' . $GLOBALS['drupal_hash_salt']); break; } diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php deleted file mode 100644 index fb900b2..0000000 --- a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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 PHP function mime_content_type(). - * - * @author Bernhard Schussek - */ -class ContentTypeMimeTypeGuesser implements MimeTypeGuesserInterface -{ - /** - * Returns whether this guesser is supported on the current OS/PHP setup - * - * @return Boolean - */ - static public function isSupported() - { - return function_exists('mime_content_type'); - } - - /** - * 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; - } - - $type = mime_content_type($path); - - // remove charset (added as of PHP 5.3) - if (false !== $pos = strpos($type, ';')) { - $type = substr($type, 0, $pos); - } - - return $type; - } -} diff --git a/core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php similarity index 96% rename from core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php index 278f510..1295d0a 100644 --- a/core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php @@ -17,7 +17,7 @@ namespace Symfony\Component\ClassLoader; * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and - * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); + * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * diff --git a/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassCollectionLoader.php similarity index 97% rename from core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassCollectionLoader.php index da777f2..49d3da3 100644 --- a/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -55,7 +55,7 @@ class ClassCollectionLoader $reload = false; if ($autoReload) { $metadata = $cacheDir.'/'.$name.$extension.'.meta'; - if (!file_exists($metadata) || !file_exists($cache)) { + if (!is_file($metadata) || !is_file($cache)) { $reload = true; } else { $time = filemtime($cache); @@ -65,7 +65,7 @@ class ClassCollectionLoader $reload = true; } else { foreach ($meta[0] as $resource) { - if (!file_exists($resource) || filemtime($resource) > $time) { + if (!is_file($resource) || filemtime($resource) > $time) { $reload = true; break; @@ -75,7 +75,7 @@ class ClassCollectionLoader } } - if (!$reload && file_exists($cache)) { + if (!$reload && is_file($cache)) { require_once $cache; return; diff --git a/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php new file mode 100644 index 0000000..5730eb0 --- /dev/null +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * ClassMapGenerator + * + * @author Gyula Sallai + */ +class ClassMapGenerator +{ + /** + * Generate a class map file + * + * @param array|string $dirs Directories or a single path to search in + * @param string $file The name of the class map file + */ + static public function dump($dirs, $file) + { + $dirs = (array) $dirs; + $maps = array(); + + foreach ($dirs as $dir) { + $maps = array_merge($maps, static::createMap($dir)); + } + + file_put_contents($file, sprintf('isFile()) { + continue; + } + + $path = $file->getRealPath(); + + if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { + continue; + } + + $classes = self::findClasses($path); + + foreach ($classes as $class) { + $map[$class] = $path; + } + + } + + return $map; + } + + /** + * Extract the classes in the given file + * + * @param string $path The file to check + * + * @return array The found classes + */ + static private function findClasses($path) + { + $contents = file_get_contents($path); + $tokens = token_get_all($contents); + + $classes = array(); + + $namespace = ''; + for ($i = 0, $max = count($tokens); $i < $max; $i++) { + $token = $tokens[$i]; + + if (is_string($token)) { + continue; + } + + $class = ''; + + switch ($token[0]) { + case T_NAMESPACE: + $namespace = ''; + // If there is a namespace, extract it + while (($t = $tokens[++$i]) && is_array($t)) { + if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) { + $namespace .= $t[1]; + } + } + $namespace .= '\\'; + break; + case T_CLASS: + case T_INTERFACE: + // Find the classname + while (($t = $tokens[++$i]) && is_array($t)) { + if (T_STRING === $t[0]) { + $class .= $t[1]; + } else if ($class !== '' && T_WHITESPACE == $t[0]) { + break; + } + } + + if (empty($namespace)) { + $classes[] = $class; + } else { + $classes[] = $namespace . $class; + } + break; + default: + break; + } + } + + return $classes; + } +} diff --git a/core/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php similarity index 96% rename from core/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php index 8a958e0..8cc6747 100644 --- a/core/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php @@ -38,6 +38,7 @@ class DebugUniversalClassLoader extends UniversalClassLoader $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks()); $loader->registerNamespaces($function[0]->getNamespaces()); $loader->registerPrefixes($function[0]->getPrefixes()); + $loader->useIncludePath($function[0]->getUseIncludePath()); $function[0] = $loader; } diff --git a/core/vendor/Symfony/Component/ClassLoader/LICENSE b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/LICENSE similarity index 100% rename from core/vendor/Symfony/Component/ClassLoader/LICENSE rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/LICENSE diff --git a/core/vendor/Symfony/Component/ClassLoader/MapClassLoader.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/MapClassLoader.php similarity index 100% rename from core/vendor/Symfony/Component/ClassLoader/MapClassLoader.php rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/MapClassLoader.php diff --git a/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/README.md b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/README.md new file mode 100644 index 0000000..bdfcb8e --- /dev/null +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/README.md @@ -0,0 +1,60 @@ +ClassLoader Component +===================== + +ClassLoader loads your project classes automatically if they follow some +standard PHP conventions. + +The Universal ClassLoader is able to autoload classes that implement the PSR-0 +standard or the PEAR naming convention. + +First, register the autoloader: + + require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; + + use Symfony\Component\ClassLoader\UniversalClassLoader; + + $loader = new UniversalClassLoader(); + $loader->register(); + +Then, register some namespaces with the `registerNamespace()` method: + + $loader->registerNamespace('Symfony', __DIR__.'/src'); + $loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src'); + +The `registerNamespace()` method takes a namespace prefix and a path where to +look for the classes as arguments. + +You can also register a sub-namespaces: + + $loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib'); + +The order of registration is significant and the first registered namespace +takes precedence over later registered one. + +You can also register more than one path for a given namespace: + + $loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src')); + +Alternatively, you can use the `registerNamespaces()` method to register more +than one namespace at once: + + $loader->registerNamespaces(array( + 'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'), + 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', + 'Doctrine' => __DIR__.'/vendor/doctrine/lib', + 'Monolog' => __DIR__.'/vendor/monolog/src', + )); + +For better performance, you can use the APC based version of the universal +class loader: + + require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; + require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; + + use Symfony\Component\ClassLoader\ApcUniversalClassLoader; + + $loader = new ApcUniversalClassLoader('apc.prefix.'); + +Furthermore, the component provides tools to aggregate classes into a single +file, which is especially useful to improve performance on servers that do not +provide byte caches. diff --git a/core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php similarity index 80% rename from core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php index d296b94..f67a127 100644 --- a/core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php @@ -17,7 +17,7 @@ namespace Symfony\Component\ClassLoader; * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and - * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); + * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * @@ -41,6 +41,10 @@ namespace Symfony\Component\ClassLoader; * 'Swift_' => __DIR__.'/Swift', * )); * + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->useIncludePath(true); + * * // activate the autoloader * $loader->register(); * @@ -60,6 +64,29 @@ class UniversalClassLoader private $prefixes = array(); private $namespaceFallbacks = array(); private $prefixFallbacks = array(); + private $useIncludePath = false; + + /** + * Turns on searching the include for class files. Allows easy loading + * of installed PEAR packages + * + * @param Boolean $useIncludePath + */ + public function useIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return Boolean + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } /** * Gets the configured namespaces. @@ -219,47 +246,54 @@ class UniversalClassLoader if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $namespace = substr($class, 0, $pos); + $className = substr($class, $pos + 1); + $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->namespaces as $ns => $dirs) { if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { - $className = substr($class, $pos + 1); - $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; - if (file_exists($file)) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { return $file; } } } foreach ($this->namespaceFallbacks as $dir) { - $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php'; - if (file_exists($file)) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { return $file; } } + } else { // PEAR-like class name + $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if (0 !== strpos($class, $prefix)) { continue; } foreach ($dirs as $dir) { - $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; - if (file_exists($file)) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { return $file; } } } foreach ($this->prefixFallbacks as $dir) { - $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; - if (file_exists($file)) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { return $file; } } } + + if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { + return $file; + } } } diff --git a/core/vendor/Symfony/Component/ClassLoader/composer.json b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/composer.json similarity index 74% rename from core/vendor/Symfony/Component/ClassLoader/composer.json rename to core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/composer.json index 35b573e..8c49eef 100644 --- a/core/vendor/Symfony/Component/ClassLoader/composer.json +++ b/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/composer.json @@ -4,7 +4,7 @@ "description": "Symfony ClassLoader Component", "keywords": [], "homepage": "http://symfony.com", - "version": "2.0.4", + "version": "2.1.0", "license": "MIT", "authors": [ { @@ -18,5 +18,9 @@ ], "require": { "php": ">=5.3.2" - } + }, + "autoload": { + "psr-0": { "Symfony\\Component\\ClassLoader": "" } + }, + "target-dir": "Symfony/Component/ClassLoader" } diff --git a/core/vendor/Symfony/Component/HttpFoundation/ApacheRequest.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ApacheRequest.php similarity index 89% rename from core/vendor/Symfony/Component/HttpFoundation/ApacheRequest.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ApacheRequest.php index 2721581..ca8f8ee 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ApacheRequest.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ApacheRequest.php @@ -46,6 +46,6 @@ class ApacheRequest extends Request */ protected function preparePathInfo() { - return $this->server->get('PATH_INFO'); + return $this->server->get('PATH_INFO') ?: substr($this->prepareRequestUri(), strlen($this->prepareBaseUrl())) ?: '/'; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/Cookie.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Cookie.php similarity index 96% rename from core/vendor/Symfony/Component/HttpFoundation/Cookie.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Cookie.php index 8392812..0511162 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Cookie.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Cookie.php @@ -48,10 +48,6 @@ class Cookie throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } - if (preg_match("/[,; \t\r\n\013\014]/", $value)) { - throw new \InvalidArgumentException(sprintf('The cookie value "%s" contains invalid characters.', $value)); - } - if (empty($name)) { throw new \InvalidArgumentException('The cookie name cannot be empty.'); } diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/FileException.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/FileException.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/UploadException.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/Exception/UploadException.php diff --git a/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/File.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/File.php new file mode 100644 index 0000000..3134ccd --- /dev/null +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/File.php @@ -0,0 +1,129 @@ + + * + * 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 + * + * @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); + } +} diff --git a/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php new file mode 100644 index 0000000..b73cd99 --- /dev/null +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php @@ -0,0 +1,100 @@ + + * + * 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. + * + * + * $guesser = ExtensionGuesser::getInstance(); + * $guesser->register(new MyCustomExtensionGuesser()); + * + * + * 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; + } +} diff --git a/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php new file mode 100644 index 0000000..5b14ef9 --- /dev/null +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php @@ -0,0 +1,26 @@ + + * + * 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); +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php similarity index 74% rename from core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php index 1b869f2..12b84cd 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -21,6 +21,23 @@ use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; */ 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 * @@ -28,8 +45,9 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface */ static public function isSupported() { - return !strstr(PHP_OS, 'WIN'); + return !defined('PHP_WINDOWS_VERSION_BUILD'); } + /** * Guesses the mime type of the file with the given path * @@ -52,7 +70,7 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface ob_start(); // need to use --mime instead of -i. see #6641 - passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($path)), $return); + passthru(sprintf($this->cmd, escapeshellarg($path)), $return); if ($return > 0) { ob_end_clean(); diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/File.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php similarity index 85% rename from core/vendor/Symfony/Component/HttpFoundation/File/File.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php index 3a900fd..188630b 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/File.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php @@ -9,27 +9,19 @@ * 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; +namespace Symfony\Component\HttpFoundation\File\Mimetype; /** - * A file in the file system. - * - * @author Bernhard Schussek - * - * @api + * Provides a best-guess mapping of mime type to file extension. */ -class File extends \SplFileInfo +class MimeTypeExtensionGuesser implements ExtensionGuesserInterface { /** * A map of mime types and their default extensions. * * @var array */ - static protected $defaultExtensions = array( + protected $defaultExtensions = array( 'application/andrew-inset' => 'ez', 'application/appledouble' => 'base64', 'application/applefile' => 'base64', @@ -443,102 +435,14 @@ class File extends \SplFileInfo ); /** - * Constructs a new file from the given path. - * - * @param string $path The path to the file - * - * @throws FileNotFoundException If the given path is not a file - * - * @api - */ - public function __construct($path) - { - if (!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(); - - return isset(static::$defaultExtensions[$type]) ? static::$defaultExtensions[$type] : null; - } - - /** - * 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() + public function guess($mimeType) { - $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); + return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php similarity index 91% rename from core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php index 23dd463..d73a093 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php @@ -67,10 +67,6 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface $this->register(new FileBinaryMimeTypeGuesser()); } - if (ContentTypeMimeTypeGuesser::isSupported()) { - $this->register(new ContentTypeMimeTypeGuesser()); - } - if (FileinfoMimeTypeGuesser::isSupported()) { $this->register(new FileinfoMimeTypeGuesser()); } @@ -97,7 +93,9 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface * 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) @@ -110,16 +108,14 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface throw new AccessDeniedException($path); } - $mimeType = null; + 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) { - $mimeType = $guesser->guess($path); - - if (null !== $mimeType) { - break; + if (null !== $mimeType = $guesser->guess($path)) { + return $mimeType; } } - - return $mimeType; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php similarity index 90% rename from core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php index c111583..66178bb 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php @@ -19,10 +19,12 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; interface MimeTypeGuesserInterface { /** - * Guesses the mime type of the file with the given path + * 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 */ diff --git a/core/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/UploadedFile.php similarity index 98% rename from core/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/UploadedFile.php index 936ed70..4e51c50 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/UploadedFile.php @@ -100,9 +100,7 @@ class UploadedFile extends File $this->error = $error ?: UPLOAD_ERR_OK; $this->test = (Boolean) $test; - if (UPLOAD_ERR_OK === $this->error) { - parent::__construct($path); - } + parent::__construct($path, UPLOAD_ERR_OK === $this->error); } /** diff --git a/core/vendor/Symfony/Component/HttpFoundation/FileBag.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/FileBag.php similarity index 99% rename from core/vendor/Symfony/Component/HttpFoundation/FileBag.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/FileBag.php index 602cff2..702ab84 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/FileBag.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/FileBag.php @@ -122,6 +122,7 @@ class FileBag extends ParameterBag * just returns the original array unmodified. * * @param array $data + * * @return array */ protected function fixPhpFilesArray($data) diff --git a/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/HeaderBag.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/HeaderBag.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/LICENSE b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/LICENSE similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/LICENSE rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/LICENSE diff --git a/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ParameterBag.php similarity index 74% rename from core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ParameterBag.php index 3a38b5f..84c0fb8 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ParameterBag.php @@ -20,6 +20,11 @@ namespace Symfony\Component\HttpFoundation; */ class ParameterBag { + /** + * Parameter storage. + * + * @var array + */ protected $parameters; /** @@ -86,8 +91,8 @@ class ParameterBag * Returns a parameter by name. * * @param string $path The key - * @param mixed $default The default value - * @param boolean $deep + * @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 */ @@ -113,7 +118,7 @@ class ParameterBag } $currentKey = ''; - } else if (']' === $char) { + } elseif (']' === $char) { if (null === $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i)); } @@ -183,8 +188,8 @@ class ParameterBag * Returns the alphabetic characters of the parameter value. * * @param string $key The parameter key - * @param mixed $default The default value - * @param boolean $deep + * @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 * @@ -199,8 +204,8 @@ class ParameterBag * Returns the alphabetic characters and digits of the parameter value. * * @param string $key The parameter key - * @param mixed $default The default value - * @param boolean $deep + * @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 * @@ -215,8 +220,8 @@ class ParameterBag * Returns the digits of the parameter value. * * @param string $key The parameter key - * @param mixed $default The default value - * @param boolean $deep + * @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 * @@ -231,8 +236,8 @@ class ParameterBag * Returns the parameter value converted to integer. * * @param string $key The parameter key - * @param mixed $default The default value - * @param boolean $deep + * @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 * @@ -242,4 +247,34 @@ class ParameterBag { 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); + } } diff --git a/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/README.md b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/README.md new file mode 100644 index 0000000..67823e7 --- /dev/null +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/README.md @@ -0,0 +1,36 @@ +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. + +Resources +--------- + +Unit tests: + +https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/HttpFoundation diff --git a/core/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RedirectResponse.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RedirectResponse.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/Request.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Request.php similarity index 87% rename from core/vendor/Symfony/Component/HttpFoundation/Request.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Request.php index e66abb7..fc33610 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Request.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Request.php @@ -71,18 +71,74 @@ class Request */ 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 + */ protected $session; + /** + * @var string + */ + protected $locale; + + /** + * @var string + */ + protected $defaultLocale = 'en'; + + /** + * @var string + */ static protected $formats; /** @@ -152,7 +208,7 @@ class Request $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')) + && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); @@ -211,23 +267,37 @@ class Request $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'] = ''; } - if (in_array(strtoupper($method), array('POST', 'PUT', 'DELETE'))) { - $request = $parameters; - $query = array(); - $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; - } else { - $request = array(); - $query = $parameters; - if (false !== $pos = strpos($uri, '?')) { - $qs = substr($uri, $pos + 1); - parse_str($qs, $params); - - $query = array_merge($params, $query); - } + 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; + if (false !== $pos = strpos($uri, '?')) { + $qs = substr($uri, $pos + 1); + parse_str($qs, $params); + + $query = array_merge($params, $query); + } + break; } $queryString = isset($components['query']) ? html_entity_decode($components['query']) : ''; @@ -373,10 +443,15 @@ class Request * 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 @@ -453,7 +528,9 @@ class Request if ($this->server->has('HTTP_CLIENT_IP')) { return $this->server->get('HTTP_CLIENT_IP'); } elseif (self::$trustProxy && $this->server->has('HTTP_X_FORWARDED_FOR')) { - return $this->server->get('HTTP_X_FORWARDED_FOR'); + $clientIp = explode(',', $this->server->get('HTTP_X_FORWARDED_FOR'), 2); + + return isset($clientIp[0]) ? trim($clientIp[0]) : ''; } } @@ -560,7 +637,31 @@ class Request */ public function getPort() { - return $this->headers->get('X-Forwarded-Port') ?: $this->server->get('SERVER_PORT'); + 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'); } /** @@ -616,7 +717,20 @@ class Request $qs = '?'.$qs; } - return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$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; } /** @@ -639,7 +753,7 @@ class Request * It builds a normalized query string, where keys/value pairs are alphabetized * and have consistent escaping. * - * @return string A normalized query string for the Request + * @return string|null A normalized query string for the Request * * @api */ @@ -846,6 +960,52 @@ class Request } /** + * 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 @@ -903,7 +1063,7 @@ class Request * * @param array $locales An array of ordered available locales * - * @return string The preferred locale + * @return string|null The preferred locale * * @api */ @@ -911,7 +1071,7 @@ class Request { $preferredLanguages = $this->getLanguages(); - if (null === $locales) { + if (empty($locales)) { return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; } @@ -1017,6 +1177,8 @@ class Request * 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) { @@ -1027,9 +1189,9 @@ class Request $values = array(); foreach (array_filter(explode(',', $header)) as $value) { // Cut off any q-value that might come after a semi-colon - if ($pos = strpos($value, ';')) { - $q = (float) trim(substr($value, strpos($value, '=') + 1)); - $value = trim(substr($value, 0, $pos)); + 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; } @@ -1057,7 +1219,7 @@ class Request { $requestUri = ''; - if ($this->headers->has('X_REWRITE_URL')) { + 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') != '') { @@ -1081,6 +1243,11 @@ class Request return $requestUri; } + /** + * Prepares the base URL. + * + * @return string + */ protected function prepareBaseUrl() { $filename = basename($this->server->get('SCRIPT_FILENAME')); @@ -1143,7 +1310,7 @@ class Request } /** - * Prepares base path. + * Prepares the base path. * * @return string base path */ @@ -1169,7 +1336,7 @@ class Request } /** - * Prepares path info. + * Prepares the path info. * * @return string path info */ @@ -1212,6 +1379,25 @@ class Request '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) { + } + } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RequestMatcher.php similarity index 80% rename from core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RequestMatcher.php index 52ba078..0ca082d 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RequestMatcher.php @@ -20,10 +20,31 @@ namespace Symfony\Component\HttpFoundation; */ 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()) @@ -122,6 +143,14 @@ class RequestMatcher implements RequestMatcherInterface 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 @@ -132,10 +161,18 @@ class RequestMatcher implements RequestMatcherInterface } } + /** + * 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); + list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 32) { return false; @@ -149,8 +186,15 @@ class RequestMatcher implements RequestMatcherInterface } /** + * Validates an IPv6 address. + * * @author David Soria Parra * @see https://github.com/dsp/v6tools + * + * @param string $requestIp + * @param string $ip + * + * @return boolean True valid, false if not. */ protected function checkIp6($requestIp, $ip) { @@ -158,16 +202,16 @@ class RequestMatcher implements RequestMatcherInterface throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } - list($address, $netmask) = explode('/', $ip); + list($address, $netmask) = explode('/', $ip, 2); - $bytes_addr = unpack("n*", inet_pton($address)); - $bytes_test = unpack("n*", inet_pton($requestIp)); + $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) ?: 16; + $left = ($left <= 16) ? $left : 16; $mask = ~(0xffff >> $left) & 0xffff; - if (($bytes_addr[$i] & $mask) != ($bytes_test[$i] & $mask)) { + if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { return false; } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RequestMatcherInterface.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RequestMatcherInterface.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/Response.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php similarity index 85% rename from core/vendor/Symfony/Component/HttpFoundation/Response.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php index e8a7d56..de4c0f4 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Response.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php @@ -25,12 +25,36 @@ class Response */ 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. + * + * @var array + */ static public $statusTexts = array( 100 => 'Continue', 101 => 'Switching Protocols', @@ -96,14 +120,18 @@ class Response } /** - * Returns the response content as it will be sent (with the 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 content + * @return string The Response as an HTTP string + * + * @see prepare() */ public function __toString() { - $this->prepare(); - return sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". $this->headers."\r\n". @@ -122,26 +150,48 @@ class Response * Prepares the Response before it is sent to the client. * * This method tweaks the Response to ensure that it is - * compliant with RFC 2616. + * 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() + 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 (!$this->headers->has('Content-Type')) { - $this->headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif ('text/' === substr($this->headers->get('Content-Type'), 0, 5) && false === strpos($this->headers->get('Content-Type'), 'charset')) { + 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 - $this->headers->set('Content-Type', $this->headers->get('Content-Type').'; charset='.$charset); + $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); } // Fix Content-Length - if ($this->headers->has('Transfer-Encoding')) { - $this->headers->remove('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); + } } } @@ -155,8 +205,6 @@ class Response return; } - $this->prepare(); - // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)); @@ -197,7 +245,7 @@ class Response } /** - * Sets the response content + * Sets the response content. * * Valid types are strings, numbers, and objects that implement a __toString() method. * @@ -215,7 +263,7 @@ class Response } /** - * Gets the current response content + * Gets the current response content. * * @return string Content * @@ -251,7 +299,7 @@ class Response } /** - * Sets response status code. + * Sets the response status code. * * @param integer $code HTTP status code * @param string $text HTTP status text @@ -271,7 +319,7 @@ class Response } /** - * Retrieves status code for the current web response. + * Retrieves the status code for the current web response. * * @return string Status code * @@ -283,7 +331,7 @@ class Response } /** - * Sets response charset. + * Sets the response charset. * * @param string $charset Character set * @@ -409,7 +457,7 @@ class Response * * @return \DateTime A \DateTime instance * - * @throws \RuntimeException when the header is not parseable + * @throws \RuntimeException When the header is not parseable * * @api */ @@ -470,7 +518,7 @@ class Response } /** - * Sets the Expires HTTP header with a \DateTime instance. + * Sets the Expires HTTP header with a DateTime instance. * * If passed a null value, it removes the header. * @@ -522,7 +570,7 @@ class Response * * This methods sets the Cache-Control max-age directive. * - * @param integer $value A number of seconds + * @param integer $value Number of seconds * * @api */ @@ -536,7 +584,7 @@ class Response * * This methods sets the Cache-Control s-maxage directive. * - * @param integer $value A number of seconds + * @param integer $value Number of seconds * * @api */ @@ -572,7 +620,7 @@ class Response * * This method adjusts the Cache-Control/s-maxage directive. * - * @param integer $seconds The number of seconds + * @param integer $seconds Number of seconds * * @api */ @@ -586,7 +634,7 @@ class Response * * This method adjusts the Cache-Control/max-age directive. * - * @param integer $seconds The number of seconds + * @param integer $seconds Number of seconds * * @api */ @@ -608,7 +656,7 @@ class Response } /** - * Sets the Last-Modified HTTP header with a \DateTime instance. + * Sets the Last-Modified HTTP header with a DateTime instance. * * If passed a null value, it removes the header. * @@ -628,7 +676,7 @@ class Response } /** - * Returns the literal value of ETag HTTP header. + * Returns the literal value of the ETag HTTP header. * * @return string The ETag HTTP header * @@ -661,7 +709,7 @@ class Response } /** - * Sets Response cache headers (validation and/or expiration). + * Sets the response's cache headers (validation and/or expiration). * * Available options are: etag, last_modified, max_age, s_maxage, private, and public. * @@ -672,7 +720,7 @@ class Response 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_keys($diff)))); + throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff)))); } if (isset($options['etag'])) { @@ -771,15 +819,15 @@ class Response } /** - * Determines if the Response validators (ETag, Last-Modified) matches + * 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 - * remove the actual content by calling the setNotModified() method. + * removes the actual content by calling the setNotModified() method. * * @param Request $request A Request instance * - * @return Boolean true if the Response validators matches the Request, false otherwise + * @return Boolean true if the Response validators match the Request, false otherwise * * @api */ @@ -802,6 +850,10 @@ class Response // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html /** + * Is response invalid? + * + * @return boolean + * * @api */ public function isInvalid() @@ -810,6 +862,10 @@ class Response } /** + * Is response informative? + * + * @return boolean + * * @api */ public function isInformational() @@ -818,6 +874,10 @@ class Response } /** + * Is response successful? + * + * @return boolean + * * @api */ public function isSuccessful() @@ -826,6 +886,10 @@ class Response } /** + * Is the response a redirect? + * + * @return boolean + * * @api */ public function isRedirection() @@ -834,6 +898,10 @@ class Response } /** + * Is there a client error? + * + * @return boolean + * * @api */ public function isClientError() @@ -842,6 +910,10 @@ class Response } /** + * Was there a server side error? + * + * @return boolean + * * @api */ public function isServerError() @@ -850,6 +922,10 @@ class Response } /** + * Is the response OK? + * + * @return boolean + * * @api */ public function isOk() @@ -858,6 +934,10 @@ class Response } /** + * Is the reponse forbidden? + * + * @return boolean + * * @api */ public function isForbidden() @@ -866,6 +946,10 @@ class Response } /** + * Is the response a not found error? + * + * @return boolean + * * @api */ public function isNotFound() @@ -874,6 +958,10 @@ class Response } /** + * Is the response a redirect of some form? + * + * @return boolean + * * @api */ public function isRedirect($location = null) @@ -882,6 +970,10 @@ class Response } /** + * Is the response empty? + * + * @return boolean + * * @api */ public function isEmpty() diff --git a/core/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ResponseHeaderBag.php similarity index 69% rename from core/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index f243dcc..11615b9 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -20,10 +20,20 @@ namespace Symfony\Component\HttpFoundation; */ class ResponseHeaderBag extends HeaderBag { - const COOKIES_FLAT = 'flat'; - const COOKIES_ARRAY = 'array'; + 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(); /** @@ -120,7 +130,6 @@ class ResponseHeaderBag extends HeaderBag * Sets a cookie. * * @param Cookie $cookie - * @return void * * @api */ @@ -135,7 +144,6 @@ class ResponseHeaderBag extends HeaderBag * @param string $name * @param string $path * @param string $domain - * @return void * * @api */ @@ -195,7 +203,6 @@ class ResponseHeaderBag extends HeaderBag * @param string $name * @param string $path * @param string $domain - * @return void * * @api */ @@ -205,6 +212,54 @@ class ResponseHeaderBag extends HeaderBag } /** + * 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 diff --git a/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ServerBag.php similarity index 91% rename from core/vendor/Symfony/Component/HttpFoundation/ServerBag.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ServerBag.php index 02db3b1..9b57f9e 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ServerBag.php @@ -19,11 +19,16 @@ namespace Symfony\Component\HttpFoundation; */ class ServerBag extends ParameterBag { + /** + * Gets the HTTP headers. + * + * @return string + */ public function getHeaders() { $headers = array(); foreach ($this->parameters as $key => $value) { - if ('HTTP_' === substr($key, 0, 5)) { + if (0 === strpos($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; } // CONTENT_* are not prefixed with HTTP_ diff --git a/core/vendor/Symfony/Component/HttpFoundation/Session.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session.php similarity index 81% rename from core/vendor/Symfony/Component/HttpFoundation/Session.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session.php index a835ef7..721a6c7 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/Session.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session.php @@ -27,25 +27,19 @@ class Session implements \Serializable protected $attributes; protected $flashes; protected $oldFlashes; - protected $locale; - protected $defaultLocale; protected $closed; /** * Constructor. * - * @param SessionStorageInterface $storage A SessionStorageInterface instance - * @param string $defaultLocale The default locale + * @param SessionStorageInterface $storage A SessionStorageInterface instance */ - public function __construct(SessionStorageInterface $storage, $defaultLocale = 'en') + public function __construct(SessionStorageInterface $storage) { $this->storage = $storage; - $this->defaultLocale = $defaultLocale; - $this->locale = $defaultLocale; $this->flashes = array(); $this->oldFlashes = array(); $this->attributes = array(); - $this->setPhpDefaultLocale($this->defaultLocale); $this->started = false; $this->closed = false; } @@ -68,8 +62,6 @@ class Session implements \Serializable if (isset($attributes['attributes'])) { $this->attributes = $attributes['attributes']; $this->flashes = $attributes['flashes']; - $this->locale = $attributes['locale']; - $this->setPhpDefaultLocale($this->locale); // flag current flash messages to be removed at shutdown $this->oldFlashes = $this->flashes; @@ -183,7 +175,6 @@ class Session implements \Serializable $this->attributes = array(); $this->flashes = array(); - $this->setPhpDefaultLocale($this->locale = $this->defaultLocale); } /** @@ -225,30 +216,6 @@ class Session implements \Serializable } /** - * Returns the locale - * - * @return string - */ - public function getLocale() - { - return $this->locale; - } - - /** - * Sets the locale. - * - * @param string $locale - */ - public function setLocale($locale) - { - if (false === $this->started) { - $this->start(); - } - - $this->setPhpDefaultLocale($this->locale = $locale); - } - - /** * Gets the flash messages. * * @return array @@ -356,7 +323,6 @@ class Session implements \Serializable $this->storage->write('_symfony2', array( 'attributes' => $this->attributes, 'flashes' => $this->flashes, - 'locale' => $this->locale, )); } @@ -380,26 +346,13 @@ class Session implements \Serializable public function serialize() { - return serialize(array($this->storage, $this->defaultLocale)); + return serialize($this->storage); } public function unserialize($serialized) { - list($this->storage, $this->defaultLocale) = unserialize($serialized); + $this->storage = unserialize($serialized); $this->attributes = array(); $this->started = false; } - - 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) { - } - } } diff --git a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php similarity index 80% rename from core/vendor/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php index 62aac40..5a6558a 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php @@ -22,13 +22,24 @@ namespace Symfony\Component\HttpFoundation\SessionStorage; class ArraySessionStorage implements SessionStorageInterface { + /** + * Storage data. + * + * @var array + */ private $data = array(); + /** + * {@inheritdoc} + */ public function read($key, $default = null) { return array_key_exists($key, $this->data) ? $this->data[$key] : $default; } + /** + * {@inheritdoc} + */ public function regenerate($destroy = false) { if ($destroy) { @@ -38,19 +49,31 @@ class ArraySessionStorage implements SessionStorageInterface return true; } + /** + * {@inheritdoc} + */ public function remove($key) { unset($this->data[$key]); } + /** + * {@inheritdoc} + */ public function start() { } + /** + * {@inheritdoc} + */ public function getId() { } + /** + * {@inheritdoc} + */ public function write($key, $data) { $this->data[$key] = $data; diff --git a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php similarity index 91% rename from core/vendor/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php index 87abd01..ceb5913 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php @@ -23,8 +23,25 @@ namespace Symfony\Component\HttpFoundation\SessionStorage; */ class FilesystemSessionStorage extends NativeSessionStorage { + /** + * File path. + * + * @var string + */ private $path; + + /** + * Data. + * + * @var array + */ private $data; + + /** + * Session started flag. + * + * @var boolean + */ private $started; /** @@ -67,7 +84,7 @@ class FilesystemSessionStorage extends NativeSessionStorage $file = $this->path.'/'.session_id().'.session'; - $this->data = file_exists($file) ? unserialize(file_get_contents($file)) : array(); + $this->data = is_file($file) ? unserialize(file_get_contents($file)) : array(); $this->started = true; } @@ -94,7 +111,8 @@ class FilesystemSessionStorage extends NativeSessionStorage * * The preferred format for a key is directory style so naming conflicts can be avoided. * - * @param string $key A unique key identifying your data + * @param string $key A unique key identifying your data + * @param string $default The default value * * @return mixed Data associated with the key * diff --git a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php diff --git a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php similarity index 92% rename from core/vendor/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php index 78f90b8..24898b7 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php @@ -19,7 +19,18 @@ namespace Symfony\Component\HttpFoundation\SessionStorage; */ class PdoSessionStorage extends NativeSessionStorage { + /** + * PDO instance. + * + * @var \PDO + */ private $db; + + /** + * Database options. + * + * @var array + */ private $dbOptions; /** @@ -139,11 +150,10 @@ class PdoSessionStorage extends NativeSessionStorage $dbTable = $this->dbOptions['db_table']; $dbTimeCol = $this->dbOptions['db_time_col']; - // delete the record associated with this id + // delete the session records that have expired $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < (:time - $lifetime)"; try { - $this->db->query($sql); $stmt = $this->db->prepare($sql); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); @@ -182,7 +192,7 @@ class PdoSessionStorage extends NativeSessionStorage $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM); if (count($sessionRows) == 1) { - return $sessionRows[0][0]; + return base64_decode($sessionRows[0][0]); } // session does not exist, create it @@ -218,9 +228,11 @@ class PdoSessionStorage extends NativeSessionStorage : "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->db->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_STR); + $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); @@ -241,6 +253,8 @@ class PdoSessionStorage extends NativeSessionStorage * * @param string $id * @param string $data + * + * @return boolean True. */ private function createNewSession($id, $data = '') { @@ -252,9 +266,11 @@ class PdoSessionStorage extends NativeSessionStorage $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->db->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_STR); + $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); diff --git a/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php similarity index 100% rename from core/vendor/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php diff --git a/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/StreamedResponse.php b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/StreamedResponse.php new file mode 100644 index 0000000..5684c3c --- /dev/null +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/StreamedResponse.php @@ -0,0 +1,121 @@ + + * + * 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 + * + * @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; + } + + /** + * Sets the PHP callback associated with this Response. + * + * @param mixed $callback A valid PHP callback + */ + public function setCallback($callback) + { + $this->callback = $callback; + if (!is_callable($this->callback)) { + throw new \LogicException('The Response callback must be a valid PHP callable.'); + } + } + + /** + * @{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; + } +} diff --git a/core/vendor/Symfony/Component/HttpFoundation/composer.json b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/composer.json similarity index 74% rename from core/vendor/Symfony/Component/HttpFoundation/composer.json rename to core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/composer.json index b3cfbbd..09b13f5 100644 --- a/core/vendor/Symfony/Component/HttpFoundation/composer.json +++ b/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/composer.json @@ -4,7 +4,7 @@ "description": "Symfony HttpFoundation Component", "keywords": [], "homepage": "http://symfony.com", - "version": "2.0.4", + "version": "2.1.0", "license": "MIT", "authors": [ { @@ -18,5 +18,9 @@ ], "require": { "php": ">=5.3.2" - } + }, + "autoload": { + "psr-0": { "Symfony\\Component\\HttpFoundation": "" } + }, + "target-dir": "Symfony/Component/HttpFoundation" } -- 1.7.4.1