| | 1 | from SimpleXMLRPCServer import SimpleXMLRPCDispatcher, resolve_dotted_attribute |
|---|
| | 2 | from django.utils.httpwrappers import HttpResponseServerError, HttpResponse |
|---|
| | 3 | |
|---|
| | 4 | |
|---|
| | 5 | class SimpleXMLRPCView(SimpleXMLRPCDispatcher): |
|---|
| | 6 | def __call__(self, request): |
|---|
| | 7 | """ SimpleXMLRPCView is callable so it can be installed as a view. |
|---|
| | 8 | |
|---|
| | 9 | Django calls it with 'request', which is a HttpRequest |
|---|
| | 10 | """ |
|---|
| | 11 | |
|---|
| | 12 | if request.META['REQUEST_METHOD'] != 'POST': |
|---|
| | 13 | return HttpResponseServerError('Non POST methods not allowed.') |
|---|
| | 14 | |
|---|
| | 15 | try: |
|---|
| | 16 | # get arguments |
|---|
| | 17 | data = request.raw_post_data |
|---|
| | 18 | response = self._marshaled_dispatch( |
|---|
| | 19 | data, getattr(self, '_dispatch', None) |
|---|
| | 20 | ) |
|---|
| | 21 | except: |
|---|
| | 22 | # internal error, report as HTTP server error |
|---|
| | 23 | return HttpResponseServerError('internal error') |
|---|
| | 24 | else: |
|---|
| | 25 | # got a valid XML RPC response |
|---|
| | 26 | return HttpResponse(response, mimetype="text/xml") |
|---|
| | 27 | |
|---|
| | 28 | class SafeXMLRPCView(SimpleXMLRPCView): |
|---|
| | 29 | """ class SafeXMLRPCView |
|---|
| | 30 | |
|---|
| | 31 | Checks for "public" attribute on callables before calling them. |
|---|
| | 32 | """ |
|---|
| | 33 | def system_listMethods(self): |
|---|
| | 34 | return SimpleXMLRPCView.system_listMethods(self) |
|---|
| | 35 | system_listMethods.public = True |
|---|
| | 36 | |
|---|
| | 37 | def system_methodSignature(self, method_name): |
|---|
| | 38 | return SimpleXMLRPCView.system_methodSignature(self, method_name) |
|---|
| | 39 | system_methodSignature.public = True |
|---|
| | 40 | |
|---|
| | 41 | def system_methodHelp(self, method_name): |
|---|
| | 42 | return SimpleXMLRPCView.system_methodHelp(self, method_name) |
|---|
| | 43 | system_methodHelp.public = True |
|---|
| | 44 | |
|---|
| | 45 | def _dispatch(self, method, params): |
|---|
| | 46 | """Dispatches the XML-RPC method. |
|---|
| | 47 | |
|---|
| | 48 | Overwriting to put some extra checks before calling a method. |
|---|
| | 49 | """ |
|---|
| | 50 | |
|---|
| | 51 | func = None |
|---|
| | 52 | try: |
|---|
| | 53 | # check to see if a matching function has been registered |
|---|
| | 54 | func = self.funcs[method] |
|---|
| | 55 | except KeyError: |
|---|
| | 56 | if self.instance is not None: |
|---|
| | 57 | # check for a _dispatch method |
|---|
| | 58 | if hasattr(self.instance, '_dispatch'): |
|---|
| | 59 | return apply( |
|---|
| | 60 | getattr(self.instance,'_dispatch'), |
|---|
| | 61 | (method, params) |
|---|
| | 62 | ) |
|---|
| | 63 | else: |
|---|
| | 64 | # call instance method directly |
|---|
| | 65 | try: |
|---|
| | 66 | func = resolve_dotted_attribute( |
|---|
| | 67 | self.instance, |
|---|
| | 68 | method |
|---|
| | 69 | ) |
|---|
| | 70 | except AttributeError: |
|---|
| | 71 | pass |
|---|
| | 72 | |
|---|
| | 73 | if func is not None and hasattr(func, 'public') and func.public: |
|---|
| | 74 | return apply(func, params) |
|---|
| | 75 | else: |
|---|
| | 76 | raise Exception('method "%s" is not supported' % method) |
|---|
| | 77 | |