Skip to content
Permalink
Browse files

Fix nested entity expansion.

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 23c860682b8d826cd8903171e065e9c1e01e7bb0
@@ -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 [];
}
@@ -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;
@@ -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.
*

0 comments on commit 23c8606

Please sign in to comment.
You can’t perform that action at this time.