1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
from trac.core import *
from trac.web.main import IRequestHandler
from trac.web.chrome import ITemplateProvider, add_stylesheet
from tracrpc.api import IXMLRPCHandler, XMLRPCSystem
from trac.wiki.formatter import wiki_to_oneliner
import xmlrpclib
class XMLRPCWeb(Component):
""" Handle XML-RPC calls from HTTP clients, as well as presenting a list of
methods available to the currently logged in user. Browsing to
<trac>/xmlrpc will display this list. """
implements(IRequestHandler, ITemplateProvider)
# IRequestHandler methods
def match_request(self, req):
return req.path_info in ('/login/xmlrpc', '/xmlrpc')
def _send_response(self, req, response):
req.send_response(200)
req.send_header('Content-Type', 'text/xml')
req.send_header('Content-Length', len(response))
req.end_headers()
req.write(response)
def process_request(self, req):
# Need at least XML_RPC
req.perm.assert_permission('XML_RPC')
# Dump RPC functions
content_type = req.get_header('Content-Type')
if content_type is None or 'text/xml' not in content_type:
namespaces = {}
for method in XMLRPCSystem(self.env).all_methods(req):
namespace = method.namespace.replace('.', '_')
if namespace not in namespaces:
namespaces[namespace] = {
'description' : wiki_to_oneliner(method.namespace_description, self.env),
'methods' : [],
'namespace' : method.namespace,
}
try:
namespaces[namespace]['methods'].append((method.signature, wiki_to_oneliner(method.description, self.env), method.permission))
except Exception, e:
from StringIO import StringIO
import traceback
out = StringIO()
traceback.print_exc(file=out)
raise Exception('%s: %s\n%s' % (method.name, str(e), out.getvalue()))
add_stylesheet(req, 'common/css/wiki.css')
req.hdf['xmlrpc.functions'] = namespaces
return 'xmlrpclist.cs', None
# Handle XML-RPC call
args, method = xmlrpclib.loads(req.read(int(req.get_header('Content-Length'))))
try:
result = XMLRPCSystem(self.env).get_method(method)(req, args)
self._send_response(req, xmlrpclib.dumps(result, methodresponse=True))
except xmlrpclib.Fault, e:
self.log.error(e)
self._send_response(req, xmlrpclib.dumps(e))
except Exception, e:
self.log.error(e)
import traceback
from StringIO import StringIO
out = StringIO()
traceback.print_exc(file = out)
self.log.error(out.getvalue())
self._send_response(req, xmlrpclib.dumps(xmlrpclib.Fault(2, "'%s' while executing '%s()'" % (str(e), method))))
# ITemplateProvider
def get_htdocs_dirs(self):
return []
def get_templates_dirs(self):
from pkg_resources import resource_filename
return [resource_filename(__name__, 'templates')]
|