Skip to content

Commit

Permalink
escaping: automatically escapes URL parts
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jun 1, 2022
1 parent becbb1b commit 4c96b66
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 7 deletions.
10 changes: 6 additions & 4 deletions src/Latte/Compiler/Escaper.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ final class Escaper
JavaScript = 'js',
Css = 'css',
ICal = 'ical',
Url = 'url';
Url = 'url',
UrlPart = 'url-part';

public const
HtmlText = 'html',
Expand Down Expand Up @@ -101,13 +102,13 @@ public function enterHtmlTag(string $name): void
}


public function enterHtmlAttribute(?string $name = null, string $quote = ''): void
public function enterHtmlAttribute(?string $name = null, string $quote = '', string $subType = ''): void
{
$this->state = self::HtmlAttribute;
$this->quote = $quote;
$this->subType = '';
$this->subType = $subType;

if ($this->contentType === ContentType::Html && is_string($name)) {
if ($this->contentType === ContentType::Html && !$this->subType && $name) {
$name = strtolower($name);
if (str_starts_with($name, 'on')) {
$this->subType = self::JavaScript;
Expand Down Expand Up @@ -150,6 +151,7 @@ public function escape(string $str): string
self::HtmlAttribute => match ($this->subType) {
'',
self::Url => $lq . 'LR\Filters::escapeHtmlAttr(' . $str . ')' . $rq,
self::UrlPart => $lq . 'LR\Filters::escapeHtmlAttr(rawurlencode(' . $str . '))' . $rq,
self::JavaScript => $lq . 'LR\Filters::escapeHtmlAttr(LR\Filters::escapeJs(' . $str . '))' . $rq,
self::Css => $lq . 'LR\Filters::escapeHtmlAttr(LR\Filters::escapeCss(' . $str . '))' . $rq,
},
Expand Down
2 changes: 1 addition & 1 deletion src/Latte/Compiler/Nodes/Html/QuotedValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function print(PrintContext $context): string
if ($this->value instanceof FragmentNode && $escaper->export() === 'html/attr/url') {
foreach ($this->value->children as $child) {
$res .= $child->print($context);
$escaper->enterHtmlAttribute(null, $this->quote);
$escaper->enterHtmlAttribute(null, $this->quote, $escaper::UrlPart);
}
} else {
$res .= $this->value->print($context);
Expand Down
6 changes: 5 additions & 1 deletion src/Latte/Compiler/Nodes/Php/ModifierNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,17 @@ public function printSimple(PrintContext $context, string $expr): string
{
$escape = $this->escape;
$check = $this->check;
$escaper = $context->getEscaper();
$export = $escaper->export();

foreach ($this->filters as $filter) {
$name = $filter->name->name;
if (['nocheck' => 1, 'noCheck' => 1][$name] ?? null) {
$check = false;
} elseif ($name === 'noescape') {
$escape = false;
} elseif ($name === 'escapeUrl' && $export === 'html/attr/url-part') {
// prevent double escaping
} else {
if (['datastream' => 1, 'dataStream' => 1][$name] ?? null) {
$check = false;
Expand All @@ -63,7 +68,6 @@ public function printSimple(PrintContext $context, string $expr): string
}
}

$escaper = $context->getEscaper();
if ($check) {
$expr = $escaper->check($expr);
}
Expand Down
8 changes: 7 additions & 1 deletion tests/common/Safe.url.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Assert::match('
<a href="" src="" action="" formaction="" title="javascript:alert(1)"></a>
<a href=""></a>
<a href="javascript:alert(1)"></a>
<a href="http://nette.org?val=javascript:alert(1)"></a>
<a href="http://nette.org?val=javascript%3Aalert%281%29"></a>
<a data="javascript:alert(1)"></a>
<OBJECT DATA=""></OBJECT>
<a HREF=""></a>
Expand Down Expand Up @@ -77,3 +77,9 @@ Assert::contains(
'LR\Filters::escapeHtmlAttr(LR\Filters::safeUrl(($this->filters->upper)($url1)))',
$latte->compile('<a href="{$url1|upper}"></a>'),
);


Assert::contains(
'echo LR\Filters::escapeHtmlAttr(rawurlencode($url1)) /* line 1 */',
$latte->compile('<a href="http://nette.org?val={$url1|escapeUrl}"></a>'),
);

0 comments on commit 4c96b66

Please sign in to comment.