Skip to content

Commit

Permalink
Filter |noescape preserves some escaping in some contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 12, 2022
1 parent c36a143 commit 13436ee
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 3 deletions.
17 changes: 17 additions & 0 deletions src/Latte/Compiler/Escaper.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,23 @@ public function escape(string $str): string
}


public function escapeRequisite(string $str): string
{
return match ($this->contentType) {
ContentType::Html => match ($this->state) {
self::HtmlAttribute => $this->quote ? 'LR\Filters::escapeHtmlChar(' . $str . ', ' . var_export($this->quote, true) . ')' : $str,
self::HtmlRawText => 'LR\Filters::escapeHtmlRawText(' . $str . ')',
default => $str,
},
ContentType::Xml => match ($this->state) {
self::HtmlAttribute => $this->quote ? 'LR\Filters::escapeHtmlChar(' . $str . ', ' . var_export($this->quote, true) . ')' : $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->escapeRequisite($expr);

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


/**
* Escapes a certain special character.
*/
public static function escapeHtmlChar($s, string $char): string
{
return str_replace(
$char,
htmlspecialchars($char, ENT_QUOTES | ENT_HTML5),
(string) $s,
);
}


/**
* Escapes string for use everywhere inside XML (except for comments).
*/
Expand Down
71 changes: 71 additions & 0 deletions tests/common/Compiler.noescape.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* Test: |noescape
*/

declare(strict_types=1);

use Tester\Assert;


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


$latte = new Latte\Engine;
$latte->setLoader(new Latte\Loaders\StringLoader);

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

// raw text
Assert::match(
'<script><\/script></script>',
$latte->renderToString('<script>{="</script>"|noescape}</script>'),
);

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

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

// in tag
Assert::match(
'<p foo a=\'a\' b="b">></p>',
$latte->renderToString('<p {="foo a=\'a\' b=\"b\">"|noescape}></p>'),
);

// attribute unquoted values
Assert::match(
'<p title=foo a=\'a\' b="b">></p>',
$latte->renderToString('<p title={="foo a=\'a\' b=\"b\">"|noescape}></p>'),
);

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

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

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

Assert::match(
'<p onclick="foo a=\'a\' b=&quot;b&quot;>"></p>',
$latte->renderToString('<p onclick="{="foo a=\'a\' b=\"b\">"|noescape}"></p>'),
);
22 changes: 22 additions & 0 deletions tests/filters/escapeHtmlChar.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

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

declare(strict_types=1);

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

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


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

0 comments on commit 13436ee

Please sign in to comment.