Skip to content

Commit

Permalink
Merge branch '5.4' into 6.0
Browse files Browse the repository at this point in the history
* 5.4:
  [Mailer] Include all transports' debug messages in RoundRobin transport exception
  [FrameworkBundle] fix: fix help message
  Use relative timestamps
  [Cache] Fix dealing with ext-redis' multi/exec returning a bool
  [Messenger][Amqp] Added missing rpc_timeout option
  [Serializer] Prevent GetSetMethodNormalizer from creating invalid magic method call
  [HttpFoundation] Fix dumping array cookies
  [WebProfilerBundle] Fix dump header not being displayed
  TraceableHttpClient: increase decorator's priority
  Use static methods inside data providers
  [FrameworkBundle] Allow configuring `framework.exceptions` with a config builder
  bug #48313 [Mime] Fix MessagePart serialization
  [ErrorHandler][DebugClassLoader] Fix some new return types support
  Fix getting the name of closures on PHP 8.1.11+
  [Translator] Fix typo "internal" / "interval"
  fix dumping top-level tagged values
  • Loading branch information
nicolas-grekas committed Dec 14, 2022
2 parents b607109 + 6c7635f commit d970ba5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 38 deletions.
68 changes: 34 additions & 34 deletions Tests/Csp/ContentSecurityPolicyHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public function provideRequestAndResponses()
];

