Skip to content

Commit

Permalink
Fix nested entity expansion.
Browse files Browse the repository at this point in the history
By using DOMDocument we can avoid internal entity expansion issues
that SimpleXMLElement will not prevent.

I've added some tests around XML conversion as there weren't any before.

Refs #11818
  • Loading branch information
markstory committed Mar 22, 2018
1 parent c97820e commit 23c8606
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 5 deletions.
9 changes: 5 additions & 4 deletions src/Controller/Component/RequestHandlerComponent.php
Expand Up @@ -232,12 +232,13 @@ public function startup(Event $event)
public function convertXml($xml)
{
try {
$xml = Xml::build($xml, ['readFile' => false]);
if (isset($xml->data)) {
return Xml::toArray($xml->data);
$xml = Xml::build($xml, ['return' => 'domdocument', 'readFile' => false]);
// We might not get child nodes if there are nested inline entities.
if ($xml->childNodes->length > 0) {
return Xml::toArray($xml);
}

return Xml::toArray($xml);
return [];
} catch (XmlException $e) {
return [];
}
Expand Down
2 changes: 1 addition & 1 deletion src/Utility/Xml.php
Expand Up @@ -154,7 +154,7 @@ protected static function _loadXml($input, $options)
$xml = new SimpleXMLElement($input, $flags);
} else {
$xml = new DOMDocument();
$xml->loadXML($input);
$xml->loadXML($input, $flags);
}
} catch (Exception $e) {
$xml = null;
Expand Down
Expand Up @@ -551,6 +551,98 @@ public function testStartupIgnoreFileAsXml()
$this->assertEquals([], $this->Controller->request->data);
}

/**
* Test that input xml is parsed
*
* @return void
*/
public function testStartupConvertXmlDataWrapper()
{
$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<data>
<article id="1" title="first"></article>
</data>
XML;
$this->Controller->request = new ServerRequest(['input' => $xml]);
$this->Controller->request->env('REQUEST_METHOD', 'POST');
$this->Controller->request->env('CONTENT_TYPE', 'application/xml');

$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->startup($event);
$expected = [
'data' => [
'article' => [
'@id' => 1,
'@title' => 'first'
]
]
];
$this->assertEquals($expected, $this->Controller->request->data);
}

/**
* Test that input xml is parsed
*
* @return void
*/
public function testStartupConvertXmlElements()
{
$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<article>
<id>1</id>
<title>first</title>
</article>
XML;
$this->Controller->request = new ServerRequest(['input' => $xml]);
$this->Controller->request->env('REQUEST_METHOD', 'POST');
$this->Controller->request->env('CONTENT_TYPE', 'application/xml');

$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->startup($event);
$expected = [
'article' => [
'id' => 1,
'title' => 'first'
]
];
$this->assertEquals($expected, $this->Controller->request->data);
}

/**
* Test that input xml is parsed
*
* @return void
*/
public function testStartupConvertXmlIgnoreEntities()
{
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE item [
<!ENTITY item "item">
<!ENTITY item1 "&item;&item;&item;&item;&item;&item;">
<!ENTITY item2 "&item1;&item1;&item1;&item1;&item1;&item1;&item1;&item1;&item1;">
<!ENTITY item3 "&item2;&item2;&item2;&item2;&item2;&item2;&item2;&item2;&item2;">
<!ENTITY item4 "&item3;&item3;&item3;&item3;&item3;&item3;&item3;&item3;&item3;">
<!ENTITY item5 "&item4;&item4;&item4;&item4;&item4;&item4;&item4;&item4;&item4;">
<!ENTITY item6 "&item5;&item5;&item5;&item5;&item5;&item5;&item5;&item5;&item5;">
<!ENTITY item7 "&item6;&item6;&item6;&item6;&item6;&item6;&item6;&item6;&item6;">
<!ENTITY item8 "&item7;&item7;&item7;&item7;&item7;&item7;&item7;&item7;&item7;">
]>
<item>
<description>&item8;</description>
</item>
XML;
$this->Controller->request = new ServerRequest(['input' => $xml]);
$this->Controller->request->env('REQUEST_METHOD', 'POST');
$this->Controller->request->env('CONTENT_TYPE', 'application/xml');

$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->startup($event);
$this->assertEquals([], $this->Controller->request->data);
}

/**
* Test mapping a new type and having startup process it.
*
Expand Down

0 comments on commit 23c8606

Please sign in to comment.