From 5b167412e1a2cac5f1ce70bbb88583752eb39286 Mon Sep 17 00:00:00 2001 From: Michael O'Connell Date: Thu, 21 Mar 2024 11:45:07 -0500 Subject: [PATCH 1/2] prevent already escaped double quotes from being escaped again, causing a syntax error --- src/Util/StringLiteralFormatter.php | 2 +- tests/StringLiteralFormatterTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Util/StringLiteralFormatter.php b/src/Util/StringLiteralFormatter.php index 523bad9..4b0f132 100644 --- a/src/Util/StringLiteralFormatter.php +++ b/src/Util/StringLiteralFormatter.php @@ -20,7 +20,7 @@ public static function formatValueForRHS($value): string { if (is_string($value)) { if (!static::isVariable($value)) { - $value = str_replace('"', '\"', $value); + $value = preg_replace(['/([^\\\])"/', '/^"/'], ['$1\"', '\"'], $value); if (strpos($value, "\n") !== false) { $value = '"""' . $value . '"""'; } else { diff --git a/tests/StringLiteralFormatterTest.php b/tests/StringLiteralFormatterTest.php index 792392b..f14bd6e 100644 --- a/tests/StringLiteralFormatterTest.php +++ b/tests/StringLiteralFormatterTest.php @@ -34,6 +34,9 @@ public function testFormatForClassRHSValue() $formattedString = StringLiteralFormatter::formatValueForRHS("\"quotedString\""); $this->assertEquals('"\"quotedString\""', $formattedString); + $formattedString = StringLiteralFormatter::formatValueForRHS(''); + $this->assertEquals('""', $formattedString); + $formattedString = StringLiteralFormatter::formatValueForRHS('\'singleQuotes\''); $this->assertEquals('"\'singleQuotes\'"', $formattedString); From 803474d4d3b3dc67c3c2017f051b82cecbd9e457 Mon Sep 17 00:00:00 2001 From: Michael O'Connell Date: Thu, 28 Mar 2024 18:26:50 -0500 Subject: [PATCH 2/2] change string escape to be a direct port of the javascript implementation --- src/Util/StringLiteralFormatter.php | 28 +++++++++++++++++++++++++++- tests/StringLiteralFormatterTest.php | 10 +++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/Util/StringLiteralFormatter.php b/src/Util/StringLiteralFormatter.php index 4b0f132..2d78a5f 100644 --- a/src/Util/StringLiteralFormatter.php +++ b/src/Util/StringLiteralFormatter.php @@ -9,6 +9,29 @@ */ class StringLiteralFormatter { + const ESCAPE_SEQUENCES = [ + '\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', '\\u0005', '\\u0006', '\\u0007', + '\\b', '\\t', '\\n', '\\u000B', '\\f', '\\r', '\\u000E', '\\u000F', + '\\u0010', '\\u0011', '\\u0012', '\\u0013', '\\u0014', '\\u0015', '\\u0016', '\\u0017', + '\\u0018', '\\u0019', '\\u001A', '\\u001B', '\\u001C', '\\u001D', '\\u001E', '\\u001F', + '', '', '\\"', '', '', '', '', '', + '', '', '', '', '', '', '', '', // 2F + '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', // 3F + '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', // 4F + '', '', '', '', '', '', '', '', + '', '', '', '', '\\\\', '', '', '', // 5F + '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', // 6F + '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '\\u007F', + '\\u0080', '\\u0081', '\\u0082', '\\u0083', '\\u0084', '\\u0085', '\\u0086', '\\u0087', + '\\u0088', '\\u0089', '\\u008A', '\\u008B', '\\u008C', '\\u008D', '\\u008E', '\\u008F', + '\\u0090', '\\u0091', '\\u0092', '\\u0093', '\\u0094', '\\u0095', '\\u0096', '\\u0097', + '\\u0098', '\\u0099', '\\u009A', '\\u009B', '\\u009C', '\\u009D', '\\u009E', '\\u009F', + ]; + /** * Converts the value provided to the equivalent RHS value to be put in a file declaration * @@ -20,10 +43,13 @@ public static function formatValueForRHS($value): string { if (is_string($value)) { if (!static::isVariable($value)) { - $value = preg_replace(['/([^\\\])"/', '/^"/'], ['$1\"', '\"'], $value); if (strpos($value, "\n") !== false) { $value = '"""' . $value . '"""'; } else { + $value = preg_replace_callback('/[\x00-\x1f\x22\x5c\x7f-\x9f]/u', function(array $matches) { + $str = $matches[0]; + return self::ESCAPE_SEQUENCES[ord($str[0])]; + }, $value); $value = "\"$value\""; } } diff --git a/tests/StringLiteralFormatterTest.php b/tests/StringLiteralFormatterTest.php index f14bd6e..1888ec6 100644 --- a/tests/StringLiteralFormatterTest.php +++ b/tests/StringLiteralFormatterTest.php @@ -35,7 +35,7 @@ public function testFormatForClassRHSValue() $this->assertEquals('"\"quotedString\""', $formattedString); $formattedString = StringLiteralFormatter::formatValueForRHS(''); - $this->assertEquals('""', $formattedString); + $this->assertEquals('""', $formattedString); $formattedString = StringLiteralFormatter::formatValueForRHS('\'singleQuotes\''); $this->assertEquals('"\'singleQuotes\'"', $formattedString); @@ -43,11 +43,11 @@ public function testFormatForClassRHSValue() $formattedString = StringLiteralFormatter::formatValueForRHS("with \n newlines"); $this->assertEquals("\"\"\"with \n newlines\"\"\"", $formattedString); - $formattedString = StringLiteralFormatter::formatValueForRHS('$var'); - $this->assertEquals('$var', $formattedString); + $formattedString = StringLiteralFormatter::formatValueForRHS('$var'); + $this->assertEquals('$var', $formattedString); - $formattedString = StringLiteralFormatter::formatValueForRHS('$400'); - $this->assertEquals('"$400"', $formattedString); + $formattedString = StringLiteralFormatter::formatValueForRHS('$400'); + $this->assertEquals('"$400"', $formattedString); // Integer tests $integerString = StringLiteralFormatter::formatValueForRHS(25);