xmlrpcutils.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 under
  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) any
  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. import xmlrpclib
  21. from base64 import encodestring
  22. #from cStringIO import StringIO
  23. ProtocolError = xmlrpclib.ProtocolError
  24. ## class BasicAuthTransport(xmlrpclib.Transport):
  25. ## def __init__(self, username=None, password=None):
  26. ## self.username = username
  27. ## self.password = password
  28. ## self.verbose = None
  29. ## self.has_ssl = httplib.__dict__.has_key("HTTPConnection")
  30. ## def request(self, host, handler, request_body, verbose=None):
  31. ## # issue XML-RPC request
  32. ## if self.has_ssl:
  33. ## if host.startswith("https:"): h = httplib.HTTPSConnection(host)
  34. ## else: h = httplib.HTTPConnection(host)
  35. ## else: h = httplib.HTTP(host)
  36. ## h.putrequest("POST", handler)
  37. ## # required by HTTP/1.1
  38. ## if not self.has_ssl: # HTTPConnection already does 1.1
  39. ## h.putheader("Host", host)
  40. ## h.putheader("Connection", "close")
  41. ## if request_body: h.send(request_body)
  42. ## if self.has_ssl:
  43. ## response = h.getresponse()
  44. ## if response.status != 200:
  45. ## raise xmlrpclib.ProtocolError(host + handler,
  46. ## response.status,
  47. ## response.reason,
  48. ## response.msg)
  49. ## file = response.fp
  50. ## else:
  51. ## errcode, errmsg, headers = h.getreply()
  52. ## if errcode != 200:
  53. ## raise xmlrpclib.ProtocolError(host + handler, errcode,
  54. ## errmsg, headers)
  55. ## file = h.getfile()
  56. ## return self.parse_response(file)
  57. class AuthMixin:
  58. """basic http authentication mixin for xmlrpc transports"""
  59. def __init__(self, username, password, encoding):
  60. self.verbose = 0
  61. self.username = username
  62. self.password = password
  63. self.encoding = encoding
  64. def request(self, host, handler, request_body, verbose=0):
  65. """issue XML-RPC request"""
  66. h = self.make_connection(host)
  67. h.putrequest("POST", handler)
  68. # required by XML-RPC
  69. h.putheader("User-Agent", self.user_agent)
  70. h.putheader("Content-Type", "text/xml")
  71. h.putheader("Content-Length", str(len(request_body)))
  72. h.putheader("Host", host)
  73. h.putheader("Connection", "close")
  74. # basic auth
  75. if self.username is not None and self.password is not None:
  76. h.putheader("AUTHORIZATION", "Basic %s" % encodestring(
  77. "%s:%s" % (self.username, self.password)).replace("\012", ""))
  78. h.endheaders()
  79. # send body
  80. if request_body:
  81. h.send(request_body)
  82. # get and check reply
  83. errcode, errmsg, headers = h.getreply()
  84. if errcode != 200:
  85. raise ProtocolError(host + handler, errcode, errmsg, headers)
  86. file = h.getfile()
  87. ## # FIXME: encoding ??? iirc, this fix a bug in xmlrpclib but...
  88. ## data = h.getfile().read()
  89. ## if self.encoding != 'UTF-8':
  90. ## data = data.replace("version='1.0'",
  91. ## "version='1.0' encoding='%s'" % self.encoding)
  92. ## result = StringIO()
  93. ## result.write(data)
  94. ## result.seek(0)
  95. ## return self.parse_response(result)
  96. return self.parse_response(file)
  97. class BasicAuthTransport(AuthMixin, xmlrpclib.Transport):
  98. """basic http authentication transport"""
  99. class BasicAuthSafeTransport(AuthMixin, xmlrpclib.SafeTransport):
  100. """basic https authentication transport"""
  101. def connect(url, user=None, passwd=None, encoding='ISO-8859-1'):
  102. """return an xml rpc server on <url>, using user / password if specified
  103. """
  104. if user or passwd:
  105. assert user and passwd is not None
  106. if url.startswith('https://'):
  107. transport = BasicAuthSafeTransport(user, passwd, encoding)
  108. else:
  109. transport = BasicAuthTransport(user, passwd, encoding)
  110. else:
  111. transport = None
  112. server = xmlrpclib.ServerProxy(url, transport, encoding=encoding)
  113. return server