Django

Code

Ticket #547: xmlrpc.2.patch

File xmlrpc.2.patch, 6.0 kB (added by upadhyay@gmail.com, 3 years ago)

Oops, attached older patch, use this one.

  • contrib/xmlrpc.py

    old new  
     1import xmlrpclib 
     2from django.utils.httpwrappers import HttpResponseServerError, HttpResponse 
     3 
     4class SimpleXMLRPCView: 
     5    """ Simple XMLRPC View. 
     6 
     7        Simple XML-RPC server that allows functions and a single instance 
     8        to be installed to handle requests. 
     9    """ 
     10    def __init__(self, logRequests=1): 
     11        self.funcs = {} 
     12        self.logRequests = logRequests 
     13        self.instance = None     
     14 
     15    def register_instance(self, instance): 
     16        """Registers an instance to respond to XML-RPC requests. 
     17 
     18            Only one instance can be installed at a time. 
     19 
     20            If the registered instance has a _dispatch method then that 
     21            method will be called with the name of the XML-RPC method and 
     22            it's parameters as a tuple 
     23            e.g. instance._dispatch('add',(2,3)) 
     24 
     25            If the registered instance does not have a _dispatch method 
     26            then the instance will be searched to find a matching method 
     27            and, if found, will be called. 
     28 
     29            Methods beginning with an '_' are considered private and will 
     30            not be called by SimpleXMLRPCView. 
     31 
     32            If a registered function matches a XML-RPC request, then it 
     33            will be called instead of the registered instance. 
     34        """ 
     35 
     36        self.instance = instance 
     37 
     38    def register_function(self, function, name = None): 
     39        """Registers a function to respond to XML-RPC requests. 
     40 
     41            The optional name argument can be used to set a Unicode name 
     42            for the function. 
     43 
     44            If an instance is also registered then it will only be called 
     45            if a matching function is not found. 
     46        """ 
     47 
     48        if name is None: 
     49            name = function.__name__ 
     50        self.funcs[name] = function 
     51 
     52    def _dispatch(self, method, params): 
     53        """Dispatches the XML-RPC method. 
     54 
     55            XML-RPC calls are forwarded to a registered function that 
     56            matches the called XML-RPC method name. If no such function 
     57            exists then the call is forwarded to the registered instance, 
     58            if available. 
     59 
     60            If the registered instance has a _dispatch method then that 
     61            method will be called with the name of the XML-RPC method and 
     62            it's parameters as a tuple 
     63            e.g. instance._dispatch('add',(2,3)) 
     64 
     65            If the registered instance does not have a _dispatch method 
     66            then the instance will be searched to find a matching method 
     67            and, if found, will be called. 
     68 
     69            Methods beginning with an '_' are considered private and will 
     70            not be called by SimpleXMLRPCView. 
     71        """ 
     72 
     73        def resolve_dotted_attribute(obj, attr): 
     74            """resolve_dotted_attribute(math, 'cos.__doc__') => math.cos.__doc__ 
     75 
     76                Resolves a dotted attribute name to an object. Raises 
     77                an AttributeError if any attribute in the chain starts 
     78                with a '_'. 
     79            """ 
     80            for i in attr.split('.'): 
     81                if i.startswith('_'): 
     82                    raise AttributeError( 
     83                        'attempt to access private attribute "%s"' % i 
     84                        ) 
     85                else: 
     86                    obj = getattr(obj,i) 
     87            return obj 
     88 
     89        func = None 
     90        try: 
     91            # check to see if a matching function has been registered 
     92            func = self.funcs[method] 
     93        except KeyError: 
     94            if self.instance is not None: 
     95                # check for a _dispatch method 
     96                if hasattr(self.instance, '_dispatch'): 
     97                    return apply( 
     98                        getattr(self.instance,'_dispatch'), 
     99                        (method, params) 
     100                        ) 
     101                else: 
     102                    # call instance method directly 
     103                    try: 
     104                        func = resolve_dotted_attribute( 
     105                            self.instance, 
     106                            method 
     107                            ) 
     108                    except AttributeError: 
     109                        pass 
     110 
     111        if func is not None and hasattr(func, 'public') and func.public: 
     112            return apply(func, params) 
     113        else: 
     114            raise Exception('method "%s" is not supported' % method) 
     115 
     116    def __call__(self, request): 
     117        """ SimpleXMLRPCView is callable so it can be installed as a view. 
     118 
     119            Django calls it with 'request', which is a HttpRequest             
     120        """ 
     121 
     122        if request.META['REQUEST_METHOD'] != 'POST': 
     123            return HttpResponseServerError('Non POST methods not allowed.') 
     124         
     125        try: 
     126            # get arguments 
     127            data = request.raw_post_data 
     128            params, method = xmlrpclib.loads(data) 
     129 
     130            # generate response 
     131            try: 
     132                response = self._dispatch(method, params) 
     133                # wrap response in a singleton tuple 
     134                response = (response,) 
     135            except: 
     136                # report exception back to server 
     137                response = xmlrpclib.dumps( 
     138                    xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)) 
     139                    ) 
     140            else: 
     141                response = xmlrpclib.dumps(response, methodresponse=1) 
     142        except: 
     143            # internal error, report as HTTP server error 
     144            return HttpResponseServerError('internal error') 
     145        else: 
     146            # got a valid XML RPC response 
     147            return HttpResponse(response, mimetype="text/xml") 
     148