diff --git a/composer.json b/composer.json index acc00b0..5398c21 100644 --- a/composer.json +++ b/composer.json @@ -16,11 +16,15 @@ ], "require": { "php": ">= 7.2", - "nette/utils": "^3.2.5" + "ext-json": "*" }, "require-dev": { - "phpstan/phpstan": "^0.12.98", - "nette/tester": "^2.4" + "nette/tester": "^2.4", + "nette/utils": "^3.2.5", + "phpstan/phpstan": "^0.12.98" + }, + "suggest": { + "nette/utils": "Allows to safe escape HTML with markup: https://doc.nette.org/en/utils/html-elements" }, "autoload": { "psr-4": { @@ -30,5 +34,8 @@ "scripts": { "phpstan": "phpstan analyze src -c phpstan.neon --level 7", "tester": "tester tests" + }, + "config": { + "sort-packages": true } } diff --git a/src/Escape.php b/src/Escape.php index 3ba327f..cf8e403 100644 --- a/src/Escape.php +++ b/src/Escape.php @@ -7,7 +7,7 @@ use Nette\HtmlStringable; use Nette\Utils\IHtmlString; -use Nette\Utils\Json; +use RuntimeException; /** * Escape funxtions. Uses UTF-8 only. @@ -28,7 +28,7 @@ class Escape public static function html($data): string { if ($data instanceof HtmlStringable || $data instanceof IHtmlString) { - return $data->__toString(); + return (string)$data; } return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5 | ENT_SUBSTITUTE); } @@ -78,10 +78,11 @@ public static function htmlComment($data): string */ public static function xml($data): string { + $data = (string)$data; // XML 1.0: \x09 \x0A \x0D and C1 allowed directly, C0 forbidden // XML 1.1: \x00 forbidden directly and as a character reference, // \x09 \x0A \x0D \x85 allowed directly, C0, C1 and \x7F allowed as character references - $data = preg_replace('#[\x00-\x08\x0B\x0C\x0E-\x1F]#', "\u{FFFD}", (string)$data); + $data = preg_replace('#[\x00-\x08\x0B\x0C\x0E-\x1F]#', "\u{FFFD}", $data); return htmlspecialchars($data, ENT_QUOTES | ENT_XML1 | ENT_SUBSTITUTE, 'UTF-8'); } @@ -95,10 +96,14 @@ public static function xml($data): string public static function js($data): string { if ($data instanceof HtmlStringable || $data instanceof IHtmlString) { - $data = $data->__toString(); + $data = (string)$data; } - $json = Json::encode($data); + $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION); + + if ($json === false) { + throw new RuntimeException("JSON encode failed: " . json_last_error_msg(), json_last_error()); + } return str_replace([']]>', '?@[\\]^`{|}~"); + return addcslashes($data, "\x00..\x1F!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~"); } /** @@ -123,17 +129,18 @@ public static function css($data): string */ public static function url($url): string { - return urlencode((string)$url); + $url = (string)$url; + return urlencode($url); } /** * Just returns argument as is without any escaping * Method is useful to mark code as intentionally unescaped as opposed to simple neglected - * @param string|mixed $url + * @param string|mixed $data * @return string */ - public static function noescape($url): string + public static function noescape($data): string { - return (string)$url; + return (string)$data; } } diff --git a/src/EscapeCss.php b/src/EscapeCss.php index 8d13635..8c4c6b1 100644 --- a/src/EscapeCss.php +++ b/src/EscapeCss.php @@ -5,8 +5,6 @@ namespace JakubBoucek\Escape; -use Nette\Utils\Strings; - class EscapeCss { /** @@ -43,12 +41,12 @@ class EscapeCss */ public static function color(string $color): string { - $valid = (bool)Strings::match( - $color, - '/^\s*(?:[-a-zA-Z]+|#[\da-fA-F]{3,8}|(?:rgba?|hsla?|lch|lab)\([\d,.%\\/ ]+\))\s*$/D' + $result = preg_match( + '/^\s*(?:[-a-zA-Z]+|#[\da-fA-F]{3,8}|(?:rgba?|hsla?|lch|lab)\([\d,.%\\/ ]+\))\s*$/D', + $color ); - if ($valid === false) { + if ($result !== 1) { return ''; }