Browse Source

Fix parsing XML-RPC values with no type specified. Closes #507

Mike Naberezny 10 years ago
parent
commit
2947fad318
3 changed files with 48 additions and 19 deletions
  1. 6 0
      CHANGES.txt
  2. 35 18
      supervisor/tests/test_xmlrpc.py
  3. 7 1
      supervisor/xmlrpc.py

+ 6 - 0
CHANGES.txt

@@ -36,6 +36,12 @@
 - Added ``signal`` command to supervisorctl.  Thanks to Moriyoshi Koizumi and
 - Added ``signal`` command to supervisorctl.  Thanks to Moriyoshi Koizumi and
   Marc Abramowitz for the patches.
   Marc Abramowitz for the patches.
 
 
+- Fixed an XML-RPC bug where the ElementTree-based parser handled strings
+  like ``<value><string>hello</string></value>`` but not strings like
+  ``<value>hello</value>``, which are valid in the XML-RPC spec.  This
+  fixes compatibility with the Apache XML-RPC client for Java and
+  possibly other clients.
+
 3.1.2 (2014-09-07)
 3.1.2 (2014-09-07)
 ------------------
 ------------------
 
 

+ 35 - 18
supervisor/tests/test_xmlrpc.py

@@ -199,42 +199,57 @@ class XMLRPCHandlerTests(unittest.TestCase):
         <value><i4>41</i4></value>
         <value><i4>41</i4></value>
         </param>
         </param>
         <param>
         <param>
-        <value><int>14</int></value>
+        <value><string>foo</string></value>
         </param>
         </param>
         <param>
         <param>
-        <value><boolean>1</boolean></value>
+        <value><string></string></value>
+        </param>
+        <param>
+        <!-- xml-rpc spec allows strings without <string> tag -->
+        <value>bar</value>
         </param>
         </param>
         <param>
         <param>
-        <value><string>hello world</string></value>
+        <value></value>
+        </param>
+        <param>
+        <value><boolean>1</boolean></value>
         </param>
         </param>
         <param>
         <param>
         <value><double>-12.214</double></value>
         <value><double>-12.214</double></value>
         </param>
         </param>
         <param>
         <param>
-        <value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>
+        <value>
+        <dateTime.iso8601>19980717T14:08:55</dateTime.iso8601>
+        </value>
         </param>
         </param>
         <param>
         <param>
         <value><base64>eW91IGNhbid0IHJlYWQgdGhpcyE=</base64></value>
         <value><base64>eW91IGNhbid0IHJlYWQgdGhpcyE=</base64></value>
         </param>
         </param>
         <param>
         <param>
         <struct>
         <struct>
-          <member><name>k</name><value><i4>5</i4></value></member>
+        <member><name>j</name><value><i4>5</i4></value></member>
+        <member><name>k</name><value>abc</value></member>
         </struct>
         </struct>
         </param>
         </param>
         <param>
         <param>
         <array>
         <array>
           <data>
           <data>
             <value><i4>12</i4></value>
             <value><i4>12</i4></value>
+            <value><string>abc</string></value>
+            <value>def</value>
             <value><i4>34</i4></value>
             <value><i4>34</i4></value>
           </data>
           </data>
         </array>
         </array>
         </param>
         </param>
         <param>
         <param>
         <struct>
         <struct>
-        <member>
-          <name>k</name>
-          <value><array><data><value><i4>1</i4></value></data></array></value>
-        </member>
+          <member>
+            <name>k</name>
+            <value><array><data>
+              <value><i4>1</i4></value>
+              <struct></struct>
+            </data></array></value>
+          </member>
         </struct>
         </struct>
         </param>
         </param>
         </params>
         </params>
@@ -248,15 +263,17 @@ class XMLRPCHandlerTests(unittest.TestCase):
         import datetime
         import datetime
         self.assertEqual(method, 'examples.getStateName')
         self.assertEqual(method, 'examples.getStateName')
         self.assertEqual(params[0], 41)
         self.assertEqual(params[0], 41)
-        self.assertEqual(params[1], 14)
-        self.assertEqual(params[2], True)
-        self.assertEqual(params[3], 'hello world')
-        self.assertEqual(params[4], -12.214)
-        self.assertEqual(params[5], datetime.datetime(1998, 7, 17, 14, 8, 55))
-        self.assertEqual(params[6], "you can't read this!")
-        self.assertEqual(params[7], {'k': 5})
-        self.assertEqual(params[8], [12, 34])
-        self.assertEqual(params[9], {'k': [1]})
+        self.assertEqual(params[1], 'foo')
+        self.assertEqual(params[2], '')
+        self.assertEqual(params[3], 'bar')
+        self.assertEqual(params[4], '')
+        self.assertEqual(params[5], True)
+        self.assertEqual(params[6], -12.214)
+        self.assertEqual(params[7], datetime.datetime(1998, 7, 17, 14, 8, 55))
+        self.assertEqual(params[8], "you can't read this!")
+        self.assertEqual(params[9], {'j': 5, 'k': 'abc'})
+        self.assertEqual(params[10], [12, 'abc', 'def', 34])
+        self.assertEqual(params[11], {'k': [1, {}]})
 
 
 class TraverseTests(unittest.TestCase):
 class TraverseTests(unittest.TestCase):
     def test_underscore(self):
     def test_underscore(self):

+ 7 - 1
supervisor/xmlrpc.py

@@ -311,7 +311,6 @@ class supervisor_xmlrpc_handler(xmlrpc_handler):
         "data": lambda x: [v.text for v in x],
         "data": lambda x: [v.text for v in x],
         "struct": lambda x: dict([(k.text or "", v.text) for k, v in x]),
         "struct": lambda x: dict([(k.text or "", v.text) for k, v in x]),
         "base64": lambda x: as_string(decodestring(as_bytes(x.text or ""))),
         "base64": lambda x: as_string(decodestring(as_bytes(x.text or ""))),
-        "value": lambda x: x[0].text,
         "param": lambda x: x[0].text,
         "param": lambda x: x[0].text,
         }
         }
 
 
@@ -327,6 +326,13 @@ class supervisor_xmlrpc_handler(xmlrpc_handler):
                 data = unmarshall(elem)
                 data = unmarshall(elem)
                 elem.clear()
                 elem.clear()
                 elem.text = data
                 elem.text = data
+            elif elem.tag == "value":
+                try:
+                    data = elem[0].text
+                except IndexError:
+                    data = elem.text or ""
+                elem.clear()
+                elem.text = data
             elif elem.tag == "methodName":
             elif elem.tag == "methodName":
                 method = elem.text
                 method = elem.text
             elif elem.tag == "params":
             elif elem.tag == "params":