From 23c860682b8d826cd8903171e065e9c1e01e7bb0 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 21 Mar 2018 22:51:46 -0400 Subject: [PATCH] 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 --- .../Component/RequestHandlerComponent.php | 9 +- src/Utility/Xml.php | 2 +- .../Component/RequestHandlerComponentTest.php | 92 +++++++++++++++++++ 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/Controller/Component/RequestHandlerComponent.php b/src/Controller/Component/RequestHandlerComponent.php index 16a8566ff19..589bcaf1419 100644 --- a/src/Controller/Component/RequestHandlerComponent.php +++ b/src/Controller/Component/RequestHandlerComponent.php @@ -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 []; } diff --git a/src/Utility/Xml.php b/src/Utility/Xml.php index faf7a7aa879..a20b626dc6d 100644 --- a/src/Utility/Xml.php +++ b/src/Utility/Xml.php @@ -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; diff --git a/tests/TestCase/Controller/Component/RequestHandlerComponentTest.php b/tests/TestCase/Controller/Component/RequestHandlerComponentTest.php index 2bd2c71df2a..98f4ccd53d0 100644 --- a/tests/TestCase/Controller/Component/RequestHandlerComponentTest.php +++ b/tests/TestCase/Controller/Component/RequestHandlerComponentTest.php @@ -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; + $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 = << +
+ 1 + first +
+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 = << + + + + + + + + + +]> + + &item8; + +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. *