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 the current user based on the SSL or GSSAPI environment
119 variables and store it in the request object's login variable. This
120 conforms to the CherryPy API:
121 http://www.cherrypy.org/wiki/RequestObject#login
123 If the user is logged in successfully, cherrypy.request.login is set
124 to the username. If the user failed to log in, cherrypy.request.login
125 is set to False. If the user did not attempt authentication,
126 cherrypy.request.login is set to None."""
127 environ = cherrypy.request.wsgi_environ
128 user = environ.get('REMOTE_USER')
132 cherrypy.request.login = None # clear what cherrypy put there
134 if environ.get('AUTH_TYPE') == 'Negotiate':
135 # Convert the krb5 principal into a krb4 username
136 if not user.endswith('@%s' % config.kerberos.realm):
137 cherrypy.request.login = False # failed to login
139 cherrypy.request.login = user.split('@')[0].replace('/', '.')
141 cherrypy.request.login = user
143 cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
145 def invirtwebstate_init():
146 """Initialize the cherrypy.request.state object from Invirt"""
147 if not hasattr(cherrypy.request, "state"):
148 cherrypy.request.state = State(cherrypy.request.login)
150 cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
153 _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}