Skip to content
This repository was archived by the owner on May 31, 2024. It is now read-only.

Commit bb21b1a

Browse files
committed
Merge branch '2.7' into 2.8
* 2.7: (95 commits) [DependencyInjection] provide better error message when using deprecated configuration options [console][TableCell] get cell width without decoration. Improve the config validation in TwigBundle [VarDumper] Changed tooltip to expand-all keybinding in OS X [Bridge\PhpUnit] Fix composer installed phpunit detection [VarDumper] Fix generic casters calling order [2.7][SecurityBundle] Remove SecurityContext from Compile [WebProfilerBundle][logger] added missing deprecation message. Fix profiler CSS [Security][Acl] enforce string identifiers [FrameworkBundle] make `templating.helper.router` service available again for BC reasons [BrowserKit] Fix bug when uri starts with http. bumped Symfony version to 2.7.1 updated VERSION for 2.7.0 updated CHANGELOG for 2.7.0 bumped Symfony version to 2.6.10 updated VERSION for 2.6.9 updated CHANGELOG for 2.6.9 fixed tests bumped Symfony version to 2.3.31 ... Conflicts: src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig src/Symfony/Component/HttpKernel/Kernel.php src/Symfony/Component/Translation/Loader/JsonFileLoader.php
2 parents 3c6c556 + 3cc16df commit bb21b1a

10 files changed

+93
-19
lines changed

Acl/Domain/ObjectIdentity.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ final class ObjectIdentity implements ObjectIdentityInterface
3636
*/
3737
public function __construct($identifier, $type)
3838
{
39-
if (empty($identifier)) {
39+
if ('' === $identifier) {
4040
throw new \InvalidArgumentException('$identifier cannot be empty.');
4141
}
4242
if (empty($type)) {
@@ -66,7 +66,7 @@ public static function fromDomainObject($domainObject)
6666
if ($domainObject instanceof DomainObjectInterface) {
6767
return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject));
6868
} elseif (method_exists($domainObject, 'getId')) {
69-
return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject));
69+
return new self((string) $domainObject->getId(), ClassUtils::getRealClass($domainObject));
7070
}
7171
} catch (\InvalidArgumentException $invalid) {
7272
throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid);

Acl/Tests/Domain/EntryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function testSetAuditSuccess()
3636
$this->assertTrue($ace->isAuditSuccess());
3737
$ace->setAuditSuccess(false);
3838
$this->assertFalse($ace->isAuditSuccess());
39-
$ace->setAuditsuccess(true);
39+
$ace->setAuditSuccess(true);
4040
$this->assertTrue($ace->isAuditSuccess());
4141
}
4242

Acl/Tests/Domain/ObjectIdentityTest.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ public function testFromDomainObjectWithProxy()
6464
$this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
6565
}
6666

67+
public function testFromDomainObjectWithoutInterfaceEnforcesStringIdentifier()
68+
{
69+
$domainObject = new TestDomainObject();
70+
$domainObject->id = 1;
71+
$id = ObjectIdentity::fromDomainObject($domainObject);
72+
73+
$this->assertSame('1', $id->getIdentifier());
74+
$this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType());
75+
}
76+
77+
public function testFromDomainObjectWithoutInterfaceAllowsZeroAsIdentifier()
78+
{
79+
$domainObject = new TestDomainObject();
80+
$domainObject->id = '0';
81+
$id = ObjectIdentity::fromDomainObject($domainObject);
82+
83+
$this->assertSame('0', $id->getIdentifier());
84+
$this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType());
85+
}
86+
6787
/**
6888
* @dataProvider getCompareData
6989
*/
@@ -89,14 +109,16 @@ public function getCompareData()
89109

90110
class TestDomainObject
91111
{
112+
public $id = 'getId()';
113+
92114
public function getObjectIdentifier()
93115
{
94116
return 'getObjectIdentifier()';
95117
}
96118

97119
public function getId()
98120
{
99-
return 'getId()';
121+
return $this->id;
100122
}
101123
}
102124
}

