diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index ab74611b8cb..e1a3c476a32 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -14,7 +14,6 @@ import re import simplejson import time import urllib2 -import xmlrpclib import zlib from xml.etree import ElementTree from cStringIO import StringIO @@ -97,7 +96,7 @@ def db_monodb(req): dbs = db_list(req) if len(dbs) == 1: return dbs[0] - except xmlrpclib.Fault: + except Exception: # ignore access denied pass return False @@ -749,10 +748,10 @@ class Database(openerpweb.Controller): try: return req.session.proxy("db").drop(password, db) - except xmlrpclib.Fault, e: - if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': - return {'error': e.faultCode, 'title': 'Drop Database'} - return {'error': _('Could not drop database !'), 'title': _('Drop Database')} + except openerp.exceptions.AccessDenied: + return {'error': 'AccessDenied', 'title': 'Drop Database'} + except Exception: + return {'error': _('Could not drop database !'), 'title': _('Drop Database')} @openerpweb.httprequest def backup(self, req, backup_db, backup_pwd, token): @@ -769,8 +768,8 @@ class Database(openerpweb.Controller): ('Content-Disposition', content_disposition(filename, req))], {'fileToken': int(token)} ) - except xmlrpclib.Fault, e: - return simplejson.dumps([[],[{'error': e.faultCode, 'title': _('Backup Database')}]]) + except Exception, e: + return simplejson.dumps([[],[{'error': openerp.tools.ustr(e), 'title': _('Backup Database')}]]) @openerpweb.httprequest def restore(self, req, db_file, restore_pwd, new_db): @@ -778,9 +777,8 @@ class Database(openerpweb.Controller): data = base64.b64encode(db_file.read()) req.session.proxy("db").restore(restore_pwd, new_db, data) return '' - except xmlrpclib.Fault, e: - if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': - raise Exception("AccessDenied") + except openerp.exceptions.AccessDenied, e: + raise Exception("AccessDenied") @openerpweb.jsonrequest def change_password(self, req, fields): @@ -789,10 +787,10 @@ class Database(openerpweb.Controller): dict(map(operator.itemgetter('name', 'value'), fields))) try: return req.session.proxy("db").change_admin_password(old_password, new_password) - except xmlrpclib.Fault, e: - if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': - return {'error': e.faultCode, 'title': _('Change Password')} - return {'error': _('Error, password not changed !'), 'title': _('Change Password')} + except openerp.exceptions.AccessDenied: + return {'error': 'AccessDenied', 'title': _('Change Password')} + except Exception: + return {'error': _('Error, password not changed !'), 'title': _('Change Password')} class Session(openerpweb.Controller): _cp_path = "/web/session" @@ -1194,7 +1192,7 @@ class Binary(openerpweb.Controller): image_data = base64.b64decode(image_base64) - except (TypeError, xmlrpclib.Fault): + except Exception: image_data = self.placeholder(req) headers.append(('ETag', retag)) headers.append(('Content-Length', len(image_data))) @@ -1311,7 +1309,7 @@ class Binary(openerpweb.Controller): 'filename': ufile.filename, 'id': attachment_id } - except xmlrpclib.Fault, e: + except Exception: args = {'error':e.faultCode } return out % (simplejson.dumps(callback), simplejson.dumps(args)) diff --git a/addons/web/http.py b/addons/web/http.py index 8595e38446f..7a1c1bcb4af 100644 --- a/addons/web/http.py +++ b/addons/web/http.py @@ -19,7 +19,6 @@ import time import traceback import urlparse import uuid -import xmlrpclib import babel.core import simplejson @@ -194,35 +193,23 @@ class JsonRequest(WebRequest): response['id'] = self.jsonrequest.get('id') response["result"] = method(self, **self.params) except session.AuthenticationError: + se = serialize_exception(e) error = { 'code': 100, 'message': "OpenERP Session Invalid", - 'data': { + 'data': dict(se, **{ 'type': 'session_invalid', - 'debug': traceback.format_exc() - } + }) } - except xmlrpclib.Fault, e: + except Exception, e: + se = serialize_exception(e) error = { 'code': 200, 'message': "OpenERP Server Error", - 'data': { + 'data': dict(se, **{ 'type': 'server_exception', - 'fault_code': e.faultCode, - 'debug': "Client %s\nServer %s" % ( - "".join(traceback.format_exception("", None, sys.exc_traceback)), e.faultString) - } - } - except Exception: - logging.getLogger(__name__ + '.JSONRequest.dispatch').exception\ - ("An error occured while handling a json request") - error = { - 'code': 300, - 'message': "OpenERP WebClient Error", - 'data': { - 'type': 'client_exception', - 'debug': "Client %s" % traceback.format_exc() - } + 'fault_code': se["message"], + }) } if error: response["error"] = error @@ -244,6 +231,27 @@ class JsonRequest(WebRequest): r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))]) return r +def serialize_exception(e): + return { + "name": type(e).__module__ + "." + type(e).__name__ if type(e).__module__ else type(e).__name__, + "debug": traceback.format_exc(), + "message": u"%s" % e, + "arguments": to_jsonable(e.args), + } + +def to_jsonable(o): + if isinstance(o, str) or isinstance(o,unicode) or isinstance(o, int) or isinstance(o, long) \ + or isinstance(o, bool) or o is None or isinstance(o, float): + return o + if isinstance(o, list) or isinstance(o, tuple): + return [to_jsonable(x) for x in o] + if isinstance(o, dict): + tmp = {} + for k, v in o.items(): + tmp[u"%s" % k] = to_jsonable(v) + return tmp + return u"%s" % o + def jsonrequest(f): """ Decorator marking the decorated method as being a handler for a JSON-RPC request (the exact request path is specified via the @@ -274,28 +282,17 @@ class HttpRequest(WebRequest): _logger.debug("%s --> %s.%s %r", self.httprequest.method, method.im_class.__name__, method.__name__, akw) try: r = method(self, **self.params) - except xmlrpclib.Fault, e: - r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps({ + except Exception: + se = serialize_exception(e) + error = { 'code': 200, 'message': "OpenERP Server Error", - 'data': { + 'data': dict(se, **{ 'type': 'server_exception', - 'fault_code': e.faultCode, - 'debug': "Server %s\nClient %s" % ( - e.faultString, traceback.format_exc()) - } - }))) - except Exception: - logging.getLogger(__name__ + '.HttpRequest.dispatch').exception( - "An error occurred while handling a json request") - r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps({ - 'code': 300, - 'message': "OpenERP WebClient Error", - 'data': { - 'type': 'client_exception', - 'debug': "Client %s" % traceback.format_exc() - } - }))) + 'fault_code': se["message"], + }) + } + r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps(error))) if self.debug or 1: if isinstance(r, (werkzeug.wrappers.BaseResponse, werkzeug.exceptions.HTTPException)): _logger.debug('<-- %s', r) diff --git a/addons/web/session.py b/addons/web/session.py index 8a083e0dec9..13c9d28230c 100644 --- a/addons/web/session.py +++ b/addons/web/session.py @@ -6,7 +6,6 @@ import logging import time import traceback import sys -import xmlrpclib import openerp @@ -85,23 +84,7 @@ class OpenERPSession(object): self.jsonp_requests = {} # FIXME use a LRU def send(self, service_name, method, *args): - code_string = u"warning -- %s\n\n%s" - try: - return openerp.netsvc.dispatch_rpc(service_name, method, args) - except openerp.osv.osv.except_osv, e: - raise xmlrpclib.Fault(code_string % (e.name, e.value), '') - except openerp.exceptions.Warning, e: - raise xmlrpclib.Fault(code_string % ("Warning", e), '') - except openerp.exceptions.AccessError, e: - raise xmlrpclib.Fault(code_string % ("AccessError", e), '') - except openerp.exceptions.AccessDenied, e: - raise xmlrpclib.Fault('AccessDenied', openerp.tools.ustr(e)) - except openerp.exceptions.DeferredException, e: - formatted_info = "".join(traceback.format_exception(*e.traceback)) - raise xmlrpclib.Fault(openerp.tools.ustr(e), formatted_info) - except Exception, e: - formatted_info = "".join(traceback.format_exception(*(sys.exc_info()))) - raise xmlrpclib.Fault(openerp.tools.ustr(e), formatted_info) + return openerp.netsvc.dispatch_rpc(service_name, method, args) def proxy(self, service): return Service(self, service)