| 1 |
<?php |
| 2 |
|
| 3 |
/* |
| 4 |
* This file is part of the Symfony package. |
| 5 |
* |
| 6 |
* (c) Fabien Potencier <fabien@symfony.com> |
| 7 |
* |
| 8 |
* For the full copyright and license information, please view the LICENSE |
| 9 |
* file that was distributed with this source code. |
| 10 |
*/ |
| 11 |
namespace WindPressDeps\Symfony\Component\Yaml; |
| 12 |
|
| 13 |
use WindPressDeps\Symfony\Component\Yaml\Exception\ParseException; |
| 14 |
/** |
| 15 |
* Unescaper encapsulates unescaping rules for single and double-quoted |
| 16 |
* YAML strings. |
| 17 |
* |
| 18 |
* @author Matthew Lewinski <matthew@lewinski.org> |
| 19 |
* |
| 20 |
* @internal |
| 21 |
*/ |
| 22 |
class Unescaper |
| 23 |
{ |
| 24 |
/** |
| 25 |
* Regex fragment that matches an escaped character in a double quoted string. |
| 26 |
*/ |
| 27 |
public const REGEX_ESCAPED_CHARACTER = '\\\\(x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8}|.)'; |
| 28 |
/** |
| 29 |
* Unescapes a single quoted string. |
| 30 |
* |
| 31 |
* @param string $value A single quoted string |
| 32 |
*/ |
| 33 |
public function unescapeSingleQuotedString(string $value): string |
| 34 |
{ |
| 35 |
return str_replace('\'\'', '\'', $value); |
| 36 |
} |
| 37 |
/** |
| 38 |
* Unescapes a double quoted string. |
| 39 |
* |
| 40 |
* @param string $value A double quoted string |
| 41 |
*/ |
| 42 |
public function unescapeDoubleQuotedString(string $value): string |
| 43 |
{ |
| 44 |
$callback = function ($match) { |
| 45 |
return $this->unescapeCharacter($match[0]); |
| 46 |
}; |
| 47 |
// evaluate the string |
| 48 |
return preg_replace_callback('/' . self::REGEX_ESCAPED_CHARACTER . '/u', $callback, $value); |
| 49 |
} |
| 50 |
/** |
| 51 |
* Unescapes a character that was found in a double-quoted string. |
| 52 |
* |
| 53 |
* @param string $value An escaped character |
| 54 |
*/ |
| 55 |
private function unescapeCharacter(string $value): string |
| 56 |
{ |
| 57 |
switch ($value[1]) { |
| 58 |
case '0': |
| 59 |
return "\x00"; |
| 60 |
case 'a': |
| 61 |
return "\x07"; |
| 62 |
case 'b': |
| 63 |
return "\x08"; |
| 64 |
case 't': |
| 65 |
return "\t"; |
| 66 |
case "\t": |
| 67 |
return "\t"; |
| 68 |
case 'n': |
| 69 |
return "\n"; |
| 70 |
case 'v': |
| 71 |
return "\v"; |
| 72 |
case 'f': |
| 73 |
return "\f"; |
| 74 |
case 'r': |
| 75 |
return "\r"; |
| 76 |
case 'e': |
| 77 |
return "\x1b"; |
| 78 |
case ' ': |
| 79 |
return ' '; |
| 80 |
case '"': |
| 81 |
return '"'; |
| 82 |
case '/': |
| 83 |
return '/'; |
| 84 |
case '\\': |
| 85 |
return '\\'; |
| 86 |
case 'N': |
| 87 |
// U+0085 NEXT LINE |
| 88 |
return "� |
| 89 |
"; |
| 90 |
case '_': |
| 91 |
// U+00A0 NO-BREAK SPACE |
| 92 |
return " "; |
| 93 |
case 'L': |
| 94 |
// U+2028 LINE SEPARATOR |
| 95 |
return "
"; |
| 96 |
case 'P': |
| 97 |
// U+2029 PARAGRAPH SEPARATOR |
| 98 |
return "
"; |
| 99 |
case 'x': |
| 100 |
return self::utf8chr(hexdec(substr($value, 2, 2))); |
| 101 |
case 'u': |
| 102 |
return self::utf8chr(hexdec(substr($value, 2, 4))); |
| 103 |
case 'U': |
| 104 |
return self::utf8chr(hexdec(substr($value, 2, 8))); |
| 105 |
default: |
| 106 |
throw new ParseException(sprintf('Found unknown escape character "%s".', $value)); |
| 107 |
} |
| 108 |
} |
| 109 |
/** |
| 110 |
* Get the UTF-8 character for the given code point. |
| 111 |
*/ |
| 112 |
private static function utf8chr(int $c): string |
| 113 |
{ |
| 114 |
if (0x80 > $c %= 0x200000) { |
| 115 |
return \chr($c); |
| 116 |
} |
| 117 |
if (0x800 > $c) { |
| 118 |
return \chr(0xc0 | $c >> 6) . \chr(0x80 | $c & 0x3f); |
| 119 |
} |
| 120 |
if (0x10000 > $c) { |
| 121 |
return \chr(0xe0 | $c >> 12) . \chr(0x80 | $c >> 6 & 0x3f) . \chr(0x80 | $c & 0x3f); |
| 122 |
} |
| 123 |
return \chr(0xf0 | $c >> 18) . \chr(0x80 | $c >> 12 & 0x3f) . \chr(0x80 | $c >> 6 & 0x3f) . \chr(0x80 | $c & 0x3f); |
| 124 |
} |
| 125 |
} |
| 126 |
|