Http/Firewall/ExceptionListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ private function startAuthentication(Request $request, AuthenticationException $
205205
protected function setTargetPath(Request $request)
206206
{
207207
// session isn't required when using HTTP basic authentication mechanism for example
208-
if ($request->hasSession() && $request->isMethodSafe()) {
208+
if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) {
209209
$request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri());
210210
}
211211
}

Http/RememberMe/AbstractRememberMeServices.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,17 @@ protected function decodeCookie($rawCookie)
268268
* @param array $cookieParts
269269
*
270270
* @return string
271+
*
272+
* @throws \InvalidArgumentException When $cookieParts contain the cookie delimiter. Extending class should either remove or escape it.
271273
*/
272274
protected function encodeCookie(array $cookieParts)
273275
{
276+
foreach ($cookieParts as $cookiePart) {
277+
if (false !== strpos($cookiePart, self::COOKIE_DELIMITER)) {
278+
throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s"', self::COOKIE_DELIMITER));
279+
}
280+
}
281+
274282
return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts));
275283
}
276284

Http/RememberMe/PersistentTokenBasedRememberMeServices.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request)
9898
throw new AuthenticationException('The cookie has expired.');
9999
}
100100

101-
$series = $persistentToken->getSeries();
102101
$tokenValue = base64_encode($this->secureRandom->nextBytes(64));
103102
$this->tokenProvider->updateToken($series, $tokenValue, new \DateTime());
104103
$request->attributes->set(self::COOKIE_ATTR_NAME,

Http/RememberMe/TokenBasedRememberMeServices.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt
9595
* @param int $expires The Unix timestamp when the cookie expires
9696
* @param string $password The encoded password
9797
*
98-
* @throws \RuntimeException if username contains invalid chars
99-
*
10098
* @return string
10199
*/
102100
protected function generateCookieValue($class, $username, $expires, $password)
103101
{
102+
// $username is encoded because it might contain COOKIE_DELIMITER,
103+
// we assume other values don't
104104
return $this->encodeCookie(array(
105105
$class,
106106
base64_encode($username),
@@ -117,8 +117,6 @@ protected function generateCookieValue($class, $username, $expires, $password)
117117
* @param int $expires The Unix timestamp when the cookie expires
118118
* @param string $password The encoded password
119119
*
120-
* @throws \RuntimeException when the private key is empty
121-
*
122120
* @return string
123121
*/
124122
protected function generateCookieHash($class, $username, $expires, $password)

Http/Tests/RememberMe/AbstractRememberMeServicesTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices;
1718

1819
class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
1920
{
@@ -236,6 +237,30 @@ public function getPositiveRememberMeParameterValues()
236237
);
237238
}
238239

240+
public function testEncodeCookieAndDecodeCookieAreInvertible()
241+
{
242+
$cookieParts = array('aa', 'bb', 'cc');
243+
$service = $this->getService();
244+
245+
$encoded = $this->callProtected($service, 'encodeCookie', array($cookieParts));
246+
$this->assertInternalType('string', $encoded);
247+
248+
$decoded = $this->callProtected($service, 'decodeCookie', array($encoded));
249+
$this->assertSame($cookieParts, $decoded);
250+
}
251+
252+
/**
253+
* @expectedException InvalidArgumentException
254+
* @expectedExceptionMessage cookie delimiter
255+
*/
256+
public function testThereShouldBeNoCookieDelimiterInCookieParts()
257+
{
258+
$cookieParts = array('aa', 'b'.AbstractRememberMeServices::COOKIE_DELIMITER.'b', 'cc');
259+
$service = $this->getService();
260+
261+
$this->callProtected($service, 'encodeCookie', array($cookieParts));
262+
}
263+
239264
protected function getService($userProvider = null, $options = array(), $logger = null)
240265
{
241266
if (null === $userProvider) {
@@ -258,4 +283,13 @@ protected function getProvider()
258283

259284
return $provider;
260285
}
286+
287+
private function callProtected($object, $method, array $args)
288+
{
289+
$reflection = new \ReflectionClass(get_class($object));
290+
$reflectionMethod = $reflection->getMethod($method);
291+
$reflectionMethod->setAccessible(true);
292+
293+
return $reflectionMethod->invokeArgs($object, $args);
294+
}
261295
}

Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,12 @@ public function testAutoLoginDoesNotAcceptAnExpiredCookie()
105105
$this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared());
106106
}
107107

108-
public function testAutoLogin()
108+
/**
109+
* @dataProvider provideUsernamesForAutoLogin
110+
*
111+
* @param string $username
112+
*/
113+
public function testAutoLogin($username)
109114
{
110115
$user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
111116
$user
@@ -123,13 +128,13 @@ public function testAutoLogin()
123128
$userProvider
124129
->expects($this->once())
125130
->method('loadUserByUsername')
126-
->with($this->equalTo('foouser'))
131+
->with($this->equalTo($username))
127132
->will($this->returnValue($user))
128133
;
129134

130135
$service = $this->getService($userProvider, array('name' => 'foo', 'always_remember_me' => true, 'lifetime' => 3600));
131136
$request = new Request();
132-
$request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time() + 3600, 'foopass'));
137+
$request->cookies->set('foo', $this->getCookie('fooclass', $username, time() + 3600, 'foopass'));
133138

