PageRenderTime 44ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/indico/MaKaC/services/interface/rpc/json.py

https://github.com/davidmorrison/indico
Python | 159 lines | 104 code | 17 blank | 38 comment | 9 complexity | e5fc6676a7f2c1892ece17c12c8a213a MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. ##
  3. ##
  4. ## This file is part of CDS Indico.
  5. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
  6. ##
  7. ## CDS Indico is free software; you can redistribute it and/or
  8. ## modify it under the terms of the GNU General Public License as
  9. ## published by the Free Software Foundation; either version 2 of the
  10. ## License, or (at your option) any later version.
  11. ##
  12. ## CDS Indico is distributed in the hope that it will be useful, but
  13. ## WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. ## General Public License for more details.
  16. ##
  17. ## You should have received a copy of the GNU General Public License
  18. ## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
  19. ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  20. from MaKaC.common.security import Sanitization
  21. from MaKaC.common.fossilize import fossilize, NonFossilizableException
  22. from MaKaC.fossils.error import ICausedErrorFossil
  23. try:
  24. from indico.web.wsgi import webinterface_handler_config as apache
  25. except ImportError:
  26. pass
  27. from MaKaC.services.interface.rpc.common import RequestError
  28. from MaKaC.services.interface.rpc.common import ProcessError
  29. from MaKaC.services.interface.rpc.common import CausedError
  30. from MaKaC.services.interface.rpc.common import NoReportError
  31. from MaKaC.services.interface.rpc.process import ServiceRunner
  32. from MaKaC.common.logger import Logger
  33. from indico.util.json import dumps, loads
  34. class Json:
  35. def __init__(self, content):
  36. self.json = encode(content)
  37. def encode(obj):
  38. return dumps(obj, ensure_ascii=True)
  39. def encode_iframe(obj):
  40. s = encode(obj)
  41. return "<html><head></head><body><textarea>%s</textarea></body></html>" % s
  42. def decode(str):
  43. return unicodeToUtf8(loads(str))
  44. def unicodeToUtf8(obj):
  45. """ obj must be a unicode object, a list or a dictionary
  46. This method will loop through the object and change unicode objects into str objects encoded in utf-8.
  47. If a list or a dictionary is found during the loop, a recursive call is made.
  48. However this method does not support objects that are not lists or dictionaries.
  49. This method is useful to turn unicode objects from the output object given by simplejson.loads(),
  50. into str objects encoded in utf-8.
  51. In case of a persistent object or an object inside a persistent object,
  52. you will need to notify the database of changes in the object after calling this method.
  53. Author: David Martin Clavo
  54. """
  55. # replace a single unicode object
  56. if isinstance(obj, unicode):
  57. return obj.encode("utf-8",'replace')
  58. # replace unicode objects inside a list
  59. if isinstance(obj,list):
  60. for i in range(0, len(obj)):
  61. obj[i] = unicodeToUtf8(obj[i])
  62. #replace unicode objects inside a dictionary
  63. if isinstance(obj,dict):
  64. for k,v in obj.items():
  65. del obj[k] #we delete the old unicode key
  66. #keys in JSON objects can only be strings, but we still call unicodeToUtf8
  67. #for the key in case we have a Python object whose key is a number, etc.
  68. obj[unicodeToUtf8(k)] = unicodeToUtf8(v)
  69. return obj
  70. def process(req):
  71. responseBody = {
  72. "version": "1.1",
  73. "error": None,
  74. "result": None
  75. }
  76. requestBody = None
  77. try:
  78. # check content type (if the users know what they are using)
  79. #if req.content_type != "application/json":
  80. # raise RequestError("Invalid content type. It must be 'application/json'.")
  81. # read request
  82. requestText = req.read()
  83. Logger.get('rpc').info('json rpc request. request text= ' + str(requestText))
  84. if requestText == "":
  85. raise RequestError("ERR-R2", "Empty request.")
  86. # decode json
  87. try:
  88. requestBody = decode(requestText)
  89. except Exception, e:
  90. raise RequestError("ERR-R3", "Error parsing json request.", e)
  91. if "id" in requestBody:
  92. responseBody["id"] = requestBody["id"]
  93. result = ServiceRunner().invokeMethod(str(requestBody["method"]),
  94. requestBody.get("params", []), req)
  95. # serialize result
  96. try:
  97. responseBody["result"] = result
  98. except Exception, e:
  99. raise ProcessError("ERR-P1", "Error during serialization.")
  100. except CausedError, e:
  101. try:
  102. errorInfo = fossilize(e)
  103. except NonFossilizableException, e2:
  104. # catch Exceptions that are not registered as Fossils
  105. # and log them
  106. errorInfo = {'code':'', 'message': str(e2)}
  107. Logger.get('dev').exception('Exception not registered as fossil')
  108. if isinstance(e, NoReportError):
  109. # NoReport errors (i.e. not logged in) shouldn't be logged
  110. pass
  111. else:
  112. Logger.get('rpc').exception('Service request failed. Request text:\r\n%s\r\n\r\n' % str(requestText))
  113. if requestBody:
  114. params = requestBody.get("params", [])
  115. Sanitization._escapeHTML(params)
  116. errorInfo["requestInfo"] = {"method": str(requestBody["method"]),
  117. "params": params,
  118. "origin": str(requestBody.get("origin", "unknown"))}
  119. Logger.get('rpc').debug('Arguments: %s' % errorInfo['requestInfo'])
  120. responseBody["error"] = errorInfo
  121. try:
  122. jsonResponse = encode(responseBody)
  123. except:
  124. Logger.get('rpc').exception("Problem encoding JSON response")
  125. # This is to avoid exceptions due to old data encodings (based on iso-8859-1)
  126. responseBody["result"] = responseBody["result"].decode('iso-8859-1').encode('utf-8')
  127. jsonResponse = encode(responseBody)
  128. req.content_type = "application/json"
  129. req.write(jsonResponse)
  130. return apache.OK