55
49
# Make the request object into an IVLE request which can be passed to apps
58
req = Request(req, html.write_html_head)
60
# Pass the apachereq to error reporter, since ivle req isn't created
62
handle_unknown_exception(apachereq, *sys.exc_info())
63
# Tell Apache not to generate its own errors as well
66
# Run the main handler, and catch all exceptions
68
return handler_(req, apachereq)
69
except mod_python.apache.SERVER_RETURN:
70
# An apache error. We discourage these, but they might still happen.
74
handle_unknown_exception(req, *sys.exc_info())
75
# Tell Apache not to generate its own errors as well
78
def handler_(req, apachereq):
80
Nested handler function. May raise exceptions. The top-level handler is
81
just used to catch exceptions.
82
Takes both an IVLE request and an Apache req.
51
req = Request(req, html.write_html_head)
84
53
# Check req.app to see if it is valid. 404 if not.
85
54
if req.app is not None and req.app not in conf.apps.app_url:
86
55
# Maybe it is a special app!
87
56
if req.app == 'logout':
90
req.throw_error(Request.HTTP_NOT_FOUND,
91
"There is no application called %s." % repr(req.app))
59
# TODO: Nicer 404 message?
60
req.throw_error(Request.HTTP_NOT_FOUND)
93
62
# Special handling for public mode - just call public app and get out
94
63
# NOTE: This will not behave correctly if the public app uses
105
74
app = conf.apps.app_url[req.app]
107
76
# Check if app requires auth. If so, perform authentication and login.
108
# This will either return a User object, None, or perform a redirect
109
# which we will not catch here.
110
77
if app.requireauth:
111
req.user = login.login(req)
112
logged_in = req.user is not None
78
req.username = login.login(req)
79
logged_in = req.username is not None
114
req.user = login.get_user_details(req)
81
req.username = login.get_username(req)
118
# Keep the user's session alive by writing to the session object.
119
# req.get_session().save()
120
# Well, it's a fine idea, but it creates considerable grief in the
121
# concurrent update department, so instead, we'll just make the
122
# sessions not time out.
124
85
# If user did not specify an app, HTTP redirect to default app and
126
87
if req.app is None:
162
118
session = req.get_session()
163
119
session.invalidate()
165
req.add_cookie(forumutil.invalidated_forum_cookie())
166
121
req.throw_redirect(util.make_path(''))
168
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
170
Given an exception that has just been thrown from IVLE, print its details
172
This is a full handler. It assumes nothing has been written, and writes a
174
req: May be EITHER an IVLE req or an Apache req.
175
IVLE reqs may have the HTML head/foot written (on a 400 error), but
176
the handler code may pass an apache req if an exception occurs before
177
the IVLE request is created.
179
req.content_type = "text/html"
180
# For some reason, some versions of mod_python have "_server" instead of
181
# "main_server". So we check for both.
183
admin_email = apache.main_server.server_admin
184
except AttributeError:
186
admin_email = apache._server.server_admin
187
except AttributeError:
190
httpcode = exc_value.httpcode
191
req.status = httpcode
192
except AttributeError:
194
req.status = apache.HTTP_INTERNAL_SERVER_ERROR
195
# We handle 3 types of error.
196
# IVLEErrors with 4xx response codes (client error).
197
# IVLEErrors with 5xx response codes (handled server error).
198
# Other exceptions (unhandled server error).
199
# IVLEErrors should not have other response codes than 4xx or 5xx
200
# (eg. throw_redirect should have been used for 3xx codes).
201
# Therefore, that is treated as an unhandled error.
203
if (exc_type == util.IVLEError and httpcode >= 400
204
and httpcode <= 499):
205
# IVLEErrors with 4xx response codes are client errors.
206
# Therefore, these have a "nice" response (we even coat it in the IVLE
208
req.write_html_head_foot = True
209
req.write('<div id="ivle_padding">\n')
211
codename, msg = req.get_http_codename(httpcode)
212
except AttributeError:
213
codename, msg = None, None
214
# Override the default message with the supplied one,
216
if exc_value.message is not None:
217
msg = exc_value.message
218
if codename is not None:
219
req.write("<h1>Error: %s</h1>\n" % cgi.escape(codename))
221
req.write("<h1>Error</h1>\n")
223
req.write("<p>%s</p>\n" % cgi.escape(msg))
225
req.write("<p>An unknown error occured.</p>\n")
226
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
227
req.write('</div>\n')
229
# A "bad" error message. We shouldn't get here unless IVLE
230
# misbehaves (which is currently very easy, if things aren't set up
232
# Write the traceback.
233
# If this is a non-4xx IVLEError, get the message and httpcode and
234
# make the error message a bit nicer (but still include the
236
# We also need to special-case IVLEJailError, as we can get another
237
# almost-exception out of it.
239
codename, msg = None, None
241
if exc_type is util.IVLEJailError:
242
msg = exc_value.type_str + ": " + exc_value.message
243
tb = 'Exception information extracted from IVLEJailError:\n'
244
tb += urllib.unquote(exc_value.info)
247
codename, msg = req.get_http_codename(httpcode)
248
except AttributeError:
250
# Override the default message with the supplied one,
252
if hasattr(exc_value, 'message') and exc_value.message is not None:
253
msg = exc_value.message
254
# Prepend the exception type
255
if exc_type != util.IVLEError:
256
msg = exc_type.__name__ + ": " + msg
258
tb = ''.join(traceback.format_exception(exc_type, exc_value,
262
<head><title>IVLE Internal Server Error</title></head>
264
<h1>IVLE Internal Server Error""")
265
if (codename is not None
266
and httpcode != apache.HTTP_INTERNAL_SERVER_ERROR):
267
req.write(": %s" % cgi.escape(codename))
269
<p>An error has occured which is the fault of the IVLE developers or
273
req.write("<p>%s</p>\n" % cgi.escape(msg))
274
if httpcode is not None:
275
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
277
<p>Please report this to <a href="mailto:%s">%s</a> (the system
278
administrator). Include the following information:</p>
279
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
282
req.write(cgi.escape(tb))
283
req.write("</pre>\n</body>\n")