134139
$returnedToken = $service->autoLogin($request);
135140

@@ -138,6 +143,14 @@ public function testAutoLogin()
138143
$this->assertEquals('fookey', $returnedToken->getKey());
139144
}
140145

146+
public function provideUsernamesForAutoLogin()
147+
{
148+
return array(
149+
array('foouser', 'Simple username'),
150+
array('foo'.TokenBasedRememberMeServices::COOKIE_DELIMITER.'user', 'Username might contain the delimiter'),
151+
);
152+
}
153+
141154
public function testLogout()
142155
{
143156
$service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null));

Resources/translations/security.fr.xlf

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88
</trans-unit>
99
<trans-unit id="2">
1010
<source>Authentication credentials could not be found.</source>
11-
<target>Les droits d'authentification n'ont pas pu être trouvés.</target>
11+
<target>Les identifiants d'authentification n'ont pas pu être trouvés.</target>
1212
</trans-unit>
1313
<trans-unit id="3">
1414
<source>Authentication request could not be processed due to a system problem.</source>
1515
<target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target>
1616
</trans-unit>
1717
<trans-unit id="4">
1818
<source>Invalid credentials.</source>
19-
<target>Droits invalides.</target>
19+
<target>Identifiants invalides.</target>
2020
</trans-unit>
2121
<trans-unit id="5">
2222
<source>Cookie has already been used by someone else.</source>
2323
<target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target>
2424
</trans-unit>
2525
<trans-unit id="6">
2626
<source>Not privileged to request the resource.</source>
27-
<target>Pas de privilèges pour accéder à la ressource.</target>
27+
<target>Privilèges insuffisants pour accéder à la ressource.</target>
2828
</trans-unit>
2929
<trans-unit id="7">
3030
<source>Invalid CSRF token.</source>
@@ -40,23 +40,23 @@
4040
</trans-unit>
4141
<trans-unit id="10">
4242
<source>No session available, it either timed out or cookies are not enabled.</source>
43-
<target>Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
43+
<target>Aucune session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
4444
</trans-unit>
4545
<trans-unit id="11">
4646
<source>No token could be found.</source>
4747
<target>Aucun jeton n'a pu être trouvé.</target>
4848
</trans-unit>
4949
<trans-unit id="12">
5050
<source>Username could not be found.</source>
51-
<target>Le nom d'utilisateur ne peut pas être trouvé.</target>
51+
<target>Le nom d'utilisateur n'a pas pu être trouvé.</target>
5252
</trans-unit>
5353
<trans-unit id="13">
5454
<source>Account has expired.</source>
5555
<target>Le compte a expiré.</target>
5656
</trans-unit>
5757
<trans-unit id="14">
5858
<source>Credentials have expired.</source>
59-
<target>Les droits ont expirés.</target>
59+
<target>Les identifiants ont expiré.</target>
6060
</trans-unit>
6161
<trans-unit id="15">
6262
<source>Account is disabled.</source>

0 commit comments

Comments
 (0)