-
-
- Admin
-
+{% if token is not empty %}
+
+
+
+ Admin
+
-
-
+
+
+{% endif %}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ExportCommandTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ExportCommandTest.php
new file mode 100644
index 0000000000..572e9b3978
--- /dev/null
+++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ExportCommandTest.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebProfilerBundle\Tests\Command;
+
+use Symfony\Bundle\WebProfilerBundle\Command\ExportCommand;
+use Symfony\Component\Console\Tester\CommandTester;
+use Symfony\Component\Console\Application;
+use Symfony\Component\HttpKernel\Profiler\Profile;
+
+class ExportCommandTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \LogicException
+ */
+ public function testExecuteWithUnknownToken()
+ {
+ $profiler = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $command = new ExportCommand($profiler);
+ $commandTester = new CommandTester($command);
+ $commandTester->execute(array('token' => 'TOKEN'));
+ }
+
+ public function testExecuteWithToken()
+ {
+ $profiler = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $profile = new Profile('TOKEN');
+ $profiler->expects($this->once())->method('loadProfile')->with('TOKEN')->will($this->returnValue($profile));
+
+ $command = new ExportCommand($profiler);
+ $commandTester = new CommandTester($command);
+ $commandTester->execute(array('token' => 'TOKEN'));
+ $this->assertEquals($profiler->export($profile), $commandTester->getDisplay());
+ }
+}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ImportCommandTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ImportCommandTest.php
new file mode 100644
index 0000000000..f5121c12d6
--- /dev/null
+++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Command/ImportCommandTest.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebProfilerBundle\Tests\Command;
+
+use Symfony\Bundle\WebProfilerBundle\Command\ImportCommand;
+use Symfony\Component\Console\Tester\CommandTester;
+use Symfony\Component\Console\Application;
+use Symfony\Component\HttpKernel\Profiler\Profile;
+
+class ImportCommandTest extends \PHPUnit_Framework_TestCase
+{
+ public function testExecute()
+ {
+ $profiler = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $profiler->expects($this->once())->method('import')->will($this->returnValue(new Profile('TOKEN')));
+
+ $command = new ImportCommand($profiler);
+ $commandTester = new CommandTester($command);
+ $commandTester->execute(array('filename' => __DIR__.'/../Fixtures/profile.data'));
+ $this->assertRegExp('/Profile "TOKEN" has been successfully imported\./', $commandTester->getDisplay());
+ }
+}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/profile.data b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/profile.data
new file mode 100644
index 0000000000..ab76cea63d
--- /dev/null
+++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/profile.data
@@ -0,0 +1 @@
+Tzo0NToiU3ltZm9ueVxDb21wb25lbnRcSHR0cEtlcm5lbFxQcm9maWxlclxQcm9maWxlIjo4OntzOjUyOiIAU3ltZm9ueVxDb21wb25lbnRcSHR0cEtlcm5lbFxQcm9maWxlclxQcm9maWxlAHRva2VuIjtzOjU6IlRPS0VOIjtzOjUzOiIAU3ltZm9ueVxDb21wb25lbnRcSHR0cEtlcm5lbFxQcm9maWxlclxQcm9maWxlAHBhcmVudCI7TjtzOjU1OiIAU3ltZm9ueVxDb21wb25lbnRcSHR0cEtlcm5lbFxQcm9maWxlclxQcm9maWxlAGNoaWxkcmVuIjthOjA6e31zOjU3OiIAU3ltZm9ueVxDb21wb25lbnRcSHR0cEtlcm5lbFxQcm9maWxlclxQcm9maWxlAGNvbGxlY3RvcnMiO2E6MDp7fXM6NDk6IgBTeW1mb255XENvbXBvbmVudFxIdHRwS2VybmVsXFByb2ZpbGVyXFByb2ZpbGUAaXAiO047czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XEh0dHBLZXJuZWxcUHJvZmlsZXJcUHJvZmlsZQBtZXRob2QiO047czo1MDoiAFN5bWZvbnlcQ29tcG9uZW50XEh0dHBLZXJuZWxcUHJvZmlsZXJcUHJvZmlsZQB1cmwiO047czo1MToiAFN5bWZvbnlcQ29tcG9uZW50XEh0dHBLZXJuZWxcUHJvZmlsZXJcUHJvZmlsZQB0aW1lIjtOO30=
\ No newline at end of file
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index 23047059c7..fff751e82f 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -52,7 +52,8 @@ class Filesystem
if ($doCopy) {
// https://bugs.php.net/bug.php?id=64634
$source = fopen($originFile, 'r');
- $target = fopen($targetFile, 'w');
+ // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
+ $target = fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))));
stream_copy_to_stream($source, $target);
fclose($source);
fclose($target);
diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php
index 7634b99966..f7f0c21425 100644
--- a/src/Symfony/Component/Finder/Tests/FinderTest.php
+++ b/src/Symfony/Component/Finder/Tests/FinderTest.php
@@ -739,17 +739,30 @@ class FinderTest extends Iterator\RealIteratorTestCase
$finder->files()->in(self::$tmpDir);
// make 'foo' directory non-readable
- chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
+ $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+ chmod($testDir, 0333);
- try {
- $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
- $this->fail('Finder should throw an exception when opening a non-readable directory.');
- } catch (\Exception $e) {
- $this->assertInstanceOf('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', $e);
+ if (false === $couldRead = is_readable($testDir)) {
+ try {
+ $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+ $this->fail('Finder should throw an exception when opening a non-readable directory.');
+ } catch (\Exception $e) {
+ $expectedExceptionClass = 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException';
+ if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
+ $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, 'PHPUnit_Framework_ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString()));
+ }
+
+ $this->assertInstanceOf($expectedExceptionClass, $e);
+ }
}
// restore original permissions
- chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
+ chmod($testDir, 0777);
+ clearstatcache($testDir);
+
+ if ($couldRead) {
+ $this->markTestSkipped('could read test files while test requires unreadable');
+ }
}
/**
@@ -765,12 +778,20 @@ class FinderTest extends Iterator\RealIteratorTestCase
$finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);
// make 'foo' directory non-readable
- chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
+ $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+ chmod($testDir, 0333);
- $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+ if (false === ($couldRead = is_readable($testDir))) {
+ $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+ }
// restore original permissions
- chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
+ chmod($testDir, 0777);
+ clearstatcache($testDir);
+
+ if ($couldRead) {
+ $this->markTestSkipped('could read test files while test requires unreadable');
+ }
}
private function buildTestData(array $tests)
diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php
index f68aa74978..06d98c8580 100644
--- a/src/Symfony/Component/HttpFoundation/Request.php
+++ b/src/Symfony/Component/HttpFoundation/Request.php
@@ -1172,7 +1172,8 @@ class Request
// as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
// check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
- if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) {
+ // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
+ if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) {
throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host));
}
@@ -1381,6 +1382,16 @@ class Request
}
}
+ /**
+ * Get the default locale.
+ *
+ * @return string
+ */
+ public function getDefaultLocale()
+ {
+ return $this->defaultLocale;
+ }
+
/**
* Sets the locale.
*
diff --git a/src/Symfony/Component/HttpFoundation/ServerBag.php b/src/Symfony/Component/HttpFoundation/ServerBag.php
index de6dbc9fb5..6a4f2c2b16 100644
--- a/src/Symfony/Component/HttpFoundation/ServerBag.php
+++ b/src/Symfony/Component/HttpFoundation/ServerBag.php
@@ -65,13 +65,13 @@ class ServerBag extends ParameterBag
}
if (null !== $authorizationHeader) {
- if (0 === stripos($authorizationHeader, 'basic')) {
+ if (0 === stripos($authorizationHeader, 'basic ')) {
// Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
- $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
+ $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2);
if (count($exploded) == 2) {
list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
}
- } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest'))) {
+ } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) {
// In some circumstances PHP_AUTH_DIGEST needs to be set
$headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
$this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
index f98864f4f1..ed06e550c7 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
@@ -42,7 +42,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument');
$request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar'));
- $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument');
+ $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its sixth argument');
}
public function testGetLocale()
@@ -200,23 +200,23 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('test.com:90', $request->getHttpHost());
$this->assertFalse($request->isSecure());
- $request = Request::create('http://test:test@test.com');
+ $request = Request::create('http://username:password@test.com');
$this->assertEquals('http://test.com/', $request->getUri());
$this->assertEquals('/', $request->getPathInfo());
$this->assertEquals('', $request->getQueryString());
$this->assertEquals(80, $request->getPort());
$this->assertEquals('test.com', $request->getHttpHost());
- $this->assertEquals('test', $request->getUser());
- $this->assertEquals('test', $request->getPassword());
+ $this->assertEquals('username', $request->getUser());
+ $this->assertEquals('password', $request->getPassword());
$this->assertFalse($request->isSecure());
- $request = Request::create('http://testnopass@test.com');
+ $request = Request::create('http://username@test.com');
$this->assertEquals('http://test.com/', $request->getUri());
$this->assertEquals('/', $request->getPathInfo());
$this->assertEquals('', $request->getQueryString());
$this->assertEquals(80, $request->getPort());
$this->assertEquals('test.com', $request->getHttpHost());
- $this->assertEquals('testnopass', $request->getUser());
+ $this->assertEquals('username', $request->getUser());
$this->assertSame('',$request->getPassword());
$this->assertFalse($request->isSecure());
@@ -1657,6 +1657,59 @@ class RequestTest extends \PHPUnit_Framework_TestCase
Request::setFactory(null);
}
+
+ /**
+ * @dataProvider getLongHostNames
+ */
+ public function testVeryLongHosts($host)
+ {
+ $start = microtime(true);
+
+ $request = Request::create('/');
+ $request->headers->set('host', $host);
+ $this->assertEquals($host, $request->getHost());
+ $this->assertLessThan(1, microtime(true) - $start);
+ }
+
+ /**
+ * @dataProvider getHostValidities
+ */
+ public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null)
+ {
+ $request = Request::create('/');
+ $request->headers->set('host', $host);
+
+ if ($isValid) {
+ $this->assertSame($expectedHost ?: $host, $request->getHost());
+ if ($expectedPort) {
+ $this->assertSame($expectedPort, $request->getPort());
+ }
+ } else {
+ $this->setExpectedException('UnexpectedValueException', 'Invalid Host');
+ $request->getHost();
+ }
+ }
+
+ public function getHostValidities()
+ {
+ return array(
+ array('.a', false),
+ array('a..', false),
+ array('a.', true),
+ array("\xE9", false),
+ array('[::1]', true),
+ array('[::1]:80', true, '[::1]', 80),
+ array(str_repeat('.', 101), false),
+ );
+ }
+
+ public function getLongHostNames()
+ {
+ return array(
+ array('a'.str_repeat('.a', 40000)),
+ array(str_repeat(':', 101)),
+ );
+ }
}
class RequestContentProxy extends Request
diff --git a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
index 89920f1fbc..662c5880b1 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
@@ -67,14 +67,24 @@ class ServerBagTest extends \PHPUnit_Framework_TestCase
), $bag->getHeaders());
}
+ public function testHttpBasicAuthWithPhpCgiBogus()
+ {
+ $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic_'.base64_encode('foo:bar')));
+
+ // Username and passwords should not be set as the header is bogus
+ $headers = $bag->getHeaders();
+ $this->assertFalse(isset($headers['PHP_AUTH_USER']));
+ $this->assertFalse(isset($headers['PHP_AUTH_PW']));
+ }
+
public function testHttpBasicAuthWithPhpCgiRedirect()
{
- $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')));
+ $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('username:pass:word')));
$this->assertEquals(array(
- 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
- 'PHP_AUTH_USER' => 'foo',
- 'PHP_AUTH_PW' => 'bar'
+ 'AUTHORIZATION' => 'Basic '.base64_encode('username:pass:word'),
+ 'PHP_AUTH_USER' => 'username',
+ 'PHP_AUTH_PW' => 'pass:word'
), $bag->getHeaders());
}
@@ -100,6 +110,17 @@ class ServerBagTest extends \PHPUnit_Framework_TestCase
), $bag->getHeaders());
}
+ public function testHttpDigestAuthWithPhpCgiBogus()
+ {
+ $digest = 'Digest_username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"';
+ $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $digest));
+
+ // Username and passwords should not be set as the header is bogus
+ $headers = $bag->getHeaders();
+ $this->assertFalse(isset($headers['PHP_AUTH_USER']));
+ $this->assertFalse(isset($headers['PHP_AUTH_PW']));
+ }
+
public function testHttpDigestAuthWithPhpCgiRedirect()
{
$digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"';
diff --git a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php
index ef3fad3d4c..1a198a55f6 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php
@@ -12,11 +12,11 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\IpUtils;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\UriSigner;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@@ -25,8 +25,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* All URL paths starting with /_fragment are handled as
* content fragments by this listener.
*
- * If the request does not come from a trusted IP, it throws an
- * AccessDeniedHttpException exception.
+ * If throws an AccessDeniedHttpException exception if the request
+ * is not signed or if it is not an internal sub-request.
*
* @author Fabien Potencier