ia64/xen-unstable

changeset 9598:09967f2d6e3b

Further workarounds for the broken string marshalling in xmlrpclib. Regardless
of the encoding used, one still may not include non-printable characters in an
XML document. When a dmesg contains a ^D character, something seen on one of
our test machines, an invalid XML document is generated.

Use a trick by David Mertz to work around this -- escape the string using
Python's repr function.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Apr 06 00:59:06 2006 +0100 (2006-04-06)
parents 395e57314710
children ece9b5710b29
files tools/python/xen/util/xmlrpclib2.py
line diff
     1.1 --- a/tools/python/xen/util/xmlrpclib2.py	Tue Apr 04 11:08:20 2006 +0100
     1.2 +++ b/tools/python/xen/util/xmlrpclib2.py	Thu Apr 06 00:59:06 2006 +0100
     1.3 @@ -20,6 +20,7 @@
     1.4  An enhanced XML-RPC client/server interface for Python.
     1.5  """
     1.6  
     1.7 +import string
     1.8  import types
     1.9  
    1.10  from httplib import HTTPConnection, HTTP
    1.11 @@ -54,6 +55,18 @@ class UnixTransport(Transport):
    1.12      def make_connection(self, host):
    1.13          return HTTPUnix(self.__handler)
    1.14  
    1.15 +
    1.16 +# See _marshalled_dispatch below.
    1.17 +def conv_string(x):
    1.18 +    if (isinstance(x, types.StringType) or
    1.19 +        isinstance(x, unicode)):
    1.20 +        s = string.replace(x, "'", r"\047")
    1.21 +        exec "s = '" + s + "'"
    1.22 +        return s
    1.23 +    else:
    1.24 +        return x
    1.25 +
    1.26 +
    1.27  class ServerProxy(xmlrpclib.ServerProxy):
    1.28      def __init__(self, uri, transport=None, encoding=None, verbose=0,
    1.29                   allow_none=1):
    1.30 @@ -65,6 +78,16 @@ class ServerProxy(xmlrpclib.ServerProxy)
    1.31          xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
    1.32                                         verbose, allow_none)
    1.33  
    1.34 +
    1.35 +    def __request(self, methodname, params):
    1.36 +        response = xmlrpclib.ServerProxy.__request(self, methodname, params)
    1.37 +
    1.38 +        if isinstance(response, tuple):
    1.39 +            return tuple([conv_string(x) for x in response])
    1.40 +        else:
    1.41 +            return conv_string(response)
    1.42 +
    1.43 +
    1.44  # This is a base XML-RPC server for TCP.  It sets allow_reuse_address to
    1.45  # true, and has an improved marshaller that logs and serializes exceptions.
    1.46  
    1.47 @@ -79,14 +102,17 @@ class TCPXMLRPCServer(SocketServer.Threa
    1.48              else:
    1.49                  response = self._dispatch(method, params)
    1.50  
    1.51 -            # Convert strings to unicode strings so that they are escaped
    1.52 -            # properly by xmlrpclib.  We use latin-1 here, but any
    1.53 -            # ASCII-compatible scheme would do -- we just care about getting
    1.54 -            # the bytes across the wire.
    1.55 -            # Any message handler that actually cares about the charset in
    1.56 -            # use should be returning Unicode strings.
    1.57 -            if isinstance(response, types.StringType):
    1.58 -                response = unicode(response, 'iso-8859-1')
    1.59 +            # With either Unicode or normal strings, we can only transmit
    1.60 +            # \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff
    1.61 +            # in an XML document.  xmlrpclib does not escape these values
    1.62 +            # properly, and then breaks when it comes to parse the document.
    1.63 +            # To hack around this problem, we use repr here and exec above
    1.64 +            # to transmit the string using Python encoding.
    1.65 +            # Thanks to David Mertz <mertz@gnosis.cx> for the trick (buried
    1.66 +            # in xml_pickle.py).
    1.67 +            if (isinstance(response, types.StringType) or
    1.68 +                isinstance(response, unicode)):
    1.69 +                response = repr(response)[1:-1]
    1.70  
    1.71              response = (response,)
    1.72              response = xmlrpclib.dumps(response,