Merge branch '2.8'
Conflicts: composer.json src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml src/Symfony/Bundle/FrameworkBundle/Resources/config/security_csrf.xml src/Symfony/Bundle/FrameworkBundle/composer.json src/Symfony/Component/DependencyInjection/ContainerBuilder.php src/Symfony/Component/Security/Core/composer.json src/Symfony/Component/Security/Csrf/composer.json src/Symfony/Component/Security/Http/composer.json src/Symfony/Component/Security/composer.json src/Symfony/Component/Translation/PluralizationRules.php src/Symfony/Component/VarDumper/Exception/ThrowingCasterException.php
This commit is contained in:
commit
6005fe53f7
26
appveyor.yml
26
appveyor.yml
|
@ -13,7 +13,7 @@ init:
|
|||
- SET SYMFONY_DEPRECATIONS_HELPER=strict
|
||||
- SET PHP=1
|
||||
- SET ANSICON=121x90 (121x90)
|
||||
- SET PHP_INI_MATRIX=php.ini-min-ext php.ini-max-ext
|
||||
- SET PHP_INI_MATRIX=php.ini-min php.ini-max
|
||||
|
||||
install:
|
||||
- IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php)
|
||||
|
@ -21,19 +21,19 @@ install:
|
|||
- IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.5.9-nts-Win32-VC11-x86.zip
|
||||
- IF %PHP%==1 7z x php-5.5.9-nts-Win32-VC11-x86.zip -y > 7z.log
|
||||
- IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat
|
||||
- IF %PHP%==1 copy /Y php.ini-development php.ini-min-ext
|
||||
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini-min-ext
|
||||
- IF %PHP%==1 echo extension_dir=ext >> php.ini-min-ext
|
||||
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini-min-ext
|
||||
- IF %PHP%==1 copy /Y php.ini-min-ext php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_apc.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_intl.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_pdo_sqlite.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 echo extension=php_ldap.dll >> php.ini-max-ext
|
||||
- IF %PHP%==1 copy /Y php.ini-development php.ini-min
|
||||
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini-min
|
||||
- IF %PHP%==1 echo extension_dir=ext >> php.ini-min
|
||||
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini-min
|
||||
- IF %PHP%==1 copy /Y php.ini-min php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_apc.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_intl.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_pdo_sqlite.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_ldap.dll >> php.ini-max
|
||||
- appveyor DownloadFile https://getcomposer.org/composer.phar
|
||||
- copy /Y php.ini-max-ext php.ini
|
||||
- copy /Y php.ini-max php.ini
|
||||
- cd c:\projects\symfony
|
||||
- php phpunit install
|
||||
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
"php": ">=5.5.9",
|
||||
"doctrine/common": "~2.4",
|
||||
"twig/twig": "~1.20|~2.0",
|
||||
"psr/log": "~1.0"
|
||||
"psr/log": "~1.0",
|
||||
"paragonie/random_compat": "~1.0"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/asset": "self.version",
|
||||
|
|
4
phpunit
4
phpunit
|
@ -24,10 +24,6 @@ if (!file_exists($COMPOSER = __DIR__.'/composer.phar')) {
|
|||
$PHP = ProcessUtils::escapeArgument($PHP);
|
||||
$COMPOSER = $PHP.' '.ProcessUtils::escapeArgument($COMPOSER);
|
||||
|
||||
if (!(isset($argv[1]) && 'install' === $argv[1]) && !file_exists(__DIR__.'/vendor')) {
|
||||
passthru("$COMPOSER update --no-progress --ansi");
|
||||
}
|
||||
|
||||
if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit")) {
|
||||
// Build a standalone phpunit without symfony/yaml
|
||||
|
||||
|
|
|
@ -87,8 +87,6 @@ class FrameworkExtension extends Extension
|
|||
$this->registerRequestConfiguration($config['request'], $container, $loader);
|
||||
}
|
||||
|
||||
$loader->load('security.xml');
|
||||
|
||||
if ($this->isConfigEnabled($container, $config['form'])) {
|
||||
$this->formConfigEnabled = true;
|
||||
$this->registerFormConfiguration($config, $container, $loader);
|
||||
|
@ -809,22 +807,22 @@ class FrameworkExtension extends Extension
|
|||
{
|
||||
$loader->load('annotations.xml');
|
||||
|
||||
if ('file' === $config['cache']) {
|
||||
$cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
|
||||
if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir));
|
||||
if ('none' !== $config['cache']) {
|
||||
if ('file' === $config['cache']) {
|
||||
$cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
|
||||
if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir));
|
||||
}
|
||||
|
||||
$container
|
||||
->getDefinition('annotations.php_file_cache')
|
||||
->replaceArgument(0, $cacheDir)
|
||||
;
|
||||
}
|
||||
|
||||
$container
|
||||
->getDefinition('annotations.file_cache_reader')
|
||||
->replaceArgument(1, $cacheDir)
|
||||
->replaceArgument(2, $config['debug'])
|
||||
;
|
||||
$container->setAlias('annotation_reader', 'annotations.file_cache_reader');
|
||||
} elseif ('none' !== $config['cache']) {
|
||||
$container
|
||||
->getDefinition('annotations.cached_reader')
|
||||
->replaceArgument(1, new Reference($config['cache']))
|
||||
->replaceArgument(1, new Reference('file' !== $config['cache'] ? $config['cache'] : 'annotations.php_file_cache'))
|
||||
->replaceArgument(2, $config['debug'])
|
||||
;
|
||||
$container->setAlias('annotation_reader', 'annotations.cached_reader');
|
||||
|
|
|
@ -13,10 +13,8 @@
|
|||
<argument /><!-- Debug-Flag -->
|
||||
</service>
|
||||
|
||||
<service id="annotations.file_cache_reader" class="Doctrine\Common\Annotations\FileCacheReader" public="false">
|
||||
<argument type="service" id="annotations.reader" />
|
||||
<service id="annotations.php_file_cache" class="Doctrine\Common\Cache\PhpFileCache" public="false">
|
||||
<argument /><!-- Cache-Directory -->
|
||||
<argument /><!-- Debug Flag -->
|
||||
</service>
|
||||
|
||||
<service id="annotation_reader" alias="annotations.reader" />
|
||||
|
|
|
@ -47,9 +47,7 @@
|
|||
</service>
|
||||
|
||||
<service id="routing.loader" class="Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader">
|
||||
<tag name="monolog.logger" channel="router" />
|
||||
<argument type="service" id="controller_name_converter" />
|
||||
<argument type="service" id="logger" on-invalid="null" />
|
||||
<argument type="service" id="routing.resolver" />
|
||||
</service>
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<!-- Pseudo-Random Number Generator -->
|
||||
<service id="security.secure_random" class="Symfony\Component\Security\Core\Util\SecureRandom">
|
||||
<tag name="monolog.logger" channel="security" />
|
||||
<argument>%kernel.cache_dir%/secure_random.seed</argument>
|
||||
<argument type="service" id="logger" on-invalid="ignore" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
|
@ -5,9 +5,7 @@
|
|||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<service id="security.csrf.token_generator" class="Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator" public="false">
|
||||
<argument type="service" id="security.secure_random" />
|
||||
</service>
|
||||
<service id="security.csrf.token_generator" class="Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator" public="false" />
|
||||
|
||||
<service id="security.csrf.token_storage" class="Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage" public="false">
|
||||
<argument type="service" id="session" />
|
||||
|
|
|
@ -15,7 +15,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
|||
use Symfony\Component\Config\Exception\FileLoaderLoadException;
|
||||
use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
|
||||
use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* DelegatingLoader delegates route loading to other loaders using a loader resolver.
|
||||
|
@ -28,20 +27,17 @@ use Psr\Log\LoggerInterface;
|
|||
class DelegatingLoader extends BaseDelegatingLoader
|
||||
{
|
||||
protected $parser;
|
||||
protected $logger;
|
||||
private $loading = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ControllerNameParser $parser A ControllerNameParser instance
|
||||
* @param LoggerInterface $logger A LoggerInterface instance
|
||||
* @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
|
||||
*/
|
||||
public function __construct(ControllerNameParser $parser, LoggerInterface $logger = null, LoaderResolverInterface $resolver)
|
||||
public function __construct(ControllerNameParser $parser, LoaderResolverInterface $resolver)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
$this->logger = $logger;
|
||||
|
||||
parent::__construct($resolver);
|
||||
}
|
||||
|
|
|
@ -69,13 +69,6 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||
$this->assertTrue($container->hasDefinition('security.csrf.token_manager'));
|
||||
}
|
||||
|
||||
public function testSecureRandomIsAvailableIfCsrfIsDisabled()
|
||||
{
|
||||
$container = $this->createContainerFromFile('csrf_disabled');
|
||||
|
||||
$this->assertTrue($container->hasDefinition('security.secure_random'));
|
||||
}
|
||||
|
||||
public function testProxies()
|
||||
{
|
||||
$container = $this->createContainerFromFile('full');
|
||||
|
@ -319,8 +312,9 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||
{
|
||||
$container = $this->createContainerFromFile('full');
|
||||
|
||||
$this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.file_cache_reader')->getArgument(1));
|
||||
$this->assertInstanceOf('Doctrine\Common\Annotations\FileCacheReader', $container->get('annotation_reader'));
|
||||
$this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.php_file_cache')->getArgument(0));
|
||||
$this->assertSame('annotations.cached_reader', (string) $container->getAlias('annotation_reader'));
|
||||
$this->assertSame('annotations.php_file_cache', (string) $container->getDefinition('annotations.cached_reader')->getArgument(1));
|
||||
}
|
||||
|
||||
public function testFileLinkFormat()
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
||||
use Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader;
|
||||
use Symfony\Component\Config\Loader\LoaderResolver;
|
||||
|
||||
class DelegatingLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConstructorApi()
|
||||
{
|
||||
$controllerNameParser = $this->getMockBuilder(ControllerNameParser::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
new DelegatingLoader($controllerNameParser, new LoaderResolver());
|
||||
$this->assertTrue(true, '__construct() takes a ControllerNameParser and LoaderResolverInterface respectively as its first and second argument.');
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
"symfony/stopwatch": "~2.8|~3.0",
|
||||
"symfony/templating": "~2.8|~3.0",
|
||||
"symfony/translation": "~2.8|~3.0",
|
||||
"doctrine/cache": "~1.0",
|
||||
"doctrine/annotations": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
@ -164,6 +164,6 @@ EOF
|
|||
|
||||
private function generateSalt()
|
||||
{
|
||||
return base64_encode($this->getContainer()->get('security.secure_random')->nextBytes(30));
|
||||
return base64_encode(random_bytes(30));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,7 @@
|
|||
<service id="security.authentication.rememberme.services.persistent"
|
||||
class="Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices"
|
||||
parent="security.authentication.rememberme.services.abstract"
|
||||
abstract="true">
|
||||
<argument type="service" id="security.secure_random" />
|
||||
</service>
|
||||
abstract="true" />
|
||||
|
||||
<service id="security.authentication.rememberme.services.simplehash"
|
||||
class="Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices"
|
||||
|
|
|
@ -91,12 +91,16 @@ class ClassLoader
|
|||
return;
|
||||
}
|
||||
if (isset($this->prefixes[$prefix])) {
|
||||
$this->prefixes[$prefix] = array_merge(
|
||||
$this->prefixes[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
if (is_array($paths)) {
|
||||
$this->prefixes[$prefix] = array_unique(array_merge(
|
||||
$this->prefixes[$prefix],
|
||||
$paths
|
||||
));
|
||||
} elseif (!in_array($paths, $this->prefixes[$prefix])) {
|
||||
$this->prefixes[$prefix][] = $paths;
|
||||
}
|
||||
} else {
|
||||
$this->prefixes[$prefix] = (array) $paths;
|
||||
$this->prefixes[$prefix] = array_unique((array) $paths);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,14 +76,36 @@ class ClassLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
);
|
||||
}
|
||||
|
||||
public function testAddPrefix()
|
||||
public function testAddPrefixSingle()
|
||||
{
|
||||
$loader = new ClassLoader();
|
||||
$loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
|
||||
$loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
|
||||
$prefixes = $loader->getPrefixes();
|
||||
$this->assertArrayHasKey('Foo', $prefixes);
|
||||
$this->assertCount(1, $prefixes['Foo']);
|
||||
}
|
||||
|
||||
public function testAddPrefixesSingle()
|
||||
{
|
||||
$loader = new ClassLoader();
|
||||
$loader->addPrefixes(array('Foo' => array('foo', 'foo')));
|
||||
$loader->addPrefixes(array('Foo' => array('foo')));
|
||||
$prefixes = $loader->getPrefixes();
|
||||
$this->assertArrayHasKey('Foo', $prefixes);
|
||||
$this->assertCount(1, $prefixes['Foo'], print_r($prefixes, true));
|
||||
}
|
||||
|
||||
public function testAddPrefixMulti()
|
||||
{
|
||||
$loader = new ClassLoader();
|
||||
$loader->addPrefix('Foo', 'foo');
|
||||
$loader->addPrefix('Foo', 'bar');
|
||||
$prefixes = $loader->getPrefixes();
|
||||
$this->assertArrayHasKey('Foo', $prefixes);
|
||||
$this->assertCount(2, $prefixes['Foo']);
|
||||
$this->assertContains('foo', $prefixes['Foo']);
|
||||
$this->assertContains('bar', $prefixes['Foo']);
|
||||
}
|
||||
|
||||
public function testUseIncludePath()
|
||||
|
|
|
@ -137,15 +137,17 @@ class ApplicationDescription
|
|||
private function sortCommands(array $commands)
|
||||
{
|
||||
$namespacedCommands = array();
|
||||
$globalCommands = array();
|
||||
foreach ($commands as $name => $command) {
|
||||
$key = $this->application->extractNamespace($name, 1);
|
||||
if (!$key) {
|
||||
$key = '_global';
|
||||
$globalCommands['_global'][$name] = $command;
|
||||
} else {
|
||||
$namespacedCommands[$key][$name] = $command;
|
||||
}
|
||||
|
||||
$namespacedCommands[$key][$name] = $command;
|
||||
}
|
||||
ksort($namespacedCommands);
|
||||
$namespacedCommands = array_merge($globalCommands, $namespacedCommands);
|
||||
|
||||
foreach ($namespacedCommands as &$commandsSet) {
|
||||
ksort($commandsSet);
|
||||
|
|
|
@ -20,6 +20,7 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
|||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Саша Стаменковић <umpirsky@gmail.com>
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
* @author Max Grigorian <maxakawizard@gmail.com>
|
||||
*/
|
||||
class Table
|
||||
{
|
||||
|
@ -61,6 +62,11 @@ class Table
|
|||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $columnStyles = array();
|
||||
|
||||
private static $styles;
|
||||
|
||||
public function __construct(OutputInterface $output)
|
||||
|
@ -139,6 +145,47 @@ class Table
|
|||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets table column style.
|
||||
*
|
||||
* @param int $columnIndex Column index
|
||||
* @param TableStyle|string $name The style name or a TableStyle instance
|
||||
*
|
||||
* @return Table
|
||||
*/
|
||||
public function setColumnStyle($columnIndex, $name)
|
||||
{
|
||||
$columnIndex = intval($columnIndex);
|
||||
|
||||
if ($name instanceof TableStyle) {
|
||||
$this->columnStyles[$columnIndex] = $name;
|
||||
} elseif (isset(self::$styles[$name])) {
|
||||
$this->columnStyles[$columnIndex] = self::$styles[$name];
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current style for a column.
|
||||
*
|
||||
* If style was not set, it returns the global table style.
|
||||
*
|
||||
* @param int $columnIndex Column index
|
||||
*
|
||||
* @return TableStyle
|
||||
*/
|
||||
public function getColumnStyle($columnIndex)
|
||||
{
|
||||
if (isset($this->columnStyles[$columnIndex])) {
|
||||
return $this->columnStyles[$columnIndex];
|
||||
}
|
||||
|
||||
return $this->getStyle();
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$headers = array_values($headers);
|
||||
|
@ -308,12 +355,14 @@ class Table
|
|||
$width += strlen($cell) - mb_strwidth($cell, $encoding);
|
||||
}
|
||||
|
||||
$style = $this->getColumnStyle($column);
|
||||
|
||||
if ($cell instanceof TableSeparator) {
|
||||
$this->output->write(sprintf($this->style->getBorderFormat(), str_repeat($this->style->getHorizontalBorderChar(), $width)));
|
||||
$this->output->write(sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width)));
|
||||
} else {
|
||||
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
|
||||
$content = sprintf($this->style->getCellRowContentFormat(), $cell);
|
||||
$this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->style->getPaddingChar(), $this->style->getPadType())));
|
||||
$content = sprintf($style->getCellRowContentFormat(), $cell);
|
||||
$this->output->write(sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,4 +61,52 @@ EOF;
|
|||
|
||||
$this->assertEquals($output, $commandTester->getDisplay(true));
|
||||
}
|
||||
|
||||
public function testExecuteListsCommandsOrder()
|
||||
{
|
||||
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
|
||||
$application = new Application();
|
||||
$application->add(new \Foo6Command());
|
||||
$commandTester = new CommandTester($command = $application->get('list'));
|
||||
$commandTester->execute(array('command' => $command->getName()), array('decorated' => false));
|
||||
$output = <<<EOF
|
||||
Console Tool
|
||||
|
||||
Usage:
|
||||
command [options] [arguments]
|
||||
|
||||
Options:
|
||||
-h, --help Display this help message
|
||||
-q, --quiet Do not output any message
|
||||
-V, --version Display this application version
|
||||
--ansi Force ANSI output
|
||||
--no-ansi Disable ANSI output
|
||||
-n, --no-interaction Do not ask any interactive question
|
||||
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
|
||||
|
||||
Available commands:
|
||||
help Displays help for a command
|
||||
list Lists commands
|
||||
0foo
|
||||
0foo:bar 0foo:bar command
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($output, trim($commandTester->getDisplay(true)));
|
||||
}
|
||||
|
||||
public function testExecuteListsCommandsOrderRaw()
|
||||
{
|
||||
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
|
||||
$application = new Application();
|
||||
$application->add(new \Foo6Command());
|
||||
$commandTester = new CommandTester($command = $application->get('list'));
|
||||
$commandTester->execute(array('command' => $command->getName(), '--raw' => true));
|
||||
$output = <<<EOF
|
||||
help Displays help for a command
|
||||
list Lists commands
|
||||
0foo:bar 0foo:bar command
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($output, trim($commandTester->getDisplay(true)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
class Foo6Command extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('0foo:bar')->setDescription('0foo:bar command');
|
||||
}
|
||||
}
|
|
@ -576,6 +576,36 @@ TABLE;
|
|||
| foo |
|
||||
+---+--+
|
||||
|
||||
TABLE;
|
||||
|
||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||
}
|
||||
|
||||
public function testColumnStyle()
|
||||
{
|
||||
$table = new Table($output = $this->getOutputStream());
|
||||
$table
|
||||
->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
|
||||
->setRows(array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
|
||||
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
|
||||
));
|
||||
|
||||
$style = new TableStyle();
|
||||
$style->setPadType(STR_PAD_LEFT);
|
||||
$table->setColumnStyle(3, $style);
|
||||
|
||||
$table->render();
|
||||
|
||||
$expected =
|
||||
<<<TABLE
|
||||
+---------------+----------------------+-----------------+--------+
|
||||
| ISBN | Title | Author | Price |
|
||||
+---------------+----------------------+-----------------+--------+
|
||||
| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
|
||||
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
|
||||
+---------------+----------------------+-----------------+--------+
|
||||
|
||||
TABLE;
|
||||
|
||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||
|
|
|
@ -845,10 +845,22 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
|||
}
|
||||
|
||||
$service = call_user_func_array($factory, $arguments);
|
||||
|
||||
if (!$definition->isDeprecated() && is_array($factory) && is_string($factory[0])) {
|
||||
$r = new \ReflectionClass($factory[0]);
|
||||
|
||||
if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
|
||||
@trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
|
||||
|
||||
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
|
||||
|
||||
if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
|
||||
@trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
if ($tryProxy || !$definition->isLazy()) {
|
||||
|
|
|
@ -417,7 +417,7 @@ class Filesystem
|
|||
}
|
||||
} else {
|
||||
if (is_link($file)) {
|
||||
$this->symlink($file->getRealPath(), $target);
|
||||
$this->symlink($file->getLinkTarget(), $target);
|
||||
} elseif (is_dir($file)) {
|
||||
$this->mkdir($target);
|
||||
} elseif (is_file($file)) {
|
||||
|
|
|
@ -915,7 +915,7 @@ class FilesystemTest extends FilesystemTestCase
|
|||
$this->assertTrue(is_dir($targetPath));
|
||||
$this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
|
||||
$this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
|
||||
$this->assertEquals($sourcePath.'nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1'));
|
||||
$this->assertEquals('nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"php": ">=5.5.9",
|
||||
"ext-ldap": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7|~3.0.0"
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Ldap\\": "" }
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
||||
"symfony/serializer": "~2.7|~3.0.0",
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0",
|
||||
"symfony/serializer": "~2.8|~3.0",
|
||||
"phpdocumentor/reflection": "^1.0.7",
|
||||
"doctrine/annotations": "~1.0"
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ CHANGELOG
|
|||
`Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface` instead
|
||||
* deprecated `Symfony\Component\Security\Core\Util\ClassUtils`, use
|
||||
`Symfony\Component\Security\Acl\Util\ClassUtils` instead
|
||||
* deprecated the `Symfony\Component\Security\Core\Util\SecureRandom` class in favor of the `random_bytes()` function
|
||||
* deprecated `supportsAttribute()` and `supportsClass()` methods of
|
||||
`Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface` and
|
||||
`Symfony\Component\Security\Core\Authorization\Voter\VoterInterface`.
|
||||
|
|
|
@ -66,7 +66,7 @@ class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
|
|||
protected function getVoterFor2Roles($token, $vote1, $vote2)
|
||||
{
|
||||
$voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
|
||||
$voter->expects($this->exactly(2))
|
||||
$voter->expects($this->any())
|
||||
->method('vote')
|
||||
->will($this->returnValueMap(array(
|
||||
array($token, null, array('ROLE_FOO'), $vote1),
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Core\Tests\Util;
|
||||
|
||||
use Symfony\Component\Security\Core\Util\SecureRandom;
|
||||
|
||||
class SecureRandomTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* T1: Monobit test.
|
||||
*
|
||||
* @dataProvider getSecureRandoms
|
||||
*/
|
||||
public function testMonobit($secureRandom)
|
||||
{
|
||||
$nbOnBits = substr_count($this->getBitSequence($secureRandom, 20000), '1');
|
||||
$this->assertTrue($nbOnBits > 9654 && $nbOnBits < 10346, 'Monobit test failed, number of turned on bits: '.$nbOnBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* T2: Chi-square test with 15 degrees of freedom (chi-Quadrat-Anpassungstest).
|
||||
*
|
||||
* @dataProvider getSecureRandoms
|
||||
*/
|
||||
public function testPoker($secureRandom)
|
||||
{
|
||||
$b = $this->getBitSequence($secureRandom, 20000);
|
||||
$c = array();
|
||||
for ($i = 0; $i <= 15; ++$i) {
|
||||
$c[$i] = 0;
|
||||
}
|
||||
|
||||
for ($j = 1; $j <= 5000; ++$j) {
|
||||
$k = 4 * $j - 1;
|
||||
++$c[8 * $b[$k - 3] + 4 * $b[$k - 2] + 2 * $b[$k - 1] + $b[$k]];
|
||||
}
|
||||
|
||||
$f = 0;
|
||||
for ($i = 0; $i <= 15; ++$i) {
|
||||
$f += $c[$i] * $c[$i];
|
||||
}
|
||||
|
||||
$Y = 16 / 5000 * $f - 5000;
|
||||
|
||||
$this->assertTrue($Y > 1.03 && $Y < 57.4, 'Poker test failed, Y = '.$Y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run test.
|
||||
*
|
||||
* @dataProvider getSecureRandoms
|
||||
*/
|
||||
public function testRun($secureRandom)
|
||||
{
|
||||
$b = $this->getBitSequence($secureRandom, 20000);
|
||||
|
||||
$runs = array();
|
||||
for ($i = 1; $i <= 6; ++$i) {
|
||||
$runs[$i] = 0;
|
||||
}
|
||||
|
||||
$addRun = function ($run) use (&$runs) {
|
||||
if ($run > 6) {
|
||||
$run = 6;
|
||||
}
|
||||
|
||||
++$runs[$run];
|
||||
};
|
||||
|
||||
$currentRun = 0;
|
||||
$lastBit = null;
|
||||
for ($i = 0; $i < 20000; ++$i) {
|
||||
if ($lastBit === $b[$i]) {
|
||||
++$currentRun;
|
||||
} else {
|
||||
if ($currentRun > 0) {
|
||||
$addRun($currentRun);
|
||||
}
|
||||
|
||||
$lastBit = $b[$i];
|
||||
$currentRun = 0;
|
||||
}
|
||||
}
|
||||
if ($currentRun > 0) {
|
||||
$addRun($currentRun);
|
||||
}
|
||||
|
||||
$this->assertTrue($runs[1] > 2267 && $runs[1] < 2733, 'Runs of length 1 outside of defined interval: '.$runs[1]);
|
||||
$this->assertTrue($runs[2] > 1079 && $runs[2] < 1421, 'Runs of length 2 outside of defined interval: '.$runs[2]);
|
||||
$this->assertTrue($runs[3] > 502 && $runs[3] < 748, 'Runs of length 3 outside of defined interval: '.$runs[3]);
|
||||
$this->assertTrue($runs[4] > 233 && $runs[4] < 402, 'Runs of length 4 outside of defined interval: '.$runs[4]);
|
||||
$this->assertTrue($runs[5] > 90 && $runs[5] < 223, 'Runs of length 5 outside of defined interval: '.$runs[5]);
|
||||
$this->assertTrue($runs[6] > 90 && $runs[6] < 233, 'Runs of length 6 outside of defined interval: '.$runs[6]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Long-run test.
|
||||
*
|
||||
* @dataProvider getSecureRandoms
|
||||
*/
|
||||
public function testLongRun($secureRandom)
|
||||
{
|
||||
$b = $this->getBitSequence($secureRandom, 20000);
|
||||
|
||||
$longestRun = $currentRun = 0;
|
||||
$lastBit = null;
|
||||
for ($i = 0; $i < 20000; ++$i) {
|
||||
if ($lastBit === $b[$i]) {
|
||||
++$currentRun;
|
||||
} else {
|
||||
if ($currentRun > $longestRun) {
|
||||
$longestRun = $currentRun;
|
||||
}
|
||||
$lastBit = $b[$i];
|
||||
$currentRun = 0;
|
||||
}
|
||||
}
|
||||
if ($currentRun > $longestRun) {
|
||||
$longestRun = $currentRun;
|
||||
}
|
||||
|
||||
$this->assertTrue($longestRun < 34, 'Failed longest run test: '.$longestRun);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serial Correlation (Autokorrelationstest).
|
||||
*
|
||||
* @dataProvider getSecureRandoms
|
||||
*/
|
||||
public function testSerialCorrelation($secureRandom)
|
||||
{
|
||||
$shift = mt_rand(1, 5000);
|
||||
$b = $this->getBitSequence($secureRandom, 20000);
|
||||
|
||||
$Z = 0;
|
||||
for ($i = 0; $i < 5000; ++$i) {
|
||||
$Z += $b[$i] === $b[$i + $shift] ? 1 : 0;
|
||||
}
|
||||
|
||||
$this->assertTrue($Z > 2326 && $Z < 2674, 'Failed serial correlation test: '.$Z);
|
||||
}
|
||||
|
||||
public function getSecureRandoms()
|
||||
{
|
||||
$secureRandoms = array();
|
||||
|
||||
// only add if openssl is indeed present
|
||||
$secureRandom = new SecureRandom();
|
||||
if ($this->hasOpenSsl($secureRandom)) {
|
||||
$secureRandoms[] = array($secureRandom);
|
||||
}
|
||||
|
||||
// no-openssl with custom seed provider
|
||||
$secureRandom = new SecureRandom(sys_get_temp_dir().'/_sf2.seed');
|
||||
$this->disableOpenSsl($secureRandom);
|
||||
$secureRandoms[] = array($secureRandom);
|
||||
|
||||
return $secureRandoms;
|
||||
}
|
||||
|
||||
protected function disableOpenSsl($secureRandom)
|
||||
{
|
||||
$ref = new \ReflectionProperty($secureRandom, 'useOpenSsl');
|
||||
$ref->setAccessible(true);
|
||||
$ref->setValue($secureRandom, false);
|
||||
$ref->setAccessible(false);
|
||||
}
|
||||
|
||||
protected function hasOpenSsl($secureRandom)
|
||||
{
|
||||
$ref = new \ReflectionProperty($secureRandom, 'useOpenSsl');
|
||||
$ref->setAccessible(true);
|
||||
|
||||
$ret = $ref->getValue($secureRandom);
|
||||
|
||||
$ref->setAccessible(false);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function getBitSequence($secureRandom, $length)
|
||||
{
|
||||
$bitSequence = '';
|
||||
for ($i = 0; $i < $length; $i += 40) {
|
||||
$value = unpack('H*', $secureRandom->nextBytes(5));
|
||||
$value = str_pad(base_convert($value[1], 16, 2), 40, '0', STR_PAD_LEFT);
|
||||
$bitSequence .= $value;
|
||||
}
|
||||
|
||||
return substr($bitSequence, 0, $length);
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Core\Util;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* A secure random number generator implementation.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
final class SecureRandom implements SecureRandomInterface
|
||||
{
|
||||
private $logger;
|
||||
private $useOpenSsl;
|
||||
private $seed;
|
||||
private $seedUpdated;
|
||||
private $seedLastUpdatedAt;
|
||||
private $seedFile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Be aware that a guessable seed will severely compromise the PRNG
|
||||
* algorithm that is employed.
|
||||
*
|
||||
* @param string $seedFile
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct($seedFile = null, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->seedFile = $seedFile;
|
||||
$this->logger = $logger;
|
||||
|
||||
// determine whether to use OpenSSL
|
||||
if (!function_exists('random_bytes') && !function_exists('openssl_random_pseudo_bytes')) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->notice('It is recommended that you install the "paragonie/random_compat" library or enable the "openssl" extension for random number generation.');
|
||||
}
|
||||
$this->useOpenSsl = false;
|
||||
} else {
|
||||
$this->useOpenSsl = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function nextBytes($nbBytes)
|
||||
{
|
||||
if (function_exists('random_bytes')) {
|
||||
return random_bytes($nbBytes);
|
||||
}
|
||||
|
||||
// try OpenSSL
|
||||
if ($this->useOpenSsl) {
|
||||
$bytes = openssl_random_pseudo_bytes($nbBytes, $strong);
|
||||
|
||||
if (false !== $bytes && true === $strong) {
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('OpenSSL did not produce a secure random number.');
|
||||
}
|
||||
}
|
||||
|
||||
// initialize seed
|
||||
if (null === $this->seed) {
|
||||
if (null === $this->seedFile) {
|
||||
throw new \RuntimeException('You need to specify a file path to store the seed.');
|
||||
}
|
||||
|
||||
if (is_file($this->seedFile)) {
|
||||
list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed();
|
||||
} else {
|
||||
$this->seed = uniqid(mt_rand(), true);
|
||||
$this->updateSeed();
|
||||
}
|
||||
}
|
||||
|
||||
$bytes = '';
|
||||
while (strlen($bytes) < $nbBytes) {
|
||||
static $incr = 1;
|
||||
$bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true);
|
||||
$this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true));
|
||||
$this->updateSeed();
|
||||
}
|
||||
|
||||
return substr($bytes, 0, $nbBytes);
|
||||
}
|
||||
|
||||
private function readSeed()
|
||||
{
|
||||
return json_decode(file_get_contents($this->seedFile));
|
||||
}
|
||||
|
||||
private function updateSeed()
|
||||
{
|
||||
if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) {
|
||||
file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true))));
|
||||
}
|
||||
|
||||
$this->seedUpdated = true;
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Core\Util;
|
||||
|
||||
/**
|
||||
* Interface that needs to be implemented by all secure random number generators.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface SecureRandomInterface
|
||||
{
|
||||
/**
|
||||
* Generates the specified number of secure random bytes.
|
||||
*
|
||||
* @param int $nbBytes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function nextBytes($nbBytes);
|
||||
}
|
|
@ -16,7 +16,8 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
"php": ">=5.5.9",
|
||||
"paragonie/random_compat" : "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0",
|
||||
|
@ -25,8 +26,8 @@
|
|||
"symfony/http-foundation": "~2.8|~3.0",
|
||||
"symfony/translation": "~2.8|~3.0",
|
||||
"symfony/validator": "~2.8|~3.0",
|
||||
"psr/log": "~1.0",
|
||||
"symfony/ldap": "~2.8|~3.0.0"
|
||||
"symfony/ldap": "~2.8|~3.0",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/event-dispatcher": "",
|
||||
|
|
|
@ -27,11 +27,6 @@ class UriSafeTokenGeneratorTest extends \PHPUnit_Framework_TestCase
|
|||
*/
|
||||
private static $bytes;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
private $random;
|
||||
|
||||
/**
|
||||
* @var UriSafeTokenGenerator
|
||||
*/
|
||||
|
@ -44,23 +39,16 @@ class UriSafeTokenGeneratorTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->random = $this->getMock('Symfony\Component\Security\Core\Util\SecureRandomInterface');
|
||||
$this->generator = new UriSafeTokenGenerator($this->random, self::ENTROPY);
|
||||
$this->generator = new UriSafeTokenGenerator(self::ENTROPY);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->random = null;
|
||||
$this->generator = null;
|
||||
}
|
||||
|
||||
public function testGenerateToken()
|
||||
{
|
||||
$this->random->expects($this->once())
|
||||
->method('nextBytes')
|
||||
->with(self::ENTROPY / 8)
|
||||
->will($this->returnValue(self::$bytes));
|
||||
|
||||
$token = $this->generator->generateToken();
|
||||
|
||||
$this->assertTrue(ctype_print($token), 'is printable');
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
|
||||
namespace Symfony\Component\Security\Csrf\TokenGenerator;
|
||||
|
||||
use Symfony\Component\Security\Core\Util\SecureRandomInterface;
|
||||
use Symfony\Component\Security\Core\Util\SecureRandom;
|
||||
|
||||
/**
|
||||
* Generates CSRF tokens.
|
||||
*
|
||||
|
@ -23,13 +20,6 @@ use Symfony\Component\Security\Core\Util\SecureRandom;
|
|||
*/
|
||||
class UriSafeTokenGenerator implements TokenGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* The generator for random values.
|
||||
*
|
||||
* @var SecureRandomInterface
|
||||
*/
|
||||
private $random;
|
||||
|
||||
/**
|
||||
* The amount of entropy collected for each token (in bits).
|
||||
*
|
||||
|
@ -40,14 +30,10 @@ class UriSafeTokenGenerator implements TokenGeneratorInterface
|
|||
/**
|
||||
* Generates URI-safe CSRF tokens.
|
||||
*
|
||||
* @param SecureRandomInterface|null $random The random value generator used for
|
||||
* generating entropy
|
||||
* @param int $entropy The amount of entropy collected for
|
||||
* each token (in bits)
|
||||
* @param int $entropy The amount of entropy collected for each token (in bits)
|
||||
*/
|
||||
public function __construct(SecureRandomInterface $random = null, $entropy = 256)
|
||||
public function __construct($entropy = 256)
|
||||
{
|
||||
$this->random = $random ?: new SecureRandom();
|
||||
$this->entropy = $entropy;
|
||||
}
|
||||
|
||||
|
@ -59,7 +45,7 @@ class UriSafeTokenGenerator implements TokenGeneratorInterface
|
|||
// Generate an URI safe base64 encoded string that does not contain "+",
|
||||
// "/" or "=" which need to be URL encoded and make URLs unnecessarily
|
||||
// longer.
|
||||
$bytes = $this->random->nextBytes($this->entropy / 8);
|
||||
$bytes = random_bytes($this->entropy / 8);
|
||||
|
||||
return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/security-core": "~2.8|~3.0"
|
||||
"symfony/security-core": "~2.8|~3.0",
|
||||
"paragonie/random_compat" : "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0",
|
||||
|
|
|
@ -35,7 +35,10 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
|
|||
const COOKIE_DELIMITER = ':';
|
||||
|
||||
protected $logger;
|
||||
protected $options;
|
||||
protected $options = array(
|
||||
'secure' => false,
|
||||
'httponly' => true,
|
||||
);
|
||||
private $providerKey;
|
||||
private $secret;
|
||||
private $userProviders;
|
||||
|
@ -66,7 +69,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
|
|||
$this->userProviders = $userProviders;
|
||||
$this->secret = $secret;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->options = $options;
|
||||
$this->options = array_merge($this->options, $options);
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
|||
use Symfony\Component\Security\Core\Exception\CookieTheftException;
|
||||
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Util\SecureRandomInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
|
@ -32,24 +31,6 @@ use Psr\Log\LoggerInterface;
|
|||
class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
|
||||
{
|
||||
private $tokenProvider;
|
||||
private $secureRandom;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $userProviders
|
||||
* @param string $secret
|
||||
* @param string $providerKey
|
||||
* @param array $options
|
||||
* @param LoggerInterface $logger
|
||||
* @param SecureRandomInterface $secureRandom
|
||||
*/
|
||||
public function __construct(array $userProviders, $secret, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom)
|
||||
{
|
||||
parent::__construct($userProviders, $secret, $providerKey, $options, $logger);
|
||||
|
||||
$this->secureRandom = $secureRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the token provider.
|
||||
|
@ -98,7 +79,7 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
|
|||
throw new AuthenticationException('The cookie has expired.');
|
||||
}
|
||||
|
||||
$tokenValue = base64_encode($this->secureRandom->nextBytes(64));
|
||||
$tokenValue = base64_encode(random_bytes(64));
|
||||
$this->tokenProvider->updateToken($series, $tokenValue, new \DateTime());
|
||||
$request->attributes->set(self::COOKIE_ATTR_NAME,
|
||||
new Cookie(
|
||||
|
@ -120,8 +101,8 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
|
|||
*/
|
||||
protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)
|
||||
{
|
||||
$series = base64_encode($this->secureRandom->nextBytes(64));
|
||||
$tokenValue = base64_encode($this->secureRandom->nextBytes(64));
|
||||
$series = base64_encode(random_bytes(64));
|
||||
$tokenValue = base64_encode(random_bytes(64));
|
||||
|
||||
$this->tokenProvider->createNewToken(
|
||||
new PersistentToken(
|
||||
|
|
|
@ -91,11 +91,8 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
|||
$request = new Request();
|
||||
$response = new Response();
|
||||
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
||||
|
||||
$service->logout($request, $response, $token);
|
||||
|
||||
$cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Cookie', $cookie);
|
||||
$this->assertTrue($cookie->isCleared());
|
||||
$this->assertSame($options['name'], $cookie->getName());
|
||||
|
@ -286,13 +283,6 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
|||
$userProvider = $this->getProvider();
|
||||
}
|
||||
|
||||
if (!isset($options['secure'])) {
|
||||
$options['secure'] = false;
|
||||
}
|
||||
if (!isset($options['httponly'])) {
|
||||
$options['httponly'] = true;
|
||||
}
|
||||
|
||||
return $this->getMockForAbstractClass('Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', array(
|
||||
array($userProvider), 'foosecret', 'fookey', $options, $logger,
|
||||
));
|
||||
|
|
|
@ -20,7 +20,6 @@ use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
|||
use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices;
|
||||
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\CookieTheftException;
|
||||
use Symfony\Component\Security\Core\Util\SecureRandom;
|
||||
|
||||
class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
@ -313,14 +312,7 @@ class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_Test
|
|||
$userProvider = $this->getProvider();
|
||||
}
|
||||
|
||||
if (!isset($options['secure'])) {
|
||||
$options['secure'] = false;
|
||||
}
|
||||
if (!isset($options['httponly'])) {
|
||||
$options['httponly'] = true;
|
||||
}
|
||||
|
||||
return new PersistentTokenBasedRememberMeServices(array($userProvider), 'foosecret', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed'));
|
||||
return new PersistentTokenBasedRememberMeServices(array($userProvider), 'foosecret', 'fookey', $options, $logger);
|
||||
}
|
||||
|
||||
protected function getProvider()
|
||||
|
|
|
@ -266,13 +266,6 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
|||
$userProvider = $this->getProvider();
|
||||
}
|
||||
|
||||
if (!isset($options['secure'])) {
|
||||
$options['secure'] = false;
|
||||
}
|
||||
if (!isset($options['httponly'])) {
|
||||
$options['httponly'] = true;
|
||||
}
|
||||
|
||||
$service = new TokenBasedRememberMeServices(array($userProvider), 'foosecret', 'fookey', $options, $logger);
|
||||
|
||||
return $service;
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~2.8|~3.0",
|
||||
"symfony/http-kernel": "~2.8|~3.0",
|
||||
"symfony/property-access": "~2.8|~3.0.0"
|
||||
"symfony/property-access": "~2.8|~3.0",
|
||||
"paragonie/random_compat" : "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0",
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Tests;
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class TranslationSyncStatusTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTranslationDirectoriesData
|
||||
*/
|
||||
public function testTranslationFileIsNotMissingInCore($dir1, $dir2)
|
||||
{
|
||||
$finder = new Finder();
|
||||
$files = $finder->in($dir1)->files();
|
||||
|
||||
foreach ($files as $file) {
|
||||
$this->assertFileExists($dir2.'/'.$file->getFilename(), 'Missing file '.$file->getFilename().' in directory '.$dir2);
|
||||
}
|
||||
}
|
||||
|
||||
public function getTranslationDirectoriesData()
|
||||
{
|
||||
$legacyTranslationsDir = $this->getLegacyTranslationsDirectory();
|
||||
$coreTranslationsDir = $this->getCoreTranslationsDirectory();
|
||||
|
||||
return array(
|
||||
'file-not-missing-in-core' => array($legacyTranslationsDir, $coreTranslationsDir),
|
||||
'file-not-added-in-core' => array($coreTranslationsDir, $legacyTranslationsDir),
|
||||
);
|
||||
}
|
||||
|
||||
public function testFileContentsAreEqual()
|
||||
{
|
||||
$finder = new Finder();
|
||||
$files = $finder->in($this->getLegacyTranslationsDirectory())->files();
|
||||
|
||||
foreach ($files as $file) {
|
||||
$coreFile = $this->getCoreTranslationsDirectory().'/'.$file->getFilename();
|
||||
|
||||
$this->assertFileEquals($file->getRealPath(), $coreFile, $file.' and '.$coreFile.' have equal content.');
|
||||
}
|
||||
}
|
||||
|
||||
private function getLegacyTranslationsDirectory()
|
||||
{
|
||||
return __DIR__.'/../Resources/translations';
|
||||
}
|
||||
|
||||
private function getCoreTranslationsDirectory()
|
||||
{
|
||||
return __DIR__.'/../Core/Resources/translations';
|
||||
}
|
||||
}
|
|
@ -20,7 +20,8 @@
|
|||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~2.8|~3.0",
|
||||
"symfony/http-kernel": "~2.8|~3.0",
|
||||
"symfony/property-access": "~2.8|~3.0.0"
|
||||
"symfony/property-access": "~2.8|~3.0",
|
||||
"paragonie/random_compat" : "~1.0"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/security-core": "self.version",
|
||||
|
@ -29,17 +30,17 @@
|
|||
"symfony/security-http": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
||||
"symfony/intl": "~2.3|~3.0.0",
|
||||
"symfony/routing": "~2.2|~3.0.0",
|
||||
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",
|
||||
"symfony/validator": "~2.5,>=2.5.5|~3.0.0",
|
||||
"symfony/finder": "~2.8|~3.0",
|
||||
"symfony/phpunit-bridge": "~2.8|~3.0",
|
||||
"symfony/intl": "~2.8|~3.0",
|
||||
"symfony/routing": "~2.8|~3.0",
|
||||
"symfony/translation": "~2.8|~3.0",
|
||||
"symfony/validator": "~2.8|~3.0",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"symfony/ldap": "~2.8|~3.0",
|
||||
"doctrine/common": "~2.2",
|
||||
"doctrine/dbal": "~2.2",
|
||||
"psr/log": "~1.0",
|
||||
"ircmaxell/password-compat": "~1.0",
|
||||
"symfony/expression-language": "~2.6|~3.0.0",
|
||||
"symfony/ldap": "~2.8|~3.0.0"
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/class-loader": "For using the ACL generateSql script",
|
||||
|
@ -48,8 +49,6 @@
|
|||
"symfony/validator": "For using the user password constraint",
|
||||
"symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs",
|
||||
"symfony/expression-language": "For using the expression voter",
|
||||
"ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5",
|
||||
"paragonie/random_compat": "",
|
||||
"symfony/ldap": "For using the LDAP user and authentication providers"
|
||||
},
|
||||
"autoload": {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
<testsuites>
|
||||
<testsuite name="Symfony Security Component Test Suite">
|
||||
<directory>./Tests/</directory>
|
||||
<directory>./Acl/Tests/</directory>
|
||||
<directory>./Core/Tests/</directory>
|
||||
<directory>./Http/Tests/</directory>
|
||||
|
@ -24,6 +25,7 @@
|
|||
<directory>./</directory>
|
||||
<exclude>
|
||||
<directory>./vendor</directory>
|
||||
<directory>./Tests</directory>
|
||||
<directory>./Acl/Tests</directory>
|
||||
<directory>./Core/Tests</directory>
|
||||
<directory>./Http/Tests</directory>
|
||||
|
|
|
@ -46,7 +46,7 @@ class UrlValidator extends ConstraintValidator
|
|||
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url');
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
if (null === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,10 @@ class UrlValidator extends ConstraintValidator
|
|||
}
|
||||
|
||||
$value = (string) $value;
|
||||
if ('' === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));
|
||||
|
||||
if (!preg_match($pattern, $value)) {
|
||||
|
|
|
@ -310,6 +310,10 @@
|
|||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>この値は予期される文字コード({{ charset }})と異なります。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="81">
|
||||
<source>This is not a valid Business Identifier Code (BIC).</source>
|
||||
<target>有効なSWIFTコードではありません。</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
@ -36,6 +36,13 @@ class UrlValidatorTest extends AbstractConstraintValidatorTest
|
|||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testEmptyStringFromObjectIsValid()
|
||||
{
|
||||
$this->validator->validate(new EmailProvider(), new Url());
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
|
||||
*/
|
||||
|
@ -173,3 +180,11 @@ class UrlValidatorTest extends AbstractConstraintValidatorTest
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EmailProvider
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,15 @@ abstract class VarDumperTestCase extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
public function assertDumpEquals($dump, $data, $message = '')
|
||||
{
|
||||
$this->assertSame(rtrim($dump), $this->getVarDumperDump($data), $message);
|
||||
$this->assertSame(rtrim($dump), $this->getDump($data), $message);
|
||||
}
|
||||
|
||||
public function assertDumpMatchesFormat($dump, $data, $message = '')
|
||||
{
|
||||
$this->assertStringMatchesFormat(rtrim($dump), $this->getVarDumperDump($data), $message);
|
||||
$this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message);
|
||||
}
|
||||
|
||||
private function getVarDumperDump($data)
|
||||
protected function getDump($data)
|
||||
{
|
||||
$h = fopen('php://memory', 'r+b');
|
||||
$cloner = new VarCloner();
|
||||
|
|
|
@ -29,7 +29,7 @@ trait VarDumperTestTrait
|
|||
$this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message);
|
||||
}
|
||||
|
||||
public function getDump($data)
|
||||
protected function getDump($data)
|
||||
{
|
||||
$h = fopen('php://memory', 'r+b');
|
||||
$cloner = new VarCloner();
|
||||
|
|
Reference in New Issue