Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ae6f141

Browse filesBrowse files
committed
[Yaml] add support for parsing the !!binary tag
1 parent ff87f30 commit ae6f141
Copy full SHA for ae6f141

File tree

5 files changed

+154
-2
lines changed
Filter options

5 files changed

+154
-2
lines changed

‎src/Symfony/Component/Yaml/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ CHANGELOG
44
3.1.0
55
-----
66

7+
* Added support for parsing base64 encoded binary data when they are tagged
8+
with the `!!binary` tag.
9+
710
* Added support for parsing timestamps as `\DateTime` objects:
811

912
```php

‎src/Symfony/Component/Yaml/Inline.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Inline.php
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ private static function evaluateScalar($scalar, $flags, $references = array())
576576
return -log(0);
577577
case '-.inf' === $scalarLower:
578578
return log(0);
579+
case 0 === strpos($scalar, '!!binary '):
580+
return self::evaluateBinaryScalar(substr($scalar, 9));
579581
case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
580582
return (float) str_replace(',', '', $scalar);
581583
case preg_match(self::getTimestampRegex(), $scalar):
@@ -595,6 +597,28 @@ private static function evaluateScalar($scalar, $flags, $references = array())
595597
}
596598
}
597599

600+
/**
601+
* @param string $scalar
602+
*
603+
* @return string
604+
*
605+
* @internal
606+
*/
607+
public static function evaluateBinaryScalar($scalar)
608+
{
609+
$parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar));
610+
611+
if (0 !== (strlen($parsedBinaryData) % 4)) {
612+
throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', strlen($parsedBinaryData)));
613+
}
614+
615+
if (!preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) {
616+
throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData));
617+
}
618+
619+
return base64_decode($parsedBinaryData, true);
620+
}
621+
598622
/**
599623
* Gets a regex that matches a YAML date.
600624
*

‎src/Symfony/Component/Yaml/Parser.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Parser.php
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
class Parser
2222
{
23+
const TAG_PATTERN = '((?P<tag>![\w!.\/:-]+) +)?';
2324
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
2425

2526
private $offset = 0;
@@ -516,10 +517,16 @@ private function parseValue($value, $flags, $context)
516517
return $this->refs[$value];
517518
}
518519

519-
if (preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) {
520+
if (preg_match('/^'.self::TAG_PATTERN.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) {
520521
$modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
521522

522-
return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));
523+
$data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));
524+
525+
if (isset($matches['tag']) && '!!binary' === $matches['tag']) {
526+
return Inline::evaluateBinaryScalar($data);
527+
}
528+
529+
return $data;
523530
}
524531

525532
try {

‎src/Symfony/Component/Yaml/Tests/InlineTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Tests/InlineTest.php
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,4 +532,41 @@ public function getDateTimeDumpTests()
532532

533533
return $tests;
534534
}
535+
536+
/**
537+
* @dataProvider getBinaryData
538+
*/
539+
public function testParseBinaryData($data)
540+
{
541+
$this->assertSame('Hello world', Inline::parse($data));
542+
}
543+
544+
public function getBinaryData()
545+
{
546+
return array(
547+
'enclosed with double quotes' => array('!!binary "SGVsbG8gd29ybGQ="'),
548+
'enclosed with single quotes' => array("!!binary 'SGVsbG8gd29ybGQ='"),
549+
'containing spaces' => array('!!binary "SGVs bG8gd 29ybGQ="'),
550+
);
551+
}
552+
553+
/**
554+
* @dataProvider getInvalidBinaryData
555+
*/
556+
public function testParseInvalidBinaryData($data, $expectedMessage)
557+
{
558+
$this->setExpectedExceptionRegExp('\Symfony\Component\Yaml\Exception\ParseException', $expectedMessage);
559+
560+
Inline::parse($data);
561+
}
562+
563+
public function getInvalidBinaryData()
564+
{
565+
return array(
566+
'length not a multiple of four' => array('!!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'),
567+
'invalid characters' => array('!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'),
568+
'too many equals characters' => array('!!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'),
569+
'misplaced equals character' => array('!!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'),
570+
);
571+
}
535572
}

‎src/Symfony/Component/Yaml/Tests/ParserTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Tests/ParserTest.php
+81Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,87 @@ public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks()
11201120
$this->parser->parse($yaml)
11211121
);
11221122
}
1123+
1124+
/**
1125+
* @dataProvider getBinaryData
1126+
*/
1127+
public function testParseBinaryData($data)
1128+
{
1129+
$this->assertSame(array('data' => 'Hello world'), $this->parser->parse($data));
1130+
}
1131+
1132+
public function getBinaryData()
1133+
{
1134+
return array(
1135+
'enclosed with double quotes' => array('data: !!binary "SGVsbG8gd29ybGQ="'),
1136+
'enclosed with single quotes' => array("data: !!binary 'SGVsbG8gd29ybGQ='"),
1137+
'containing spaces' => array('data: !!binary "SGVs bG8gd 29ybGQ="'),
1138+
'in block scalar' => array(
1139+
<<<EOT
1140+
data: !!binary |
1141+
SGVsbG8gd29ybGQ=
1142+
EOT
1143+
),
1144+
'containing spaces in block scalar' => array(
1145+
<<<EOT
1146+
data: !!binary |
1147+
SGVs bG8gd 29ybGQ=
1148+
EOT
1149+
),
1150+
);
1151+
}
1152+
1153+
/**
1154+
* @dataProvider getInvalidBinaryData
1155+
*/
1156+
public function testParseInvalidBinaryData($data, $expectedMessage)
1157+
{
1158+
$this->setExpectedExceptionRegExp('\Symfony\Component\Yaml\Exception\ParseException', $expectedMessage);
1159+
1160+
$this->parser->parse($data);
1161+
}
1162+
1163+
public function getInvalidBinaryData()
1164+
{
1165+
return array(
1166+
'length not a multiple of four' => array('data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'),
1167+
'invalid characters' => array('!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'),
1168+
'too many equals characters' => array('data: !!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'),
1169+
'misplaced equals character' => array('data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'),
1170+
'length not a multiple of four in block scalar' => array(
1171+
<<<EOT
1172+
data: !!binary |
1173+
SGVsbG8d29ybGQ=
1174+
EOT
1175+
,
1176+
'/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/',
1177+
),
1178+
'invalid characters in block scalar' => array(
1179+
<<<EOT
1180+
data: !!binary |
1181+
SGVsbG8#d29ybGQ=
1182+
EOT
1183+
,
1184+
'/The base64 encoded data \(.*\) contains invalid characters/',
1185+
),
1186+
'too many equals characters in block scalar' => array(
1187+
<<<EOT
1188+
data: !!binary |
1189+
SGVsbG8gd29yb===
1190+
EOT
1191+
,
1192+
'/The base64 encoded data \(.*\) contains invalid characters/',
1193+
),
1194+
'misplaced equals character in block scalar' => array(
1195+
<<<EOT
1196+
data: !!binary |
1197+
SGVsbG8gd29ybG=Q
1198+
EOT
1199+
,
1200+
'/The base64 encoded data \(.*\) contains invalid characters/',
1201+
),
1202+
);
1203+
}
11231204
}
11241205

11251206
class B

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.