return [
[$nonce, ['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce], $this->createRequest(), $this->createResponse()],
[$nonce, ['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce], $this->createRequest($requestNonceHeaders), $this->createResponse($responseNonceHeaders)],
[$nonce, ['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce], $this->createRequest($requestNonceHeaders), $this->createResponse()],
[$nonce, ['csp_script_nonce' => $responseScriptNonce, 'csp_style_nonce' => $responseStyleNonce], $this->createRequest(), $this->createResponse($responseNonceHeaders)],
[$nonce, ['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce], self::createRequest(), self::createResponse()],
[$nonce, ['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce], self::createRequest($requestNonceHeaders), self::createResponse($responseNonceHeaders)],
[$nonce, ['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce], self::createRequest($requestNonceHeaders), self::createResponse()],
[$nonce, ['csp_script_nonce' => $responseScriptNonce, 'csp_style_nonce' => $responseStyleNonce], self::createRequest(), self::createResponse($responseNonceHeaders)],
];
}

Expand All @@ -96,112 +96,112 @@ public function provideRequestAndResponsesForOnKernelResponse()
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(),
self::createRequest(),
self::createResponse(),
['Content-Security-Policy' => null, 'Content-Security-Policy-Report-Only' => null, 'X-Content-Security-Policy' => null],
],
[
$nonce, ['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce],
$this->createRequest($requestNonceHeaders),
$this->createResponse($responseNonceHeaders),
self::createRequest($requestNonceHeaders),
self::createResponse($responseNonceHeaders),
['Content-Security-Policy' => null, 'Content-Security-Policy-Report-Only' => null, 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $requestScriptNonce, 'csp_style_nonce' => $requestStyleNonce],
$this->createRequest($requestNonceHeaders),
$this->createResponse(),
self::createRequest($requestNonceHeaders),
self::createResponse(),
['Content-Security-Policy' => null, 'Content-Security-Policy-Report-Only' => null, 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $responseScriptNonce, 'csp_style_nonce' => $responseStyleNonce],
$this->createRequest(),
$this->createResponse($responseNonceHeaders),
self::createRequest(),
self::createResponse($responseNonceHeaders),
['Content-Security-Policy' => null, 'Content-Security-Policy-Report-Only' => null, 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'frame-ancestors https: ; form-action: https:', 'Content-Security-Policy-Report-Only' => 'frame-ancestors http: ; form-action: http:']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'frame-ancestors https: ; form-action: https:', 'Content-Security-Policy-Report-Only' => 'frame-ancestors http: ; form-action: http:']),
['Content-Security-Policy' => 'frame-ancestors https: ; form-action: https:', 'Content-Security-Policy-Report-Only' => 'frame-ancestors http: ; form-action: http:', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'']),
['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\'']),
['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' \'unsafe-inline\'; style-src-elem \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'default-src \'none\'', 'Content-Security-Policy-Report-Only' => 'default-src \'none\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'default-src \'none\'', 'Content-Security-Policy-Report-Only' => 'default-src \'none\'']),
['Content-Security-Policy' => 'default-src \'none\'; script-src \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'none\'; script-src \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'']),
['Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'script-src \'self\'; style-src \'self\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'script-src \'self\'; style-src \'self\'']),
['Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'']),
self::createRequest(),
self::createResponse(['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'']),
['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'', 'Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['X-Content-Security-Policy' => 'script-src \'self\'']),
self::createRequest(),
self::createResponse(['X-Content-Security-Policy' => 'script-src \'self\'']),
['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'sha384-LALALALALAAL\'']),
self::createRequest(),
self::createResponse(['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'sha384-LALALALALAAL\'']),
['X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'sha384-LALALALALAAL\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy' => null],
],
[
$nonce,
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'script-src \'self\'; style-src \'self\'', 'X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'; style-src \'self\'']),
self::createRequest(),
self::createResponse(['Content-Security-Policy' => 'script-src \'self\'; style-src \'self\'', 'X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'; style-src \'self\'']),
['Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => 'script-src \'self\' \'unsafe-inline\'; style-src \'self\' \'unsafe-inline\' \'nonce-'.$nonce.'\''],
],
];
}

private function createRequest(array $headers = [])
private static function createRequest(array $headers = [])
{
$request = new Request();
$request->headers->add($headers);

return $request;
}

private function createResponse(array $headers = [])
private static function createResponse(array $headers = [])
{
$response = new Response();
$response->headers->add($headers);
Expand Down
61 changes: 61 additions & 0 deletions Tests/Twig/WebProfilerExtensionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?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\Bundle\WebProfilerBundle\Tests\Twig;

use PHPUnit\Framework\TestCase;
use Symfony\Bundle\WebProfilerBundle\Twig\WebProfilerExtension;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Twig\Environment;
use Twig\Extension\CoreExtension;
use Twig\Extension\EscaperExtension;

class WebProfilerExtensionTest extends TestCase
{
/**
* @dataProvider provideMessages
*/
public function testDumpHeaderIsDisplayed(string $message, array $context, bool $dump1HasHeader, bool $dump2HasHeader)
{
class_exists(CoreExtension::class); // Load twig_convert_encoding()
class_exists(EscaperExtension::class); // Load twig_escape_filter()

$twigEnvironment = $this->mockTwigEnvironment();
$varCloner = new VarCloner();

$webProfilerExtension = new WebProfilerExtension();

$needle = 'window.Sfdump';

$dump1 = $webProfilerExtension->dumpLog($twigEnvironment, $message, $varCloner->cloneVar($context));
self::assertSame($dump1HasHeader, str_contains($dump1, $needle));

$dump2 = $webProfilerExtension->dumpData($twigEnvironment, $varCloner->cloneVar([]));
self::assertSame($dump2HasHeader, str_contains($dump2, $needle));
}

public function provideMessages(): iterable
{
yield ['Some message', ['foo' => 'foo', 'bar' => 'bar'], false, true];
yield ['Some message {@see some text}', ['foo' => 'foo', 'bar' => 'bar'], false, true];
yield ['Some message {foo}', ['foo' => 'foo', 'bar' => 'bar'], true, false];
yield ['Some message {foo}', ['bar' => 'bar'], false, true];
}

private function mockTwigEnvironment()
{
$twigEnvironment = $this->createMock(Environment::class);

$twigEnvironment->expects($this->any())->method('getCharset')->willReturn('UTF-8');

return $twigEnvironment;
}
}
14 changes: 10 additions & 4 deletions Twig/WebProfilerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,19 @@ public function dumpLog(Environment $env, string $message, Data $context = null)
$message = twig_escape_filter($env, $message);
$message = preg_replace('/&quot;(.*?)&quot;/', '&quot;<b>$1</b>&quot;', $message);

if (null === $context || !str_contains($message, '{')) {
$replacements = [];
foreach ($context ?? [] as $k => $v) {
$k = '{'.twig_escape_filter($env, $k).'}';
if (str_contains($message, $k)) {
$replacements[$k] = $v;
}
}

if (!$replacements) {
return '<span class="dump-inline">'.$message.'</span>';
}

$replacements = [];
foreach ($context as $k => $v) {
$k = '{'.twig_escape_filter($env, $k).'}';
foreach ($replacements as $k => $v) {
$replacements['&quot;<b>'.$k.'</b>&quot;'] = $replacements['&quot;'.$k.'&quot;'] = $replacements[$k] = $this->dumpData($env, $v);
}

Expand Down

0 comments on commit d970ba5

Please sign in to comment.