Skip to content

Commit

Permalink
Merge pull request #9 from jakubboucek/safeUrl
Browse files Browse the repository at this point in the history
Add `safeUrl()` and `htmlHref()`
  • Loading branch information
jakubboucek authored Sep 26, 2022
2 parents 1d81731 + 3aa9714 commit 0de2c39
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Package is substrate of [Latte package](https://github.com/nette/latte/)

- Escape HTML
- Escape HTML attributes
- Escape HTML href attributes
- Escape HTML comments
- Escape XML
- Escape JS
Expand Down
31 changes: 31 additions & 0 deletions src/Escape.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public static function htmlAttr($data): string
return self::html($data);
}

/**
* Escapes string for use inside HTML attribute `href` or `src` which contains URL string.
* @param string|mixed $data
* @return string
*/
public static function htmlHref($data): string
{
return self::htmlAttr(self::safeUrl($data));
}

/**
* Escapes string for use inside HTML comments.
* @param string|mixed $data
Expand Down Expand Up @@ -140,6 +150,27 @@ public static function url($data): string
return urlencode($data);
}

/**
* Sanitizes string for use inside href attribute.
* @param string|mixed $data
* @param bool $warning
* @return string
*
* @link https://api.nette.org/2.4/source-Latte.Runtime.Filters.php.html#_safeUrl
*/
public static function safeUrl($data, bool $warning = false):string
{
if (preg_match('~^(?:(?:https?|ftp)://[^@]+(?:/.*)?|(?:mailto|tel|sms):.+|[/?#].*|[^:]+)$~Di', (string)$data)) {
return (string)$data;
}

if($warning) {
trigger_error('URL was removed because is invalid or unsafe: ' . $data, E_USER_WARNING);
}

return '';
}

/**
* Just returns argument as is without any escaping.
* Method is useful to mark code as intentionally unescaped as opposed to simple neglected.
Expand Down
49 changes: 49 additions & 0 deletions tests/EscapeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ public function testHtmlAttr(string $expected, $data): void
Assert::same($expected, Escape::htmlAttr($data));
}

public function getHtmlHrefArgs(): array
{
return [
['', ''],
['http://example.com/foo/bar.txt?par=var', 'http://example.com/foo/bar.txt?par=var'],
['', 'javascript:alert(1)'],
];
}

/**
* @dataProvider getHtmlHrefArgs
*/
public function testHtmlHref(string $expected, $data): void
{
Assert::same($expected, Escape::htmlHref($data));
}

public function getHtmlCommentArgs(): array
{
return [
Expand Down Expand Up @@ -232,6 +249,38 @@ public function testUrl(string $expected, $data): void
Assert::same($expected, Escape::url($data));
}

public function getSafeUrlArgs(): array
{
return [
['', null],
['', ''],
['', 'http://'],
['http://x', 'http://x'],
['http://x:80', 'http://x:80'],
['', 'http://nette.org@1572395127'],
['https://x', 'https://x'],
['ftp://x', 'ftp://x'],
['mailto:x', 'mailto:x'],
['/', '/'],
['/a:b', '/a:b'],
['//x', '//x'],
['#aa:b', '#aa:b'],
['', 'data:'],
['', 'javascript:'],
['', ' javascript:'],
['javascript', 'javascript'],
['http://example.com', Html::fromHtml('http://example.com')],
];
}

/**
* @dataProvider getSafeUrlArgs
*/
public function testSafeUrl(string $expected, $data): void
{
Assert::same($expected, Escape::safeUrl($data));
}

public function getNoescapeArgs(): array
{
return [
Expand Down

0 comments on commit 0de2c39

Please sign in to comment.