65
65
m.connect(routex, view=view_class, **kwargs_dict)
69
"""Handles a request which may be to anywhere in the site except media.
68
def handler(apachereq):
69
"""Handles an HTTP request.
70
71
Intended to be called by mod_python, as a handler.
72
req: An Apache request object.
74
# Make the request object into an IVLE request which can be passed to apps
77
req = Request(req, html.write_html_head)
79
# Pass the apachereq to error reporter, since ivle req isn't created
81
handle_unknown_exception(apachereq, *sys.exc_info())
82
# Tell Apache not to generate its own errors as well
83
return mod_python.apache.OK
85
# Run the main handler, and catch all exceptions
87
return handler_(req, apachereq)
88
except mod_python.apache.SERVER_RETURN:
89
# An apache error. We discourage these, but they might still happen.
93
handle_unknown_exception(req, *sys.exc_info())
94
# Tell Apache not to generate its own errors as well
95
return mod_python.apache.OK
97
def handler_(req, apachereq):
99
Nested handler function. May raise exceptions. The top-level handler is
100
just used to catch exceptions.
101
Takes both an IVLE request and an Apache req.
73
@param apachereq: An Apache request object.
75
# Make the request object into an IVLE request which can be given to views
76
req = Request(apachereq, config)
103
78
# Hack? Try and get the user login early just in case we throw an error
104
79
# (most likely 404) to stop us seeing not logged in even when we are.
105
80
if not req.publicmode:
106
user = login.get_user_details(req)
81
user = ivle.webapp.security.get_user_details(req)
108
83
# Don't set the user if it is disabled or hasn't accepted the ToS.
109
84
if user and user.valid:
112
conf = ivle.config.Config()
115
### BEGIN New plugins framework ###
116
87
if req.publicmode:
117
req.mapper = generate_route_mapper(conf.plugin_index[PublicViewPlugin],
88
req.mapper = generate_router(config.plugin_index[PublicViewPlugin],
120
req.mapper = generate_route_mapper(conf.plugin_index[ViewPlugin],
91
req.mapper = generate_router(config.plugin_index[ViewPlugin], 'urls')
123
93
matchdict = req.mapper.match(req.uri)
124
94
if matchdict is not None:
164
139
req.store.commit()
167
# We had no matching URL! Check if it matches an old-style app. If
169
if req.app not in ivle.conf.apps.app_url:
170
return req.HTTP_NOT_FOUND # TODO: Prettify.
171
### END New plugins framework ###
174
### BEGIN legacy application framework ###
175
# We have no public apps back here.
176
assert not req.publicmode
178
# app is the App object for the chosen app
180
app = ivle.conf.apps.app_url[ivle.conf.apps.default_app]
182
app = ivle.conf.apps.app_url[req.app]
184
# Check if app requires auth. If so, perform authentication and login.
185
# This will either return a User object, None, or perform a redirect
186
# which we will not catch here.
188
logged_in = req.user is not None
192
assert logged_in # XXX
195
# Keep the user's session alive by writing to the session object.
196
# req.get_session().save()
197
# Well, it's a fine idea, but it creates considerable grief in the
198
# concurrent update department, so instead, we'll just make the
199
# sessions not time out.
200
req.get_session().unlock()
202
# Call the specified app with the request object
203
apps.call_app(app.dir, req)
205
# MAKE SURE we write the HTTP (and possibly HTML) header. This
206
# wouldn't happen if nothing else ever got written, so we have to make
208
req.ensure_headers_written()
210
# When done, write out the HTML footer if the app has requested it
211
if req.write_html_head_foot:
212
html.write_html_foot(req)
214
# Note: Apache will not write custom HTML error messages here.
215
# Use req.throw_error to do that.
142
XHTMLErrorView(req, NotFound()).render(req)
218
145
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
274
logging.debug('Logging Unhandled Exception')
276
# We handle 3 types of error.
277
# IVLEErrors with 4xx response codes (client error).
278
# IVLEErrors with 5xx response codes (handled server error).
279
# Other exceptions (unhandled server error).
280
# IVLEErrors should not have other response codes than 4xx or 5xx
281
# (eg. throw_redirect should have been used for 3xx codes).
282
# Therefore, that is treated as an unhandled error.
284
if (exc_type == util.IVLEError and httpcode >= 400
285
and httpcode <= 499):
286
# IVLEErrors with 4xx response codes are client errors.
287
# Therefore, these have a "nice" response (we even coat it in the IVLE
290
req.write_html_head_foot = True
291
req.write_javascript_settings = False
292
req.write('<div id="ivle_padding">\n')
188
# A "bad" error message. We shouldn't get here unless IVLE
189
# misbehaves (which is currently very easy, if things aren't set up
191
# Write the traceback.
192
# If this is a non-4xx IVLEError, get the message and httpcode and
193
# make the error message a bit nicer (but still include the
195
# We also need to special-case IVLEJailError, as we can get another
196
# almost-exception out of it.
198
codename, msg = None, None
200
if exc_type is util.IVLEJailError:
201
msg = exc_value.type_str + ": " + exc_value.message
202
tb = 'Exception information extracted from IVLEJailError:\n'
203
tb += urllib.unquote(exc_value.info)
294
206
codename, msg = req.get_http_codename(httpcode)
295
207
except AttributeError:
296
codename, msg = None, None
297
# Override the default message with the supplied one,
299
if exc_value.message is not None:
300
msg = exc_value.message
301
if codename is not None:
302
req.write("<h1>Error: %s</h1>\n" % cgi.escape(codename))
304
req.write("<h1>Error</h1>\n")
306
req.write("<p>%s</p>\n" % cgi.escape(msg))
308
req.write("<p>An unknown error occured.</p>\n")
311
logging.info(str(msg))
313
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
315
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
316
%cgi.escape(logfile))
317
req.write('</div>\n')
318
html.write_html_foot(req)
320
# A "bad" error message. We shouldn't get here unless IVLE
321
# misbehaves (which is currently very easy, if things aren't set up
323
# Write the traceback.
324
# If this is a non-4xx IVLEError, get the message and httpcode and
325
# make the error message a bit nicer (but still include the
327
# We also need to special-case IVLEJailError, as we can get another
328
# almost-exception out of it.
330
codename, msg = None, None
332
if exc_type is util.IVLEJailError:
333
msg = exc_value.type_str + ": " + exc_value.message
334
tb = 'Exception information extracted from IVLEJailError:\n'
335
tb += urllib.unquote(exc_value.info)
338
codename, msg = req.get_http_codename(httpcode)
339
except AttributeError:
341
# Override the default message with the supplied one,
343
if hasattr(exc_value, 'message') and exc_value.message is not None:
344
msg = exc_value.message
345
# Prepend the exception type
346
if exc_type != util.IVLEError:
347
msg = exc_type.__name__ + ": " + repr(msg)
349
tb = ''.join(traceback.format_exception(exc_type, exc_value,
353
logging.error('%s\n%s'%(str(msg), tb))
354
# Error messages are only displayed is the user is NOT a student,
355
# or if there has been a problem logging the error message
356
show_errors = (not publicmode) and ((login and \
357
str(role) != "student") or logfail)
358
req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
210
tb = ''.join(traceback.format_exception(exc_type, exc_value,
213
logging.error('%s\n%s'%(str(msg), tb))
215
# Error messages are only displayed is the user is NOT a student,
216
# or if there has been a problem logging the error message
217
show_errors = (not publicmode) and ((login and req.user.admin) or logfail)
218
req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
359
219
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
360
220
<html xmlns="http://www.w3.org/1999/xhtml">
361
221
<head><title>IVLE Internal Server Error</title></head>
363
223
<h1>IVLE Internal Server Error""")
365
if (codename is not None
366
and httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR):
367
req.write(": %s" % cgi.escape(codename))
225
if codename is not None and \
226
httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR:
227
req.write(": %s" % cgi.escape(codename))
370
230
<p>An error has occured which is the fault of the IVLE developers or
371
administration. The developers have been notified.</p>
375
req.write("<p>%s</p>\n" % cgi.escape(msg))
376
if httpcode is not None:
377
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
379
<p>Please report this to <a href="mailto:%s">%s</a> (the system
380
administrator). Include the following information:</p>
381
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
383
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
385
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
386
%cgi.escape(logfile))
387
req.write("</body></html>")
234
req.write("Please report this issue to the server administrators, "
235
"along with the following information.")
237
req.write("Details have been logged for further examination.")
242
req.write("<p>%s</p>\n" % cgi.escape(msg))
243
if httpcode is not None:
244
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
245
req.write("<h2>Debugging information</h2>")
247
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
248
req.write("</body></html>")