src/ztfy/utils/protocol/xmlrpc.py
branchZTK-1.1
changeset 148 d3668ecd9137
parent 29 035058514c2d
child 160 5fdc01c95cad
equal deleted inserted replaced
147:044dc196ec8a 148:d3668ecd9137
       
     1 ### -*- coding: utf-8 -*- ####################################################
       
     2 ##############################################################################
       
     3 #
       
     4 # Copyright (c) 2008 Thierry Florac <tflorac AT ulthar.net>
       
     5 # All Rights Reserved.
       
     6 #
       
     7 # This software is subject to the provisions of the Zope Public License,
       
     8 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     9 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
    10 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    11 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    12 # FOR A PARTICULAR PURPOSE.
       
    13 #
       
    14 ##############################################################################
       
    15 
       
    16 
       
    17 # import standard packages
       
    18 import base64
       
    19 import cookielib
       
    20 import urllib2
       
    21 import xmlrpclib
       
    22 
       
    23 # import Zope3 interfaces
       
    24 
       
    25 # import local interfaces
       
    26 
       
    27 # import Zope3 packages
       
    28 
       
    29 # import local packages
       
    30 
       
    31 
       
    32 class XMLRPCCookieAuthTransport(xmlrpclib.Transport):
       
    33     """An XML-RPC transport handling authentication via cookies"""
       
    34 
       
    35     def __init__(self, user_agent, credentials=(), cookies=None):
       
    36         xmlrpclib.Transport.__init__(self)
       
    37         self.user_agent = user_agent
       
    38         self.credentials = credentials
       
    39         self.cookies = cookies
       
    40 
       
    41     # override the send_host hook to also send authentication info
       
    42     def send_host(self, connection, host):
       
    43         xmlrpclib.Transport.send_host(self, connection, host)
       
    44         if (self.cookies is not None) and (len(self.cookies) > 0):
       
    45             for cookie in self.cookies:
       
    46                 connection.putheader('Cookie', '%s=%s' % (cookie.name, cookie.value))
       
    47         elif self.credentials:
       
    48             auth = 'Basic %s' % base64.encodestring("%s:%s" % self.credentials).strip()
       
    49             connection.putheader('Authorization', auth)
       
    50 
       
    51     def request(self, host, handler, request_body, verbose=False):
       
    52 
       
    53         # dummy request class for extracting cookies
       
    54         class CookieRequest(urllib2.Request):
       
    55             pass
       
    56 
       
    57         # dummy response class for extracting cookies
       
    58         class CookieResponse:
       
    59             def __init__(self, headers):
       
    60                 self.headers = headers
       
    61             def info(self):
       
    62                 return self.headers
       
    63 
       
    64         # issue XML-RPC request
       
    65         connection = self.make_connection(host)
       
    66         self.verbose = verbose
       
    67         if verbose:
       
    68             connection.set_debuglevel(1)
       
    69         self.send_request(connection, handler, request_body)
       
    70         self.send_host(connection, host)
       
    71         self.send_user_agent(connection)
       
    72         # get response
       
    73         self.send_content(connection, request_body)
       
    74         errcode, errmsg, headers = connection.getreply()
       
    75         # extract cookies from response headers
       
    76         crequest = CookieRequest('http://%s/' % host)
       
    77         cresponse = CookieResponse(headers)
       
    78         if self.cookies is not None:
       
    79             self.cookies.extract_cookies(cresponse, crequest)
       
    80         if errcode != 200:
       
    81             raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
       
    82         try:
       
    83             sock = connection._conn.sock
       
    84         except AttributeError:
       
    85             sock = None
       
    86         return self._parse_response(connection.getfile(), sock)
       
    87 
       
    88 
       
    89 def getClient(uri, credentials=(), verbose=False):
       
    90     """Get an XML-RPC client which supports basic authentication"""
       
    91     transport = XMLRPCCookieAuthTransport('Python XML-RPC Client/0.1 (ZTFY basic implementation)', credentials)
       
    92     return xmlrpclib.Server(uri, transport=transport, verbose=verbose)
       
    93 
       
    94 
       
    95 def getClientWithCookies(uri, credentials=(), verbose=False):
       
    96     """Get an XML-RPC client which supports authentication throught cookies"""
       
    97     transport = XMLRPCCookieAuthTransport('Python XML-RPC Client/0.1 (ZTFY cookie implementation)', credentials, cookielib.CookieJar())
       
    98     return xmlrpclib.Server(uri, transport=transport, verbose=verbose)