Skip to content

Commit

Permalink
implemented mandatory escaping (cannot be disabled using |noescape)
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 11, 2023
1 parent 22bd941 commit 5b3bc33
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 8 deletions.
20 changes: 20 additions & 0 deletions src/Latte/Compiler/Escaper.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,26 @@ public function escape(string $str): string
}


public function escapeMandatory(string $str): string
{
return match ($this->contentType) {
ContentType::Html => match ($this->state) {
self::HtmlAttribute => "LR\\Filters::escapeHtmlQuotes($str)",
self::HtmlRawText => match ($this->subType) {
self::HtmlText => 'LR\Filters::convertHtmlToHtmlRawText(' . $str . ')',
default => "LR\\Filters::convertJSToHtmlRawText($str)",
},
default => $str,
},
ContentType::Xml => match ($this->state) {
self::HtmlAttribute => "LR\\Filters::escapeHtmlQuotes($str)",
default => $str,
},
default => $str,
};
}


public function check(string $str): string
{
if ($this->state === self::HtmlAttribute && $this->subType === self::Url) {
Expand Down
6 changes: 3 additions & 3 deletions src/Latte/Compiler/Nodes/Php/ModifierNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ public function printSimple(PrintContext $context, string $expr): string
$expr = $escaper->check($expr);
}

if ($escape) {
$expr = $escaper->escape($expr);
}
$expr = $escape
? $escaper->escape($expr)
: $escaper->escapeMandatory($expr);

return $expr;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Latte/Runtime/Filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ public static function escapeHtmlRawTextHtml($s): string
}


/**
* Escapes only quotes.
*/
public static function escapeHtmlQuotes($s): string
{
return strtr((string) $s, ['"' => '"', "'" => ''']);
}


/**
* Escapes string for use everywhere inside XML (except for comments and tags).
*/
Expand Down
2 changes: 1 addition & 1 deletion tests/common/contentType.html.css.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ Assert::match(

// no escape
Assert::match(
'<style></style></style>',
'<style><\/style></style>',
$latte->renderToString('<style>{="</style>"|noescape}</style>'),
);
2 changes: 1 addition & 1 deletion tests/common/contentType.html.javascript.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,6 @@ Assert::match(

// no escape
Assert::match(
'<script></script></script>',
'<script><\/script></script>',
$latte->renderToString('<script>{="</script>"|noescape}</script>'),
);
4 changes: 2 additions & 2 deletions tests/common/contentType.html.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ Assert::match(

// no escape in attribute
Assert::match(
'<p title="foo a=\'a\' b="b">"></p>',
'<p title="foo a=&apos;a&apos; b=&quot;b&quot;>"></p>',
$latte->renderToString('<p title={="foo a=\'a\' b=\"b\">"|noescape}></p>'),
);

// no escape in JS attribute
Assert::match(
'<p onclick="foo a=\'a\' b="b">"></p>',
'<p onclick="foo a=&apos;a&apos; b=&quot;b&quot;>"></p>',
$latte->renderToString('<p onclick="{="foo a=\'a\' b=\"b\">"|noescape}"></p>'),
);
2 changes: 1 addition & 1 deletion tests/common/contentType.html.script-html.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Assert::match(

// no escape
Assert::match(
'<script type="text/html"></script></script>',
'<script type="text/html"></x-script></script>',
$latte->renderToString('<script type="text/html">{="</script>"|noescape}</script>'),
);

Expand Down
6 changes: 6 additions & 0 deletions tests/common/contentType.html.script-unknown.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ Assert::exception(
'Including block a with content type HTML into incompatible type HTML/RAW/TEXT.',
);

// no escape
Assert::match(
'<script type="foo"><\/script></script>',
$latte->renderToString('<script type="foo">{="</script>"|noescape}</script>'),
);

// content of <script> is RAWTEXT
Assert::match(
<<<'XX'
Expand Down
20 changes: 20 additions & 0 deletions tests/filters/escapeHtmlQuotes.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* Test: Latte\Runtime\Filters::escapeHtmlQuotes
*/

declare(strict_types=1);

use Latte\Runtime\Filters;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


Assert::same('', Filters::escapeHtmlQuotes(null));
Assert::same('', Filters::escapeHtmlQuotes(''));
Assert::same('1', Filters::escapeHtmlQuotes(1));
Assert::same('string', Filters::escapeHtmlQuotes('string'));
Assert::same('< & &apos; &quot; >', Filters::escapeHtmlQuotes('< & \' " >'));
Assert::same('&quot;', Filters::escapeHtmlQuotes('&quot;'));

0 comments on commit 5b3bc33

Please sign in to comment.