2
# Copyright (C) 2007-2008 The University of Melbourne
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2009 The University of Melbourne
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
# This is a mod_python handler program. The correct way to call it is to have
23
# Apache send all requests to be handled by the module 'dispatch'.
25
# Top-level handler. Handles all requests to all pages in IVLE.
26
# Handles authentication (not authorization).
27
# Then passes the request along to the appropriate ivle app.
18
# Author: Matt Giuca, Will Grant
21
This is a mod_python handler program. The correct way to call it is to have
22
Apache send all requests to be handled by the module 'dispatch'.
24
Top-level handler. Handles all requests to all pages in IVLE.
25
Handles authentication (not authorization).
26
Then passes the request along to the appropriate ivle app.
40
from mod_python import apache, Cookie
42
42
from ivle import util
44
44
import ivle.conf.apps
45
from ivle.dispatch.request import Request
46
from ivle.dispatch import login
48
from request import Request
49
49
import plugins.console # XXX: Relies on www/ being in the Python path.
51
# XXX List of plugins, which will eventually be read in from conf
53
'ivle.webapp.admin.user#Plugin',
54
'ivle.webapp.tutorial#Plugin',
55
'ivle.webapp.admin.subject#Plugin',
56
'ivle.webapp.filesystem.browser#Plugin',
57
'ivle.webapp.filesystem.diff#Plugin',
58
'ivle.webapp.filesystem.svnlog#Plugin',
59
'ivle.webapp.groups#Plugin',
60
'ivle.webapp.console#Plugin',
61
'ivle.webapp.security#Plugin',
62
'ivle.webapp.media#Plugin',
65
def generate_route_mapper(plugins):
67
Build a Mapper object for doing URL matching using 'routes', based on the
68
given plugin registry.
70
m = routes.Mapper(explicit=True)
72
# Establish a URL pattern for each element of plugin.urls
73
if not hasattr(plugins[name], 'urls'):
75
for url in plugins[name].urls:
78
kwargs_dict = url[2] if len(url) >= 3 else {}
79
m.connect(routex, view=view_class, **kwargs_dict)
82
def get_plugin(pluginstr):
83
plugin_path, classname = pluginstr.split('#')
84
# Load the plugin module from somewhere in the Python path
85
# (Note that plugin_path is a fully-qualified Python module name).
87
getattr(__import__(plugin_path, fromlist=[classname]), classname))
52
90
"""Handles a request which may be to anywhere in the site except media.
53
91
Intended to be called by mod_python, as a handler.
64
102
handle_unknown_exception(apachereq, *sys.exc_info())
65
103
# Tell Apache not to generate its own errors as well
104
return mod_python.apache.OK
68
106
# Run the main handler, and catch all exceptions
76
114
handle_unknown_exception(req, *sys.exc_info())
77
115
# Tell Apache not to generate its own errors as well
116
return mod_python.apache.OK
80
118
def handler_(req, apachereq):
88
126
if not req.publicmode:
89
127
req.user = login.get_user_details(req)
129
### BEGIN New plugins framework ###
130
# XXX This should be done ONCE per Python process, not per request.
132
# XXX No authentication is done here
133
req.plugins = dict([get_plugin(pluginstr) for pluginstr in plugins_HACK])
134
req.reverse_plugins = dict([(v, k) for (k, v) in req.plugins.items()])
135
req.mapper = generate_route_mapper(req.plugins)
137
matchdict = req.mapper.match(req.uri)
138
if matchdict is not None:
139
viewcls = matchdict['view']
140
# Get the remaining arguments, less 'view', 'action' and 'controller'
141
# (The latter two seem to be built-in, and we don't want them).
142
kwargs = matchdict.copy()
144
# Instantiate the view, which should be a BaseView class
145
view = viewcls(req, **kwargs)
150
### END New plugins framework ###
91
152
# Check req.app to see if it is valid. 404 if not.
92
153
if req.app is not None and req.app not in ivle.conf.apps.app_url:
93
154
req.throw_error(Request.HTTP_NOT_FOUND,
180
241
# For some reason, some versions of mod_python have "_server" instead of
181
242
# "main_server". So we check for both.
183
admin_email = apache.main_server.server_admin
244
admin_email = mod_python.apache.main_server.server_admin
184
245
except AttributeError:
186
admin_email = apache._server.server_admin
247
admin_email = mod_python.apache._server.server_admin
187
248
except AttributeError:
293
362
logging.error('%s\n%s'%(str(msg), tb))
363
# Error messages are only displayed is the user is NOT a student,
364
# or if there has been a problem logging the error message
365
show_errors = (not publicmode) and ((login and \
366
str(role) != "student") or logfail)
295
367
req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
296
368
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
297
369
<html xmlns="http://www.w3.org/1999/xhtml">
298
370
<head><title>IVLE Internal Server Error</title></head>
300
372
<h1>IVLE Internal Server Error""")
301
if (codename is not None
302
and httpcode != apache.HTTP_INTERNAL_SERVER_ERROR):
303
req.write(": %s" % cgi.escape(codename))
374
if (codename is not None
375
and httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR):
376
req.write(": %s" % cgi.escape(codename))
304
378
req.write("""</h1>
305
379
<p>An error has occured which is the fault of the IVLE developers or
380
administration. The developers have been notified.</p>
309
req.write("<p>%s</p>\n" % cgi.escape(msg))
310
if httpcode is not None:
311
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
313
<p>Please report this to <a href="mailto:%s">%s</a> (the system
314
administrator). Include the following information:</p>
315
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
384
req.write("<p>%s</p>\n" % cgi.escape(msg))
385
if httpcode is not None:
386
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
388
<p>Please report this to <a href="mailto:%s">%s</a> (the system
389
administrator). Include the following information:</p>
390
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
317
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
319
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
320
%cgi.escape(logfile))
392
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
394
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
395
%cgi.escape(logfile))
321
396
req.write("</body></html>")