From 7d028b77a4bde48ed2729f370773c9d510156686 Mon Sep 17 00:00:00 2001 From: Ryan McNair Date: Mon, 27 Jan 2014 21:48:51 +0000 Subject: [PATCH] Add support for special char in volume metadata Using special characters such as "&" in volume metadata caused SAX parser to split text into multiple child nodes, as stated in the specs for SAX parsers. In this case extract_text would return 'None' because text was return if there was exactly one child node. Concatenating the values of child nodes accounts for SAX parsers splitting contigous characters into multiple chunks. Change-Id: I3709789d33ff7b07eaeaf725f5183105443d0abc Closes-Bug: #1268513 --- cinder/api/openstack/wsgi.py | 10 ++++++---- cinder/tests/api/openstack/test_wsgi.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cinder/api/openstack/wsgi.py b/cinder/api/openstack/wsgi.py index e561b7cab..b1138cdb6 100644 --- a/cinder/api/openstack/wsgi.py +++ b/cinder/api/openstack/wsgi.py @@ -290,11 +290,13 @@ class XMLDeserializer(TextDeserializer): def extract_text(self, node): """Get the text field contained by the given node.""" - if len(node.childNodes) == 1: - child = node.childNodes[0] + text = [] + # Cannot assume entire text will be in a single child node because SAX + # parsers may split contiguous character data into multiple chunks + for child in node.childNodes: if child.nodeType == child.TEXT_NODE: - return child.nodeValue - return "" + text.append(child.nodeValue) + return ''.join(text) def find_attribute_or_element(self, parent, name): """Get an attribute value; fallback to an element if not found.""" diff --git a/cinder/tests/api/openstack/test_wsgi.py b/cinder/tests/api/openstack/test_wsgi.py index 4f8c9144f..fe7a4404e 100644 --- a/cinder/tests/api/openstack/test_wsgi.py +++ b/cinder/tests/api/openstack/test_wsgi.py @@ -245,6 +245,29 @@ class XMLDeserializerTest(test.TestCase): self.assertEqual(deserializer.deserialize(xml), as_dict) +class MetadataXMLDeserializerTest(test.TestCase): + def test_xml_meta_parsing_special_character(self): + """Test that when a SaxParser splits a string containing special + characters into multiple childNodes there are no issues extracting + the text. + """ + meta_xml_str = """ + + value&3 + value2 + value1 + + """.strip() + meta_expected = {'key1': 'value1', + 'key2': 'value2', + 'key3': 'value&3'} + meta_deserializer = wsgi.MetadataXMLDeserializer() + document = wsgi.utils.safe_minidom_parse_string(meta_xml_str) + root_node = document.childNodes[0] + meta_extracted = meta_deserializer.extract_metadata(root_node) + self.assertEqual(meta_expected, meta_extracted) + + class ResourceTest(test.TestCase): def test_resource_call(self): class Controller(object): -- 2.45.2