OLD | NEW |
(Empty) | |
| 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
| 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
| 3 # |
| 4 # This file is part of logilab-common. |
| 5 # |
| 6 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
| 7 # the terms of the GNU Lesser General Public License as published by the Free |
| 8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
| 9 # later version. |
| 10 # |
| 11 # logilab-common is distributed in the hope that it will be useful, but WITHOUT |
| 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
| 14 # details. |
| 15 # |
| 16 # You should have received a copy of the GNU Lesser General Public License along |
| 17 # with logilab-common. If not, see <http://www.gnu.org/licenses/>. |
| 18 """XML-RPC utilities.""" |
| 19 __docformat__ = "restructuredtext en" |
| 20 |
| 21 import xmlrpclib |
| 22 from base64 import encodestring |
| 23 #from cStringIO import StringIO |
| 24 |
| 25 ProtocolError = xmlrpclib.ProtocolError |
| 26 |
| 27 ## class BasicAuthTransport(xmlrpclib.Transport): |
| 28 ## def __init__(self, username=None, password=None): |
| 29 ## self.username = username |
| 30 ## self.password = password |
| 31 ## self.verbose = None |
| 32 ## self.has_ssl = httplib.__dict__.has_key("HTTPConnection") |
| 33 |
| 34 ## def request(self, host, handler, request_body, verbose=None): |
| 35 ## # issue XML-RPC request |
| 36 ## if self.has_ssl: |
| 37 ## if host.startswith("https:"): h = httplib.HTTPSConnection(host) |
| 38 ## else: h = httplib.HTTPConnection(host) |
| 39 ## else: h = httplib.HTTP(host) |
| 40 |
| 41 ## h.putrequest("POST", handler) |
| 42 |
| 43 ## # required by HTTP/1.1 |
| 44 ## if not self.has_ssl: # HTTPConnection already does 1.1 |
| 45 ## h.putheader("Host", host) |
| 46 ## h.putheader("Connection", "close") |
| 47 |
| 48 ## if request_body: h.send(request_body) |
| 49 ## if self.has_ssl: |
| 50 ## response = h.getresponse() |
| 51 ## if response.status != 200: |
| 52 ## raise xmlrpclib.ProtocolError(host + handler, |
| 53 ## response.status, |
| 54 ## response.reason, |
| 55 ## response.msg) |
| 56 ## file = response.fp |
| 57 ## else: |
| 58 ## errcode, errmsg, headers = h.getreply() |
| 59 ## if errcode != 200: |
| 60 ## raise xmlrpclib.ProtocolError(host + handler, errcode, |
| 61 ## errmsg, headers) |
| 62 |
| 63 ## file = h.getfile() |
| 64 |
| 65 ## return self.parse_response(file) |
| 66 |
| 67 |
| 68 |
| 69 class AuthMixin: |
| 70 """basic http authentication mixin for xmlrpc transports""" |
| 71 |
| 72 def __init__(self, username, password, encoding): |
| 73 self.verbose = 0 |
| 74 self.username = username |
| 75 self.password = password |
| 76 self.encoding = encoding |
| 77 |
| 78 def request(self, host, handler, request_body, verbose=0): |
| 79 """issue XML-RPC request""" |
| 80 h = self.make_connection(host) |
| 81 h.putrequest("POST", handler) |
| 82 # required by XML-RPC |
| 83 h.putheader("User-Agent", self.user_agent) |
| 84 h.putheader("Content-Type", "text/xml") |
| 85 h.putheader("Content-Length", str(len(request_body))) |
| 86 h.putheader("Host", host) |
| 87 h.putheader("Connection", "close") |
| 88 # basic auth |
| 89 if self.username is not None and self.password is not None: |
| 90 h.putheader("AUTHORIZATION", "Basic %s" % encodestring( |
| 91 "%s:%s" % (self.username, self.password)).replace("\012", "")) |
| 92 h.endheaders() |
| 93 # send body |
| 94 if request_body: |
| 95 h.send(request_body) |
| 96 # get and check reply |
| 97 errcode, errmsg, headers = h.getreply() |
| 98 if errcode != 200: |
| 99 raise ProtocolError(host + handler, errcode, errmsg, headers) |
| 100 file = h.getfile() |
| 101 ## # FIXME: encoding ??? iirc, this fix a bug in xmlrpclib but... |
| 102 ## data = h.getfile().read() |
| 103 ## if self.encoding != 'UTF-8': |
| 104 ## data = data.replace("version='1.0'", |
| 105 ## "version='1.0' encoding='%s'" % self.encoding
) |
| 106 ## result = StringIO() |
| 107 ## result.write(data) |
| 108 ## result.seek(0) |
| 109 ## return self.parse_response(result) |
| 110 return self.parse_response(file) |
| 111 |
| 112 class BasicAuthTransport(AuthMixin, xmlrpclib.Transport): |
| 113 """basic http authentication transport""" |
| 114 |
| 115 class BasicAuthSafeTransport(AuthMixin, xmlrpclib.SafeTransport): |
| 116 """basic https authentication transport""" |
| 117 |
| 118 |
| 119 def connect(url, user=None, passwd=None, encoding='ISO-8859-1'): |
| 120 """return an xml rpc server on <url>, using user / password if specified |
| 121 """ |
| 122 if user or passwd: |
| 123 assert user and passwd is not None |
| 124 if url.startswith('https://'): |
| 125 transport = BasicAuthSafeTransport(user, passwd, encoding) |
| 126 else: |
| 127 transport = BasicAuthTransport(user, passwd, encoding) |
| 128 else: |
| 129 transport = None |
| 130 server = xmlrpclib.ServerProxy(url, transport, encoding=encoding) |
| 131 return server |
OLD | NEW |