diff --git a/src/Components/Inlines/Image.php b/src/Components/Inlines/Image.php index 053d40e..e8a7606 100644 --- a/src/Components/Inlines/Image.php +++ b/src/Components/Inlines/Image.php @@ -8,6 +8,7 @@ use Erusev\Parsedown\Components\Inline; use Erusev\Parsedown\Configurables\SafeMode; use Erusev\Parsedown\Html\Renderables\Element; use Erusev\Parsedown\Html\Renderables\Text; +use Erusev\Parsedown\Html\Sanitisation\UrlSanitiser; use Erusev\Parsedown\Parsedown; use Erusev\Parsedown\Parsing\Excerpt; use Erusev\Parsedown\State; @@ -84,7 +85,7 @@ final class Image implements Inline } if ($State->get(SafeMode::class)->isEnabled()) { - $attributes['src'] = Element::filterUnsafeUrl($attributes['src']); + $attributes['src'] = UrlSanitiser::filter($attributes['src']); } return Element::selfClosing('img', $attributes); diff --git a/src/Components/Inlines/Link.php b/src/Components/Inlines/Link.php index 9d14d2e..76978de 100644 --- a/src/Components/Inlines/Link.php +++ b/src/Components/Inlines/Link.php @@ -10,6 +10,7 @@ use Erusev\Parsedown\Configurables\InlineTypes; use Erusev\Parsedown\Configurables\SafeMode; use Erusev\Parsedown\Html\Renderables\Element; use Erusev\Parsedown\Html\Renderables\Text; +use Erusev\Parsedown\Html\Sanitisation\UrlSanitiser; use Erusev\Parsedown\Parsedown; use Erusev\Parsedown\Parsing\Excerpt; use Erusev\Parsedown\State; @@ -124,7 +125,7 @@ final class Link implements Inline } if ($State->get(SafeMode::class)->isEnabled()) { - $attributes['href'] = Element::filterUnsafeUrl($attributes['href']); + $attributes['href'] = UrlSanitiser::filter($attributes['href']); } $State = $State->setting( diff --git a/src/Html/Renderables/Element.php b/src/Html/Renderables/Element.php index af08727..01abf96 100644 --- a/src/Html/Renderables/Element.php +++ b/src/Html/Renderables/Element.php @@ -62,25 +62,6 @@ final class Element implements Renderable 'basefont' => true, ]; - /** @var string[] */ - public static $COMMON_SCHEMES = [ - 'http://', - 'https://', - 'ftp://', - 'ftps://', - 'mailto:', - 'tel:', - 'data:image/png;base64,', - 'data:image/gif;base64,', - 'data:image/jpeg;base64,', - 'irc:', - 'ircs:', - 'git:', - 'ssh:', - 'news:', - 'steam:', - ]; - /** @var string */ private $name; @@ -224,40 +205,4 @@ final class Element implements Renderable return $html; } - - /** - * @param string $url - * @param string[]|null $permittedSchemes - * @return string - */ - public static function filterUnsafeUrl($url, $permittedSchemes = null) - { - if (! isset($permittedSchemes)) { - $permittedSchemes = self::$COMMON_SCHEMES; - } - - foreach ($permittedSchemes as $scheme) { - if (self::striAtStart($url, $scheme)) { - return $url; - } - } - - return \str_replace(':', '%3A', $url); - } - - /** - * @param string $string - * @param string $needle - * @return bool - */ - private static function striAtStart($string, $needle) - { - $len = \strlen($needle); - - if ($len > \strlen($string)) { - return false; - } else { - return \strtolower(\substr($string, 0, $len)) === \strtolower($needle); - } - } } diff --git a/src/Html/Sanitisation/UrlSanitiser.php b/src/Html/Sanitisation/UrlSanitiser.php new file mode 100644 index 0000000..0979566 --- /dev/null +++ b/src/Html/Sanitisation/UrlSanitiser.php @@ -0,0 +1,63 @@ + \strlen($string)) { + return false; + } else { + return \strtolower(\substr($string, 0, $len)) === \strtolower($needle); + } + } +}