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
12 class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
13 """Callable which processes a dictionary, returning the rendered body."""
15 def __init__(self, template, next_handler, content_type='text/html; charset=utf-8'):
16 self.template = template
17 self.next_handler = next_handler
18 self.content_type = content_type
21 env = globals().copy()
22 env.update(self.next_handler())
23 cherrypy.response.headers['Content-Type'] = self.content_type
24 return self.template.render(**env)
27 class MakoLoader(object):
32 def get_lookup(self, directories, module_directory=None,
33 collection_size=-1, imports=[], **kwargs):
34 # Find the appropriate template lookup.
35 key = (tuple(directories), module_directory)
37 lookup = self.lookups[key]
39 lookup = TemplateLookup(directories=directories,
40 module_directory=module_directory,
41 collection_size=collection_size,
42 default_filters=['decode.utf8'],
43 input_encoding='utf-8',
44 output_encoding='utf-8',
47 self.lookups[key] = lookup
50 def __call__(self, filename, directories, module_directory=None,
51 collection_size=-1, content_type='text/html; charset=utf-8',
53 cherrypy.request.lookup = lookup = self.get_lookup(directories, module_directory,
54 collection_size, imports)
55 cherrypy.request.template = t = lookup.get_template(filename)
56 cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler, content_type)
58 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
60 def revertStandardError():
61 """Move stderr to stdout, and return the contents of the old stderr."""
63 if not isinstance(errio, StringIO):
65 sys.stderr = sys.stdout
70 old_handler = cherrypy.request.handler
71 def wrapper(*args, **kwargs):
72 sys.stderr = StringIO()
73 ret = old_handler(*args, **kwargs)
74 e = revertStandardError()
76 if isinstance(ret, dict):
80 cherrypy.request.handler = wrapper
82 cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
84 class JSONEncoder(simplejson.JSONEncoder):
85 def default(self, obj):
86 if isinstance(obj, datetime.datetime):
88 elif isinstance(obj, decimal.Decimal):
91 return simplejson.JSONEncoder.default(self, obj)
93 def jsonify_tool_callback(*args, **kwargs):
94 if not cherrypy.request.cached:
95 response = cherrypy.response
96 response.headers['Content-Type'] = 'text/javascript'
97 response.body = JSONEncoder().iterencode(response.body)
99 cherrypy.tools.jsonify = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
102 """If the user isn't logged in, raise 403 with an error."""
103 if cherrypy.request.login is False:
104 raise cherrypy.HTTPError(403,
105 "You are not authorized to access that resource")
107 cherrypy.tools.require_login = cherrypy.Tool('on_start_resource', require_login, priority=150)
110 """If the request isn't a POST request, raise 405 Method Not Allowed"""
111 if cherrypy.request.method != "POST":
112 raise cherrypy.HTTPError(405,
113 "You must submit this request with POST")
115 cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource', require_POST, priority=150)
117 def remote_user_login():
118 """Get remote user from SSL or GSSAPI, and store in request object.
120 Get the current user based on environment variables set by SSL or
121 GSSAPI, and store it in the attribute cherrpy.request.login.
123 Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
124 the attribute is set to the username on successful login, to False on
125 failed login, and is left at None if the user attempted no authentication.
127 environ = cherrypy.request.wsgi_environ
128 user = environ.get('REMOTE_USER')
131 if environ.get('AUTH_TYPE') == 'Negotiate':
132 # Convert the krb5 principal into a krb4 username
133 if not user.endswith('@%s' % config.kerberos.realm):
134 cherrypy.request.login = False # failed to log in
136 cherrypy.request.login = user.split('@')[0].replace('/', '.')
138 cherrypy.request.login = user
140 cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
142 def invirtwebstate_init():
143 """Initialize the cherrypy.request.state object from Invirt"""
144 if not hasattr(cherrypy.request, "state"):
145 cherrypy.request.state = State(cherrypy.request.login)
147 cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
150 _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}