| Index: third_party/logilab/logilab/common/xmlrpcutils.py
|
| diff --git a/third_party/logilab/logilab/common/xmlrpcutils.py b/third_party/logilab/logilab/common/xmlrpcutils.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1d30d829b0b013d4c4edffd0b459c0cd537d4646
|
| --- /dev/null
|
| +++ b/third_party/logilab/logilab/common/xmlrpcutils.py
|
| @@ -0,0 +1,131 @@
|
| +# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
| +# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
| +#
|
| +# This file is part of logilab-common.
|
| +#
|
| +# logilab-common is free software: you can redistribute it and/or modify it under
|
| +# the terms of the GNU Lesser General Public License as published by the Free
|
| +# Software Foundation, either version 2.1 of the License, or (at your option) any
|
| +# later version.
|
| +#
|
| +# logilab-common is distributed in the hope that it will be useful, but WITHOUT
|
| +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
| +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
| +# details.
|
| +#
|
| +# You should have received a copy of the GNU Lesser General Public License along
|
| +# with logilab-common. If not, see <http://www.gnu.org/licenses/>.
|
| +"""XML-RPC utilities."""
|
| +__docformat__ = "restructuredtext en"
|
| +
|
| +import xmlrpclib
|
| +from base64 import encodestring
|
| +#from cStringIO import StringIO
|
| +
|
| +ProtocolError = xmlrpclib.ProtocolError
|
| +
|
| +## class BasicAuthTransport(xmlrpclib.Transport):
|
| +## def __init__(self, username=None, password=None):
|
| +## self.username = username
|
| +## self.password = password
|
| +## self.verbose = None
|
| +## self.has_ssl = httplib.__dict__.has_key("HTTPConnection")
|
| +
|
| +## def request(self, host, handler, request_body, verbose=None):
|
| +## # issue XML-RPC request
|
| +## if self.has_ssl:
|
| +## if host.startswith("https:"): h = httplib.HTTPSConnection(host)
|
| +## else: h = httplib.HTTPConnection(host)
|
| +## else: h = httplib.HTTP(host)
|
| +
|
| +## h.putrequest("POST", handler)
|
| +
|
| +## # required by HTTP/1.1
|
| +## if not self.has_ssl: # HTTPConnection already does 1.1
|
| +## h.putheader("Host", host)
|
| +## h.putheader("Connection", "close")
|
| +
|
| +## if request_body: h.send(request_body)
|
| +## if self.has_ssl:
|
| +## response = h.getresponse()
|
| +## if response.status != 200:
|
| +## raise xmlrpclib.ProtocolError(host + handler,
|
| +## response.status,
|
| +## response.reason,
|
| +## response.msg)
|
| +## file = response.fp
|
| +## else:
|
| +## errcode, errmsg, headers = h.getreply()
|
| +## if errcode != 200:
|
| +## raise xmlrpclib.ProtocolError(host + handler, errcode,
|
| +## errmsg, headers)
|
| +
|
| +## file = h.getfile()
|
| +
|
| +## return self.parse_response(file)
|
| +
|
| +
|
| +
|
| +class AuthMixin:
|
| + """basic http authentication mixin for xmlrpc transports"""
|
| +
|
| + def __init__(self, username, password, encoding):
|
| + self.verbose = 0
|
| + self.username = username
|
| + self.password = password
|
| + self.encoding = encoding
|
| +
|
| + def request(self, host, handler, request_body, verbose=0):
|
| + """issue XML-RPC request"""
|
| + h = self.make_connection(host)
|
| + h.putrequest("POST", handler)
|
| + # required by XML-RPC
|
| + h.putheader("User-Agent", self.user_agent)
|
| + h.putheader("Content-Type", "text/xml")
|
| + h.putheader("Content-Length", str(len(request_body)))
|
| + h.putheader("Host", host)
|
| + h.putheader("Connection", "close")
|
| + # basic auth
|
| + if self.username is not None and self.password is not None:
|
| + h.putheader("AUTHORIZATION", "Basic %s" % encodestring(
|
| + "%s:%s" % (self.username, self.password)).replace("\012", ""))
|
| + h.endheaders()
|
| + # send body
|
| + if request_body:
|
| + h.send(request_body)
|
| + # get and check reply
|
| + errcode, errmsg, headers = h.getreply()
|
| + if errcode != 200:
|
| + raise ProtocolError(host + handler, errcode, errmsg, headers)
|
| + file = h.getfile()
|
| +## # FIXME: encoding ??? iirc, this fix a bug in xmlrpclib but...
|
| +## data = h.getfile().read()
|
| +## if self.encoding != 'UTF-8':
|
| +## data = data.replace("version='1.0'",
|
| +## "version='1.0' encoding='%s'" % self.encoding)
|
| +## result = StringIO()
|
| +## result.write(data)
|
| +## result.seek(0)
|
| +## return self.parse_response(result)
|
| + return self.parse_response(file)
|
| +
|
| +class BasicAuthTransport(AuthMixin, xmlrpclib.Transport):
|
| + """basic http authentication transport"""
|
| +
|
| +class BasicAuthSafeTransport(AuthMixin, xmlrpclib.SafeTransport):
|
| + """basic https authentication transport"""
|
| +
|
| +
|
| +def connect(url, user=None, passwd=None, encoding='ISO-8859-1'):
|
| + """return an xml rpc server on <url>, using user / password if specified
|
| + """
|
| + if user or passwd:
|
| + assert user and passwd is not None
|
| + if url.startswith('https://'):
|
| + transport = BasicAuthSafeTransport(user, passwd, encoding)
|
| + else:
|
| + transport = BasicAuthTransport(user, passwd, encoding)
|
| + else:
|
| + transport = None
|
| + server = xmlrpclib.ServerProxy(url, transport, encoding=encoding)
|
| + return server
|
|
|