X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=apps%2Fpatchwork%2Fviews%2Fxmlrpc.py;h=eebc2aae48600179471782fe8ee55e52a845d83a;hb=67181f5c929018d5304732969f0811795c13ea37;hp=f7a8dac8381ca1c74dd01da09709ae3ca8367898;hpb=f0d09c7ad846a02c4d5d99bfe412b0ba35164150;p=patchwork diff --git a/apps/patchwork/views/xmlrpc.py b/apps/patchwork/views/xmlrpc.py index f7a8dac..eebc2aa 100644 --- a/apps/patchwork/views/xmlrpc.py +++ b/apps/patchwork/views/xmlrpc.py @@ -20,15 +20,14 @@ # Patchwork XMLRPC interface # -from django.core.exceptions import ImproperlyConfigured from SimpleXMLRPCServer import SimpleXMLRPCDispatcher from django.http import HttpResponse, HttpResponseRedirect, \ HttpResponseServerError -from django.conf import settings from django.core import urlresolvers -from django.shortcuts import render_to_response from django.contrib.auth import authenticate -from patchwork.models import Patch, Project, Person, Bundle, State +from patchwork.models import Patch, Project, Person, State +from patchwork.views import patch_to_mbox +from django.views.decorators.csrf import csrf_exempt import sys import base64 @@ -39,26 +38,33 @@ class PatchworkXMLRPCDispatcher(SimpleXMLRPCDispatcher): if sys.version_info[:3] >= (2,5,): SimpleXMLRPCDispatcher.__init__(self, allow_none=False, encoding=None) + def _dumps(obj, *args, **kwargs): + kwargs['allow_none'] = self.allow_none + kwargs['encoding'] = self.encoding + return xmlrpclib.dumps(obj, *args, **kwargs) else: + def _dumps(obj, *args, **kwargs): + return xmlrpclib.dumps(obj, *args, **kwargs) SimpleXMLRPCDispatcher.__init__(self) + self.dumps = _dumps + # map of name => (auth, func) self.func_map = {} - def register_function(self, fn, auth_required): self.func_map[fn.__name__] = (auth_required, fn) def _user_for_request(self, request): - auth_header = None + auth_header = None - if request.META.has_key('HTTP_AUTHORIZATION'): - auth_header = request.META.get('HTTP_AUTHORIZATION') - elif request.META.has_key('Authorization'): - auth_header = request.META.get('Authorization') + if 'HTTP_AUTHORIZATION' in request.META: + auth_header = request.META.get('HTTP_AUTHORIZATION') + elif 'Authorization' in request.META: + auth_header = request.META.get('Authorization') - if auth_header is None or auth_header == '': + if auth_header is None or auth_header == '': raise Exception("No authentication credentials given") str = auth_header.strip() @@ -99,16 +105,13 @@ class PatchworkXMLRPCDispatcher(SimpleXMLRPCDispatcher): response = self._dispatch(request, method, params) # wrap response in a singleton tuple response = (response,) - response = xmlrpclib.dumps(response, methodresponse=1, - allow_none=self.allow_none, encoding=self.encoding) + response = self.dumps(response, methodresponse=1) except xmlrpclib.Fault, fault: - response = xmlrpclib.dumps(fault, allow_none=self.allow_none, - encoding=self.encoding) + response = self.dumps(fault) except: # report exception back to server - response = xmlrpclib.dumps( + response = self.dumps( xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), - encoding=self.encoding, allow_none=self.allow_none, ) return response @@ -116,6 +119,7 @@ class PatchworkXMLRPCDispatcher(SimpleXMLRPCDispatcher): dispatcher = PatchworkXMLRPCDispatcher() # XMLRPC view function +@csrf_exempt def xmlrpc(request): if request.method != 'POST': return HttpResponseRedirect( @@ -126,7 +130,7 @@ def xmlrpc(request): try: ret = dispatcher._marshaled_dispatch(request) response.write(ret) - except Exception, e: + except Exception: return HttpResponseServerError() return response @@ -164,12 +168,20 @@ def project_to_dict(obj): def person_to_dict(obj): """Return a trimmed down dictionary representation of a Person object which is OK to send to the client.""" + + # Make sure we don't return None even if the user submitted a patch + # with no real name. XMLRPC can't marshall None. + if obj.name is not None: + name = obj.name + else: + name = obj.email + return \ { 'id' : obj.id, 'email' : obj.email, - 'name' : obj.name, - 'user' : str(obj.user), + 'name' : name, + 'user' : unicode(obj.user).encode("utf-8"), } def patch_to_dict(obj): @@ -178,17 +190,17 @@ def patch_to_dict(obj): return \ { 'id' : obj.id, - 'date' : str(obj.date), + 'date' : unicode(obj.date).encode("utf-8"), 'filename' : obj.filename(), 'msgid' : obj.msgid, 'name' : obj.name, - 'project' : str(obj.project), + 'project' : unicode(obj.project).encode("utf-8"), 'project_id' : obj.project_id, - 'state' : str(obj.state), + 'state' : unicode(obj.state).encode("utf-8"), 'state_id' : obj.state_id, - 'submitter' : str(obj.submitter), + 'submitter' : unicode(obj.submitter).encode("utf-8"), 'submitter_id' : obj.submitter_id, - 'delegate' : str(obj.delegate), + 'delegate' : unicode(obj.delegate).encode("utf-8"), 'delegate_id' : max(obj.delegate_id, 0), 'commit_ref' : max(obj.commit_ref, ''), } @@ -292,7 +304,6 @@ def patch_list(filter={}): "commit_ref", "hash", "msgid", - "name", "max_count", ] @@ -326,7 +337,7 @@ def patch_list(filter={}): patches = Patch.objects.filter(**dfilter) if max_count > 0: - return map(patch_to_dict, patches)[:max_count] + return map(patch_to_dict, patches[:max_count]) else: return map(patch_to_dict, patches) @@ -342,12 +353,31 @@ def patch_get(patch_id): except: return {} +@xmlrpc_method(False) +def patch_get_by_hash(hash): + """Return structure for the given patch hash.""" + try: + patch = Patch.objects.filter(hash = hash)[0] + return patch_to_dict(patch) + except: + return {} + +@xmlrpc_method(False) +def patch_get_by_project_hash(project, hash): + """Return structure for the given patch hash.""" + try: + patch = Patch.objects.filter(project__linkname = project, + hash = hash)[0] + return patch_to_dict(patch) + except: + return {} + @xmlrpc_method(False) def patch_get_mbox(patch_id): """Return mbox string for the given patch ID.""" try: patch = Patch.objects.filter(id = patch_id)[0] - return patch.mbox().as_string() + return patch_to_mbox(patch).as_string() except: return ""