Skip to content

Commit 3ee13b9

Browse files
committed
Merge branch '2.5'
* 2.5: (23 commits) [HttpKernel] fixed some unit tests for 2.4 (signature now uses SHA256 instead of MD5) [HttpKernel] simplified code [HttpKernel] fixed internal fragment handling fixing yaml indentation Unexpexted ));" [WebProfiler] replaced the import/export feature from the web interface to a CLI tool Forced all fragment uris to be signed, even for ESI Add tests and more assertions [FrameworkBundle][Translator] Validate locales. [HttpFoundation] added some missing tests [HttpFoundation] Improve string values in test codes [Security] Add more tests for StringUtils::equals fix comment: not fourth but sixth argument fixing typo in a comment [FrameworkBundle] fixed CS [FrameworkBundle] PhpExtractor bugfix and improvements [Finder] Fix findertest readability [Filesystem] Add FTP stream wrapper context option to enable overwrite (override) fix parsing of Authorization header Test examples from Drupal SA-CORE-2014-003 ... Conflicts: src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/admin.html.twig src/Symfony/Component/Filesystem/Filesystem.php src/Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php
2 parents acd4607 + 6521614 commit 3ee13b9

File tree

7 files changed

+80
-62
lines changed

7 files changed

+80
-62
lines changed

EventListener/FragmentListener.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

1414
use Symfony\Component\HttpFoundation\Request;
15-
use Symfony\Component\HttpFoundation\IpUtils;
1615
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
1716
use Symfony\Component\HttpKernel\KernelEvents;
1817
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
1918
use Symfony\Component\HttpKernel\UriSigner;
19+
use Symfony\Component\HttpKernel\HttpKernelInterface;
2020
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2121

2222
/**
@@ -25,8 +25,8 @@
2525
* All URL paths starting with /_fragment are handled as
2626
* content fragments by this listener.
2727
*
28-
* If the request does not come from a trusted IP, it throws an
29-
* AccessDeniedHttpException exception.
28+
* If throws an AccessDeniedHttpException exception if the request
29+
* is not signed or if it is not an internal sub-request.
3030
*
3131
* @author Fabien Potencier <[email protected]>
3232
*/
@@ -62,7 +62,9 @@ public function onKernelRequest(GetResponseEvent $event)
6262
return;
6363
}
6464

65-
$this->validateRequest($request);
65+
if ($event->isMasterRequest()) {
66+
$this->validateRequest($request);
67+
}
6668

6769
parse_str($request->query->get('_path', ''), $attributes);
6870
$request->attributes->add($attributes);
@@ -77,13 +79,6 @@ protected function validateRequest(Request $request)
7779
throw new AccessDeniedHttpException();
7880
}
7981

80-
// does the Request come from a trusted IP?
81-
$trustedIps = array_merge($this->getLocalIpAddresses(), $request->getTrustedProxies());
82-
$remoteAddress = $request->server->get('REMOTE_ADDR');
83-
if (IpUtils::checkIp($remoteAddress, $trustedIps)) {
84-
return;
85-
}
86-
8782
// is the Request signed?
8883
// we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
8984
if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) {
@@ -93,6 +88,11 @@ protected function validateRequest(Request $request)
9388
throw new AccessDeniedHttpException();
9489
}
9590

