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,
17 content_type='text/html; charset=utf-8'):
18 self.template = template
19 self.next_handler = next_handler
20 self.content_type = content_type
23 env = globals().copy()
24 env.update(self.next_handler())
25 cherrypy.response.headers['Content-Type'] = self.content_type
26 return self.template.render(**env)
29 class MakoLoader(object):
34 def get_lookup(self, directories, module_directory=None,
35 collection_size=-1, imports=[], **kwargs):
36 # Find the appropriate template lookup.
37 key = (tuple(directories), module_directory)
39 lookup = self.lookups[key]
41 lookup = TemplateLookup(directories=directories,
42 module_directory=module_directory,
43 collection_size=collection_size,
44 default_filters=['decode.utf8'],
45 input_encoding='utf-8',
46 output_encoding='utf-8',
49 self.lookups[key] = lookup
52 def __call__(self, filename, directories, module_directory=None,
53 collection_size=-1, content_type='text/html; charset=utf-8',
55 cherrypy.request.lookup = lookup = self.get_lookup(
56 directories, module_directory, collection_size, imports)
57 cherrypy.request.template = t = lookup.get_template(filename)
58 cherrypy.request.handler = MakoHandler(
59 t, cherrypy.request.handler, content_type)
61 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
64 def revertStandardError():
65 """Move stderr to stdout, and return the contents of the old stderr."""
67 if not isinstance(errio, StringIO):
69 sys.stderr = sys.stdout
75 old_handler = cherrypy.request.handler
76 def wrapper(*args, **kwargs):
77 sys.stderr = StringIO()
78 ret = old_handler(*args, **kwargs)
79 e = revertStandardError()
81 if isinstance(ret, dict):
85 cherrypy.request.handler = wrapper
87 cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
90 class JSONEncoder(simplejson.JSONEncoder):
91 def default(self, obj):
92 if isinstance(obj, datetime.datetime):
94 elif isinstance(obj, decimal.Decimal):
97 return simplejson.JSONEncoder.default(self, obj)
100 def jsonify_tool_callback(*args, **kwargs):
101 if not cherrypy.request.cached:
102 response = cherrypy.response
103 response.headers['Content-Type'] = 'text/javascript'
104 response.body = JSONEncoder().iterencode(response.body)
106 cherrypy.tools.jsonify = cherrypy.Tool('before_finalize',
107 jsonify_tool_callback, priority=30)
111 """If the user isn't logged in, raise 403 with an error."""
112 if cherrypy.request.login is False:
113 raise cherrypy.HTTPError(403,
114 "You are not authorized to access that resource")
116 cherrypy.tools.require_login = cherrypy.Tool('on_start_resource',
117 require_login, priority=150)
121 """If the request isn't a POST request, raise 405 Method Not Allowed"""
122 if cherrypy.request.method != "POST":
123 raise cherrypy.HTTPError(405,
124 "You must submit this request with POST")
126 cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource',
127 require_POST, priority=150)
130 def remote_user_login():
131 """Get remote user from SSL or GSSAPI, and store in request object.
133 Get the current user based on environment variables set by SSL or
134 GSSAPI, and store it in the attribute cherrpy.request.login.
136 Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
137 the attribute is set to the username on successful login, to False on
138 failed login, and is left at None if the user attempted no authentication.
140 environ = cherrypy.request.wsgi_environ
141 user = environ.get('REMOTE_USER')
144 if environ.get('AUTH_TYPE') == 'Negotiate':
145 # Convert the krb5 principal into a krb4 username
146 if not user.endswith('@%s' % config.kerberos.realm):
147 cherrypy.request.login = False # failed to log in
149 cherrypy.request.login = user.split('@')[0].replace('/', '.')
151 cherrypy.request.login = user
153 cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource',
154 remote_user_login, priority=50)
157 def invirtwebstate_init():
158 """Initialize the cherrypy.request.state object from Invirt"""
159 if not hasattr(cherrypy.request, "state"):
160 cherrypy.request.state = State(cherrypy.request.login)
162 cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource',
163 invirtwebstate_init, priority=100)
167 _cp_config = {'tools.mako.directories':
168 [os.path.join(os.path.dirname(__file__),'templates')]}