# copyright 2003-2010 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 Foobar. If not, see . """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 , 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