42
42
from ivle import util
44
44
from ivle.dispatch.request import Request
45
45
import ivle.webapp.security
46
46
from ivle.webapp.base.plugins import ViewPlugin, PublicViewPlugin
47
from ivle.webapp.errors import HTTPError, Unauthorized
49
def generate_route_mapper(view_plugins, attr):
47
from ivle.webapp.base.xhtml import XHTMLView, XHTMLErrorView
48
from ivle.webapp.errors import HTTPError, Unauthorized, NotFound
50
config = ivle.config.Config()
52
def generate_router(view_plugins, attr):
51
54
Build a Mapper object for doing URL matching using 'routes', based on the
52
55
given plugin registry.
62
65
m.connect(routex, view=view_class, **kwargs_dict)
66
"""Handles a request which may be to anywhere in the site except media.
68
def handler(apachereq):
69
"""Handles an HTTP request.
67
71
Intended to be called by mod_python, as a handler.
69
req: An Apache request object.
71
# Make the request object into an IVLE request which can be passed to apps
76
# Pass the apachereq to error reporter, since ivle req isn't created
78
handle_unknown_exception(apachereq, *sys.exc_info())
79
# Tell Apache not to generate its own errors as well
80
return mod_python.apache.OK
82
# Run the main handler, and catch all exceptions
84
return handler_(req, apachereq)
85
except mod_python.apache.SERVER_RETURN:
86
# An apache error. We discourage these, but they might still happen.
90
handle_unknown_exception(req, *sys.exc_info())
91
# Tell Apache not to generate its own errors as well
92
return mod_python.apache.OK
94
def handler_(req, apachereq):
96
Nested handler function. May raise exceptions. The top-level handler is
97
just used to catch exceptions.
98
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)
100
78
# Hack? Try and get the user login early just in case we throw an error
101
79
# (most likely 404) to stop us seeing not logged in even when we are.
102
80
if not req.publicmode:
106
84
if user and user.valid:
109
conf = ivle.config.Config()
112
87
if req.publicmode:
113
req.mapper = generate_route_mapper(conf.plugin_index[PublicViewPlugin],
88
req.mapper = generate_router(config.plugin_index[PublicViewPlugin],
116
req.mapper = generate_route_mapper(conf.plugin_index[ViewPlugin],
91
req.mapper = generate_router(config.plugin_index[ViewPlugin], 'urls')
119
93
matchdict = req.mapper.match(req.uri)
120
94
if matchdict is not None:
173
154
the IVLE request is created.
175
156
req.content_type = "text/html"
176
logfile = os.path.join(ivle.conf.log_path, 'ivle_error.log')
157
logfile = os.path.join(config['paths']['logs'], 'ivle_error.log')
178
# For some reason, some versions of mod_python have "_server" instead of
179
# "main_server". So we check for both.
181
admin_email = mod_python.apache.main_server.server_admin
182
except AttributeError:
184
admin_email = mod_python.apache._server.server_admin
185
except AttributeError:
160
# XXX: This remains here for ivle.interpret's IVLEErrors. Once we rewrite
161
# fileservice, req.status should always be 500 (ISE) here.
188
163
httpcode = exc_value.httpcode
189
164
req.status = httpcode
190
165
except AttributeError:
192
167
req.status = mod_python.apache.HTTP_INTERNAL_SERVER_ERROR
194
170
publicmode = req.publicmode
195
171
except AttributeError:
220
logging.debug('Logging Unhandled Exception')
222
193
# A "bad" error message. We shouldn't get here unless IVLE
223
194
# misbehaves (which is currently very easy, if things aren't set up
225
196
# Write the traceback.
226
# If this is a non-4xx IVLEError, get the message and httpcode and
227
# make the error message a bit nicer (but still include the
229
# We also need to special-case IVLEJailError, as we can get another
198
# We need to special-case IVLEJailError, as we can get another
230
199
# almost-exception out of it.
232
codename, msg = None, None
234
200
if exc_type is util.IVLEJailError:
235
msg = exc_value.type_str + ": " + exc_value.message
236
201
tb = 'Exception information extracted from IVLEJailError:\n'
237
202
tb += urllib.unquote(exc_value.info)
240
codename, msg = req.get_http_codename(httpcode)
241
except AttributeError:
243
# Override the default message with the supplied one,
245
if hasattr(exc_value, 'message') and exc_value.message is not None:
246
msg = exc_value.message
247
# Prepend the exception type
248
if exc_type != util.IVLEError:
249
msg = exc_type.__name__ + ": " + repr(msg)
251
204
tb = ''.join(traceback.format_exception(exc_type, exc_value,
255
logging.error('%s\n%s'%(str(msg), tb))
207
logging.error('\n' + tb)
256
209
# Error messages are only displayed is the user is NOT a student,
257
210
# or if there has been a problem logging the error message
258
show_errors = (not publicmode) and ((login and \
259
str(role) != "student") or logfail)
211
show_errors = (not publicmode) and ((login and req.user.admin) or logfail)
260
212
req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
261
213
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
262
214
<html xmlns="http://www.w3.org/1999/xhtml">
263
215
<head><title>IVLE Internal Server Error</title></head>
265
<h1>IVLE Internal Server Error""")
267
if (codename is not None
268
and httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR):
269
req.write(": %s" % cgi.escape(codename))
217
<h1>IVLE Internal Server Error</h1>
272
218
<p>An error has occured which is the fault of the IVLE developers or
273
administration. The developers have been notified.</p>
277
req.write("<p>%s</p>\n" % cgi.escape(msg))
278
if httpcode is not None:
279
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
281
<p>Please report this to <a href="mailto:%s">%s</a> (the system
282
administrator). Include the following information:</p>
283
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
222
req.write("Please report this issue to the server administrators, "
223
"along with the following information.")
225
req.write("Details have been logged for further examination.")
229
req.write("<h2>Debugging information</h2>")
285
230
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
287
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
288
%cgi.escape(logfile))
289
231
req.write("</body></html>")