From b9a5635e81eeca262ed42ae30698897a8d5be0e9 Mon Sep 17 00:00:00 2001 From: Johnny Wong Date: Fri, 29 Jan 2016 18:43:52 +0800 Subject: [PATCH] Support "!!binary" syntax (decodes base64 string). Only supported in folded-scalar (lines ending with | or >) form, or inline form. Example Yaml: items - name: !!binary "SGVsbG8sIHdvcmxkLg==" desc: !!binary | SGVsbG8sIH dvcmxkLg== --- src/Symfony/Component/Yaml/Inline.php | 3 +++ src/Symfony/Component/Yaml/Parser.php | 8 ++++++-- src/Symfony/Component/Yaml/Tests/InlineTest.php | 3 +++ src/Symfony/Component/Yaml/Tests/ParserTest.php | 12 ++++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index acc400f69c048..b6a697ba4161e 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -21,6 +21,7 @@ */ class Inline { + const REGEX_TAG_PATTERN = '((?P![\w!.\/:-]+) +)?'; const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; private static $exceptionOnInvalidType = false; @@ -500,6 +501,8 @@ private static function evaluateScalar($scalar, $references = array()) return; case 0 === strpos($scalar, '!!float '): return (float) substr($scalar, 8); + case 0 === strncmp($scalar, '!!binary ', 9): + return base64_decode(self::parseScalar(substr($scalar, 9))); case ctype_digit($scalar): $raw = $scalar; $cast = (int) $scalar; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 9e4da1766431e..6939a0d0e448c 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -488,10 +488,14 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob return $this->refs[$value]; } - if (preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { + if (preg_match('/^'.Inline::REGEX_TAG_PATTERN.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + $output = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + if (isset($matches['tag']) && $matches['tag'] == '!!binary') { + $output = base64_decode($output); + } + return $output; } try { diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index ab541dade2bdf..540e4c45fff6f 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -304,6 +304,9 @@ public function getTestsForParseWithMapObjects() array('-12', -12), array('"quoted string"', 'quoted string'), array("'quoted string'", 'quoted string'), + array('!!binary "SGVsbG8sIHdvcmxkLg=="', 'Hello, world.'), + array('!!float 1230', 1230.0), + array('!!unknown "string"', '!!unknown "string"'), array('12.30e+02', 12.30e+02), array('0x4D2', 0x4D2), array('02333', 02333), diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 579cf8ce7d37e..24e9101f8d151 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -788,6 +788,18 @@ public function testNestedFoldedStringBlockWithComments() )); } + public function testFoldedBinaryBlock() + { + $this->assertEquals(array(array('name' => 'Hello, world.', 'desc' => 'Hello, world.')), Yaml::parse(<<<'EOF' +- + name: !!binary "SGVsbG8sIHdvcmxkLg==" + desc: !!binary | + SGVsbG8sIH + dvcmxkLg== +EOF + )); + } + public function testReferenceResolvingInInlineStrings() { $this->assertEquals(array(