Index: contrib/xmlrpc.py
===================================================================
--- contrib/xmlrpc.py	(revision 0)
+++ contrib/xmlrpc.py	(revision 0)
@@ -0,0 +1,77 @@
+from SimpleXMLRPCServer import SimpleXMLRPCDispatcher, resolve_dotted_attribute
+from django.utils.httpwrappers import HttpResponseServerError, HttpResponse
+
+
+class SimpleXMLRPCView(SimpleXMLRPCDispatcher):
+    def __call__(self, request):
+        """ SimpleXMLRPCView is callable so it can be installed as a view.
+
+            Django calls it with 'request', which is a HttpRequest            
+        """
+
+        if request.META['REQUEST_METHOD'] != 'POST':
+            return HttpResponseServerError('Non POST methods not allowed.')
+        
+        try:
+            # get arguments
+            data = request.raw_post_data
+            response = self._marshaled_dispatch(
+                    data, getattr(self, '_dispatch', None)
+                )
+        except:
+            # internal error, report as HTTP server error
+            return HttpResponseServerError('internal error')
+        else:
+            # got a valid XML RPC response
+            return HttpResponse(response, mimetype="text/xml")
+    
+class SafeXMLRPCView(SimpleXMLRPCView):
+    """ class SafeXMLRPCView
+
+        Checks for "public" attribute on callables before calling them.    
+    """
+    def system_listMethods(self):        
+        return SimpleXMLRPCView.system_listMethods(self)
+    system_listMethods.public = True
+    
+    def system_methodSignature(self, method_name):
+        return SimpleXMLRPCView.system_methodSignature(self, method_name)
+    system_methodSignature.public = True
+
+    def system_methodHelp(self, method_name):
+        return SimpleXMLRPCView.system_methodHelp(self, method_name)
+    system_methodHelp.public = True
+    
+    def _dispatch(self, method, params):
+        """Dispatches the XML-RPC method.
+
+            Overwriting to put some extra checks before calling a method. 
+        """
+
+        func = None
+        try:
+            # check to see if a matching function has been registered
+            func = self.funcs[method]
+        except KeyError:
+            if self.instance is not None:
+                # check for a _dispatch method
+                if hasattr(self.instance, '_dispatch'):
+                    return apply(
+                        getattr(self.instance,'_dispatch'),
+                        (method, params)
+                        )
+                else:
+                    # call instance method directly
+                    try:
+                        func = resolve_dotted_attribute(
+                            self.instance,
+                            method
+                            )
+                    except AttributeError:
+                        pass
+
+        if func is not None and hasattr(func, 'public') and func.public:
+            return apply(func, params)
+        else:
+            raise Exception('method "%s" is not supported' % method)
+
