Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d657834

Browse files
committed
Merge branch '2.3' into 2.7
* 2.3: [Security][bugfix] "Remember me" cookie cleared on logout with custom "secure"/"httponly" config options [1] [ci] Use current PHP_BINARY when running ./phpunit Fixed typos [UPGRADE-3.0] fix bullet indentation [Security] InMemoryUserProvider now concerns whether user's password is changed when refreshing
2 parents 2c46204 + 9becf27 commit d657834

File tree

10 files changed

+139
-44
lines changed

10 files changed

+139
-44
lines changed

UPGRADE-3.0.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,18 @@ UPGRADE FROM 2.x to 3.0
299299
```php
300300
echo $form->getErrors(true, false);
301301
```
302-
* The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList` class has been removed in
303-
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
304302

305-
* The `Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList` class has been removed in
306-
favor of `Symfony\Component\Form\ChoiceList\LazyChoiceList`.
303+
* The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList` class has been removed in
304+
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
307305

308-
* The `Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList` class has been removed in
309-
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
306+
* The `Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList` class has been removed in
307+
favor of `Symfony\Component\Form\ChoiceList\LazyChoiceList`.
310308

311-
* The `Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList` class has been removed in
312-
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
309+
* The `Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList` class has been removed in
310+
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
311+
312+
* The `Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList` class has been removed in
313+
favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
313314

314315
### FrameworkBundle
315316

phpunit

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,26 @@ use Symfony\Component\Process\ProcessUtils;
66
error_reporting(-1);
77
require __DIR__.'/src/Symfony/Component/Process/ProcessUtils.php';
88

9-
$PHPUNIT_VERSION = '4.8';
9+
// PHPUnit 4.8 does not support PHP 7, while 5.0 requires PHP 5.6+
10+
$PHPUNIT_VERSION = PHP_VERSION_ID >= 70000 ? '5.0' : '4.8';
1011
$PHPUNIT_DIR = __DIR__.'/.phpunit';
12+
$PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php';
13+
14+
if (!file_exists($COMPOSER = __DIR__.'/composer.phar')) {
15+
$COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? `where.exe composer.phar` : (`which composer.phar` ?: `which composer`));
16+
if (!file_exists($COMPOSER)) {
17+
stream_copy_to_stream(
18+
fopen('https://getcomposer.org/composer.phar', 'rb'),
19+
fopen($COMPOSER = __DIR__.'/composer.phar', 'wb')
20+
);
21+
}
22+
}
1123

12-
// PHPUnit 4.8 does not support PHP 7, while 5.0 requires PHP 5.6+
13-
if (PHP_VERSION_ID >= 70000) {
14-
$PHPUNIT_VERSION = '5.0';
24+
$PHP = ProcessUtils::escapeArgument($PHP);
25+
$COMPOSER = $PHP.' '.ProcessUtils::escapeArgument($COMPOSER);
26+
27+
if (!(isset($argv[1]) && 'install' === $argv[1]) && !file_exists(__DIR__.'/vendor')) {
28+
passthru("$COMPOSER update --no-progress --ansi");
1529
}
1630

1731
if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit")) {
@@ -30,8 +44,8 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit")) {
3044
$zip->extractTo(getcwd());
3145
$zip->close();
3246
chdir("phpunit-$PHPUNIT_VERSION");
33-
passthru("composer remove --no-update symfony/yaml");
34-
passthru("composer install --prefer-source --no-progress --ansi");
47+
passthru("$COMPOSER remove --no-update symfony/yaml");
48+
passthru("$COMPOSER install --prefer-source --no-progress --ansi");
3549
chdir($oldPwd);
3650
}
3751

@@ -42,7 +56,7 @@ if (isset($argv[1]) && 'symfony' === $argv[1]) {
4256
array_shift($cmd);
4357
}
4458

45-
$cmd[0] = "php $PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit --colors=always";
59+
$cmd[0] = sprintf('%s %s --colors=always', $PHP, ProcessUtils::escapeArgument("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit"));
4660
$cmd = str_replace('%', '%%', implode(' ', $cmd)).' %1$s';
4761

4862
$phpIniMatrix = isset($_SERVER['PHP_INI_MATRIX']) ? explode(' ', $_SERVER['PHP_INI_MATRIX']) : array();
@@ -52,7 +66,7 @@ if ($phpIniMatrix) {
5266
exit(1);
5367
}
5468

55-
$phpDir = dirname(`where.exe php`);
69+
$phpDir = ProcessUtils::escapeArgument(dirname(`where.exe php`));
5670