91+
/**
92+
* @deprecated Deprecated since 2.3.19, to be removed in 3.0.
93+
*
94+
* @return string[]
95+
*/
9696
protected function getLocalIpAddresses()
9797
{
9898
return array('127.0.0.1', 'fe80::1', '::1');

EventListener/SessionListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ abstract class SessionListener implements EventSubscriberInterface
2525
{
2626
public function onKernelRequest(GetResponseEvent $event)
2727
{
28-
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
28+
if (!$event->isMasterRequest()) {
2929
return;
3030
}
3131

EventListener/TestSessionListener.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ abstract class TestSessionListener implements EventSubscriberInterface
3030
{
3131
public function onKernelRequest(GetResponseEvent $event)
3232
{
33-
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
33+
if (!$event->isMasterRequest()) {
3434
return;
3535
}
3636

@@ -55,7 +55,7 @@ public function onKernelRequest(GetResponseEvent $event)
5555
*/
5656
public function onKernelResponse(FilterResponseEvent $event)
5757
{
58-
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
58+
if (!$event->isMasterRequest()) {
5959
return;
6060
}
6161

Fragment/AbstractSurrogateFragmentRenderer.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpFoundation\Response;
1616
use Symfony\Component\HttpKernel\Controller\ControllerReference;
1717
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
18+
use Symfony\Component\HttpKernel\UriSigner;
1819

1920
/**
2021
* Implements Surrogate rendering strategy.
@@ -25,6 +26,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
2526
{
2627
private $surrogate;
2728
private $inlineStrategy;
29+
private $signer;
2830

2931
/**
3032
* Constructor.
@@ -34,11 +36,13 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
3436
*
3537
* @param SurrogateInterface $surrogate An Surrogate instance
3638
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
39+
* @param UriSigner $signer
3740
*/
38-
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy)
41+
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null)
3942
{
4043
$this->surrogate = $surrogate;
4144
$this->inlineStrategy = $inlineStrategy;
45+
$this->signer = $signer;
4246
}
4347

4448
/**
@@ -64,16 +68,28 @@ public function render($uri, Request $request, array $options = array())
6468
}
6569

6670
if ($uri instanceof ControllerReference) {
67-
$uri = $this->generateFragmentUri($uri, $request);
71+
$uri = $this->generateSignedFragmentUri($uri, $request);
6872
}
6973

7074
$alt = isset($options['alt']) ? $options['alt'] : null;
7175
if ($alt instanceof ControllerReference) {
72-
$alt = $this->generateFragmentUri($alt, $request);
76+
$alt = $this->generateSignedFragmentUri($alt, $request);
7377
}
7478

7579
$tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
7680

7781
return new Response($tag);
7882
}
83+
84+
private function generateSignedFragmentUri($uri, Request $request)
85+
{
86+
if (null === $this->signer) {
87+
throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
88+
}
89+
90+
// we need to sign the absolute URI, but want to return the path only.
91+
$fragmentUri = $this->signer->sign($this->generateFragmentUri($uri, $request, true));
92+
93+
return substr($fragmentUri, strlen($request->getSchemeAndHttpHost()));
94+
}
7995
}

Fragment/SsiFragmentRenderer.php

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,18 @@
1111

1212
namespace Symfony\Component\HttpKernel\Fragment;
1313

14-
use Symfony\Component\HttpKernel\Controller\ControllerReference;
15-
use Symfony\Component\HttpFoundation\Request;
16-
use Symfony\Component\HttpKernel\UriSigner;
17-
1814
/**
1915
* Implements the SSI rendering strategy.
2016
*
2117
* @author Sebastian Krebs <[email protected]>
2218
*/
2319
class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
2420
{
25-
/** @var UriSigner */
26-
private $signer;
27-
28-
/**
29-
* Set uri signer
30-
*
31-
* @param UriSigner $signer
32-
*/
33-
public function setUriSigner(UriSigner $signer)
34-
{
35-
$this->signer = $signer;
36-
}
37-
3821
/**
3922
* {@inheritdoc}
4023
*/
4124
public function getName()
4225
{
4326
return 'ssi';
4427
}
45-
46-
/**
47-
* {@inheritdoc}
48-
*/
49-
protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true)
50-
{
51-
$uri = parent::generateFragmentUri($reference, $request, $absolute, $strict);
52-
53-
if ($this->signer) {
54-
$uri = $this->signer->sign($uri);
55-
}
56-
57-
return $uri;
58-
}
5928
}

Tests/EventListener/FragmentListenerTest.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,6 @@ public function testAccessDeniedWithNonSafeMethods()
4747
$listener->onKernelRequest($event);
4848
}
4949

50-
/**
51-
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
52-
*/
53-
public function testAccessDeniedWithNonLocalIps()
54-
{
55-
$request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
56-
57-
$listener = new FragmentListener(new UriSigner('foo'));
58-
$event = $this->createGetResponseEvent($request);
59-
60-
$listener->onKernelRequest($event);
61-
}
62-
6350
/**
6451
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
6552
*/

Tests/Fragment/EsiFragmentRendererTest.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer;
1616
use Symfony\Component\HttpKernel\HttpCache\Esi;
1717
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpKernel\UriSigner;
1819

1920
class EsiFragmentRendererTest extends \PHPUnit_Framework_TestCase
2021
{
@@ -41,7 +42,52 @@ public function testRender()
4142
$this->assertEquals('<esi:include src="/" />', $strategy->render('/', $request)->getContent());
4243
$this->assertEquals("<esi:comment text=\"This is a comment\" />\n<esi:include src=\"/\" />", $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent());
4344
$this->assertEquals('<esi:include src="/" alt="foo" />', $strategy->render('/', $request, array('alt' => 'foo'))->getContent());
44-
$this->assertEquals('<esi:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" alt="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller" />', $strategy->render(new ControllerReference('main_controller', array(), array()), $request, array('alt' => new ControllerReference('alt_controller', array(), array())))->getContent());
45+
}
46+
47+
public function testRenderControllerReference()
48+
{
49+
$signer = new UriSigner('foo');
50+
$strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(), $signer);
51+
52+
$request = Request::create('/');
53+
$request->setLocale('fr');
54+
$request->headers->set('Surrogate-Capability', 'ESI/1.0');
55+
56+
$reference = new ControllerReference('main_controller', array(), array());
57+
$altReference = new ControllerReference('alt_controller', array(), array());
58+
59+
$this->assertEquals(
60+
'<esi:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller&_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D" alt="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller&_hash=iPJEdRoUpGrM1ztqByiorpfMPtiW%2FOWwdH1DBUXHhEc%3D" />',
61+
$strategy->render($reference, $request, array('alt' => $altReference))->getContent()
62+
);
63+
}
64+
65+
/**
66+
* @expectedException \LogicException
67+
*/
68+
public function testRenderControllerReferenceWithoutSignerThrowsException()
69+
{
70+
$strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy());
71+
72+
$request = Request::create('/');
73+
$request->setLocale('fr');
74+
$request->headers->set('Surrogate-Capability', 'ESI/1.0');
75+
76+
$strategy->render(new ControllerReference('main_controller'), $request);
77+
}
78+
79+
/**
80+
* @expectedException \LogicException
81+
*/
82+
public function testRenderAltControllerReferenceWithoutSignerThrowsException()
83+
{
84+
$strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy());
85+
86+
$request = Request::create('/');
87+
$request->setLocale('fr');
88+
$request->headers->set('Surrogate-Capability', 'ESI/1.0');
89+
90+
$strategy->render('/', $request, array('alt' => new ControllerReference('alt_controller')));
4591
}
4692

4793
private function getInlineStrategy($called = false)

0 commit comments

Comments
 (0)