1""" 2Security enhancements for xmlrpc. 3""" 4from __future__ import print_function 5 6import sys 7 8try: 9 import xmlrpc.client as xmlrpclib 10except ImportError: 11 import xmlrpclib 12 13try: 14 import requests 15except ImportError: 16 print('python requests is required, please reinstall.', file=sys.stderr) 17 sys.exit(1) 18 19 20class RequestsTransport(xmlrpclib.Transport): 21 """ 22 Drop in Transport for xmlrpclib that uses Requests instead of httplib 23 # https://gist.github.com/chrisguitarguy/2354951 24 # https://github.com/mardiros/pyshop/blob/master/pyshop/helpers/pypi.py 25 """ 26 27 use_https = True 28 29 def __init__(self, use_datetime=0, host=None): 30 xmlrpclib.Transport.__init__(self, use_datetime) 31 if host: 32 self.use_https = 'https' in host 33 34 def request(self, host, handler, request_body, verbose): 35 """ 36 Make an xmlrpc request. 37 """ 38 headers = {'User-Agent': self.user_agent, 39 'Accept': 'text/xml', 40 'Content-Type': 'text/xml'} 41 42 url = self._build_url(host, handler) 43 try: 44 resp = requests.post(url, data=request_body, headers=headers) 45 except ValueError: 46 raise 47 except Exception: 48 raise # something went wrong 49 else: 50 try: 51 resp.raise_for_status() 52 except requests.RequestException as e: 53 raise xmlrpclib.ProtocolError(url, resp.status_code, 54 str(e), resp.headers) 55 else: 56 return self.parse_response(resp) 57 58 def parse_response(self, resp): 59 """ 60 Parse the xmlrpc response. 61 """ 62 p, u = self.getparser() 63 p.feed(resp.content) 64 p.close() 65 return u.close() 66 67 def _build_url(self, host, handler): 68 """ 69 Build a url for our request based on the host, handler and use_https 70 property 71 """ 72 scheme = 'https' if self.use_https else 'http' 73 return '%s://%s%s' % (scheme, host, handler) 74