5771
$newCmd = 'cmd /v:on /d /c "(SET X=0';
5872
foreach ($phpIniMatrix as $iniFile) {

src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ public function write($sessionId, $data)
160160
$mergeStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
161161
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
162162

163-
//Oracle has a bug that will intermitently happen if you
164-
//have only 1 bind on a CLOB field for 2 different statements
165-
//(INSERT and UPDATE in this case)
163+
// Oracle has a bug that will intermittently happen if you
164+
// have only 1 bind on a CLOB field for 2 different statements
165+
// (INSERT and UPDATE in this case)
166166
if ('oracle' == $this->con->getDatabasePlatform()->getName()) {
167167
$mergeStmt->bindParam(':data2', $encoded, \PDO::PARAM_STR);
168168
}

src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ protected function normalizeToken($token)
9090
/**
9191
* Seeks to a non-whitespace token.
9292
*/
93-
private function seekToNextReleventToken(\Iterator $tokenIterator)
93+
private function seekToNextRelevantToken(\Iterator $tokenIterator)
9494
{
9595
for (; $tokenIterator->valid(); $tokenIterator->next()) {
9696
$t = $tokenIterator->current();
@@ -153,7 +153,7 @@ protected function parseTokens($tokens, MessageCatalogue $catalog)
153153
$tokenIterator->seek($key);
154154

155155
foreach ($sequence as $item) {
156-
$this->seekToNextReleventToken($tokenIterator);
156+
$this->seekToNextRelevantToken($tokenIterator);
157157

158158
if ($this->normalizeToken($tokenIterator->current()) == $item) {
159159
$tokenIterator->next();

src/Symfony/Component/Security/Core/Tests/User/InMemoryUserProviderTest.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,39 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
1818
{
1919
public function testConstructor()
2020
{
21-
$provider = new InMemoryUserProvider(array(
21+
$provider = $this->createProvider();
22+
23+
$user = $provider->loadUserByUsername('fabien');
24+
$this->assertEquals('foo', $user->getPassword());
25+
$this->assertEquals(array('ROLE_USER'), $user->getRoles());
26+
$this->assertFalse($user->isEnabled());
27+
}
28+
29+
public function testRefresh()
30+
{
31+
$user = new User('fabien', 'bar');
32+
33+
$provider = $this->createProvider();
34+
35+
$refreshedUser = $provider->refreshUser($user);
36+
$this->assertEquals('foo', $refreshedUser->getPassword());
37+
$this->assertEquals(array('ROLE_USER'), $refreshedUser->getRoles());
38+
$this->assertFalse($refreshedUser->isEnabled());
39+
$this->assertFalse($refreshedUser->isCredentialsNonExpired());
40+
}
41+
42+
/**
43+
* @return InMemoryUserProvider
44+
*/
45+
protected function createProvider()
46+
{
47+
return new InMemoryUserProvider(array(
2248
'fabien' => array(
2349
'password' => 'foo',
2450
'enabled' => false,
2551
'roles' => array('ROLE_USER'),
2652
),
2753
));
28-
29-
$user = $provider->loadUserByUsername('fabien');
30-
$this->assertEquals('foo', $user->getPassword());
31-
$this->assertEquals(array('ROLE_USER'), $user->getRoles());
32-
$this->assertFalse($user->isEnabled());
3354
}
3455

3556
public function testCreateUser()

src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,9 @@ public function createUser(UserInterface $user)
6767
*/
6868
public function loadUserByUsername($username)
6969
{
70-
if (!isset($this->users[strtolower($username)])) {
71-
$ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
72-
$ex->setUsername($username);
73-
74-
throw $ex;
75-
}
70+
$user = $this->getUser($username);
7671

77-
$user = $this->users[strtolower($username)];
78-
79-
return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(),
80-
$user->isCredentialsNonExpired(), $user->isAccountNonLocked());
72+
return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), $user->isCredentialsNonExpired(), $user->isAccountNonLocked());
8173
}
8274

8375
/**
@@ -89,7 +81,9 @@ public function refreshUser(UserInterface $user)
8981
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
9082
}
9183

92-
return $this->loadUserByUsername($user->getUsername());
84+
$storedUser = $this->getUser($user->getUsername());
85+
86+
return new User($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled(), $storedUser->isAccountNonExpired(), $storedUser->isCredentialsNonExpired() && $storedUser->getPassword() === $user->getPassword(), $storedUser->isAccountNonLocked());
9387
}
9488

9589
/**
@@ -99,4 +93,25 @@ public function supportsClass($class)
9993
{
10094
return $class === 'Symfony\Component\Security\Core\User\User';
10195
}
96+
97+
/**
98+
* Returns the user by given username.
99+
*
100+
* @param string $username The username.
101+
*
102+
* @return User
103+
*
104+
* @throws UsernameNotFoundException If user whose given username does not exist.
105+
*/
106+
private function getUser($username)
107+
{
108+
if (!isset($this->users[strtolower($username)])) {
109+
$ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
110+
$ex->setUsername($username);
111+
112+
throw $ex;
113+
}
114+
115+
return $this->users[strtolower($username)];
116+
}
102117
}

src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ protected function cancelCookie(Request $request)
293293
$this->logger->debug('Clearing remember-me cookie.', array('name' => $this->options['name']));
294294
}
295295

296-
$request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain']));
296+
$request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly']));
297297
}
298298

299299
/**

src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,35 @@ public function testAutoLogin()
8282
$this->assertSame('fookey', $returnedToken->getProviderKey());
8383
}
8484

85-
public function testLogout()
85+
/**
86+
* @dataProvider provideOptionsForLogout
87+
*/
88+
public function testLogout(array $options)
8689
{
87-
$service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
90+
$service = $this->getService(null, $options);
8891
$request = new Request();
8992
$response = new Response();
9093
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
9194

9295
$service->logout($request, $response, $token);
9396

94-
$this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
97+
$cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME);
98+
99+
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Cookie', $cookie);
100+
$this->assertTrue($cookie->isCleared());
101+
$this->assertSame($options['name'], $cookie->getName());
102+
$this->assertSame($options['path'], $cookie->getPath());
103+
$this->assertSame($options['domain'], $cookie->getDomain());
104+
$this->assertSame($options['secure'], $cookie->isSecure());
105+
$this->assertSame($options['httponly'], $cookie->isHttpOnly());
106+
}
107+
108+
public function provideOptionsForLogout()
109+
{
110+
return array(
111+
array(array('name' => 'foo', 'path' => '/', 'domain' => null, 'secure' => false, 'httponly' => true)),
112+
array(array('name' => 'foo', 'path' => '/bar', 'domain' => 'baz.com', 'secure' => true, 'httponly' => false)),
113+
);
95114
}
96115

97116
public function testLoginFail()
@@ -267,6 +286,13 @@ protected function getService($userProvider = null, $options = array(), $logger
267286
$userProvider = $this->getProvider();
268287
}
269288

289+
if (!isset($options['secure'])) {
290+
$options['secure'] = false;
291+
}
292+
if (!isset($options['httponly'])) {
293+
$options['httponly'] = true;
294+
}
295+
270296
return $this->getMockForAbstractClass('Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', array(
271297
array($userProvider), 'fookey', 'fookey', $options, $logger,
272298
));

src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public function testAutoLogin()
180180

181181
public function testLogout()
182182
{
183-
$service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo'));
183+
$service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo', 'secure' => true, 'httponly' => false));
184184
$request = new Request();
185185
$request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue')));
186186
$response = new Response();
@@ -201,6 +201,8 @@ public function testLogout()
201201
$this->assertTrue($cookie->isCleared());
202202
$this->assertEquals('/foo', $cookie->getPath());
203203
$this->assertEquals('foodomain.foo', $cookie->getDomain());
204+
$this->assertTrue($cookie->isSecure());
205+
$this->assertFalse($cookie->isHttpOnly());
204206
}
205207

206208
public function testLogoutSimplyIgnoresNonSetRequestCookie()
@@ -311,6 +313,13 @@ protected function getService($userProvider = null, $options = array(), $logger
311313
$userProvider = $this->getProvider();
312314
}
313315

316+
if (!isset($options['secure'])) {
317+
$options['secure'] = false;
318+
}
319+
if (!isset($options['httponly'])) {
320+
$options['httponly'] = true;
321+
}
322+
314323
return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed'));
315324
}
316325

src/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public function provideUsernamesForAutoLogin()
153153

154154
public function testLogout()
155155
{
156-
$service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));
156+
$service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'secure' => true, 'httponly' => false));
157157
$request = new Request();
158158
$response = new Response();
159159
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
@@ -164,6 +164,8 @@ public function testLogout()
164164
$this->assertTrue($cookie->isCleared());
165165
$this->assertEquals('/', $cookie->getPath());
166166
$this->assertNull($cookie->getDomain());
167+
$this->assertTrue($cookie->isSecure());
168+
$this->assertFalse($cookie->isHttpOnly());
167169
}
168170

169171
public function testLoginFail()
@@ -264,6 +266,13 @@ protected function getService($userProvider = null, $options = array(), $logger
264266
$userProvider = $this->getProvider();
265267
}
266268

269+
if (!isset($options['secure'])) {
270+
$options['secure'] = false;
271+
}
272+
if (!isset($options['httponly'])) {
273+
$options['httponly'] = true;
274+
}
275+
267276
$service = new TokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger);
268277

269278
return $service;

0 commit comments

Comments
 (0)