4 from mako.template import Template
5 from mako.lookup import TemplateLookup
7 import datetime, decimal
8 from StringIO import StringIO
9 from invirt.config import structs as config
10 from webcommon import State
13 class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
14 """Callable which processes a dictionary, returning the rendered body."""
16 def __init__(self, template, next_handler, content_type='text/html; charset=utf-8'):
17 self.template = template
18 self.next_handler = next_handler
19 self.content_type = content_type
22 env = globals().copy()
23 env.update(self.next_handler())
24 cherrypy.response.headers['Content-Type'] = self.content_type
25 return self.template.render(**env)
28 class MakoLoader(object):
33 def get_lookup(self, directories, module_directory=None,
34 collection_size=-1, imports=[], **kwargs):
35 # Find the appropriate template lookup.
36 key = (tuple(directories), module_directory)
38 lookup = self.lookups[key]
40 lookup = TemplateLookup(directories=directories,
41 module_directory=module_directory,
42 collection_size=collection_size,
43 default_filters=['decode.utf8'],
44 input_encoding='utf-8',
45 output_encoding='utf-8',
48 self.lookups[key] = lookup
51 def __call__(self, filename, directories, module_directory=None,
52 collection_size=-1, content_type='text/html; charset=utf-8',
54 cherrypy.request.lookup = lookup = self.get_lookup(directories, module_directory,
55 collection_size, imports)
56 cherrypy.request.template = t = lookup.get_template(filename)
57 cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler, content_type)
59 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
62 def revertStandardError():
63 """Move stderr to stdout, and return the contents of the old stderr."""
65 if not isinstance(errio, StringIO):
67 sys.stderr = sys.stdout
73 old_handler = cherrypy.request.handler
74 def wrapper(*args, **kwargs):
75 sys.stderr = StringIO()
76 ret = old_handler(*args, **kwargs)
77 e = revertStandardError()
79 if isinstance(ret, dict):
83 cherrypy.request.handler = wrapper
85 cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
88 class JSONEncoder(simplejson.JSONEncoder):
89 def default(self, obj):
90 if isinstance(obj, datetime.datetime):
92 elif isinstance(obj, decimal.Decimal):
95 return simplejson.JSONEncoder.default(self, obj)
98 def jsonify_tool_callback(*args, **kwargs):
99 if not cherrypy.request.cached:
100 response = cherrypy.response
101 response.headers['Content-Type'] = 'text/javascript'
102 response.body = JSONEncoder().iterencode(response.body)
104 cherrypy.tools.jsonify = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
108 """If the user isn't logged in, raise 403 with an error."""
109 if cherrypy.request.login is False:
110 raise cherrypy.HTTPError(403,
111 "You are not authorized to access that resource")
113 cherrypy.tools.require_login = cherrypy.Tool('on_start_resource', require_login, priority=150)
117 """If the request isn't a POST request, raise 405 Method Not Allowed"""
118 if cherrypy.request.method != "POST":
119 raise cherrypy.HTTPError(405,
120 "You must submit this request with POST")
122 cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource', require_POST, priority=150)
125 def remote_user_login():
126 """Get remote user from SSL or GSSAPI, and store in request object.
128 Get the current user based on environment variables set by SSL or
129 GSSAPI, and store it in the attribute cherrpy.request.login.
131 Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
132 the attribute is set to the username on successful login, to False on
133 failed login, and is left at None if the user attempted no authentication.
135 environ = cherrypy.request.wsgi_environ
136 user = environ.get('REMOTE_USER')
139 if environ.get('AUTH_TYPE') == 'Negotiate':
140 # Convert the krb5 principal into a krb4 username
141 if not user.endswith('@%s' % config.kerberos.realm):
142 cherrypy.request.login = False # failed to log in
144 cherrypy.request.login = user.split('@')[0].replace('/', '.')
146 cherrypy.request.login = user
148 cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
151 def invirtwebstate_init():
152 """Initialize the cherrypy.request.state object from Invirt"""
153 if not hasattr(cherrypy.request, "state"):
154 cherrypy.request.state = State(cherrypy.request.login)
156 cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
160 _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}