62
49
# Make the request object into an IVLE request which can be passed to apps
65
req = Request(req, html.write_html_head)
67
# Pass the apachereq to error reporter, since ivle req isn't created
69
handle_unknown_exception(apachereq, *sys.exc_info())
70
# Tell Apache not to generate its own errors as well
73
# Run the main handler, and catch all exceptions
75
return handler_(req, apachereq)
76
except mod_python.apache.SERVER_RETURN:
77
# An apache error. We discourage these, but they might still happen.
81
handle_unknown_exception(req, *sys.exc_info())
82
# Tell Apache not to generate its own errors as well
85
def handler_(req, apachereq):
87
Nested handler function. May raise exceptions. The top-level handler is
88
just used to catch exceptions.
89
Takes both an IVLE request and an Apache req.
91
# Hack? Try and get the user login early just in case we throw an error
92
# (most likely 404) to stop us seeing not logged in even when we are.
93
if not req.publicmode:
94
req.user = login.get_user_details(req)
51
req = Request(req, html.write_html_head)
96
53
# Check req.app to see if it is valid. 404 if not.
97
54
if req.app is not None and req.app not in conf.apps.app_url:
99
56
if req.app == 'logout':
102
req.throw_error(Request.HTTP_NOT_FOUND,
103
"There is no application called %s." % repr(req.app))
105
# Special handling for public mode - only allow the public app, call it
107
# NOTE: This will not behave correctly if the public app uses
108
# write_html_head_foot, but "serve" does not.
110
if req.app != conf.apps.public_app:
111
req.throw_error(Request.HTTP_FORBIDDEN,
112
"This application is not available on the public site.")
113
app = conf.apps.app_url[conf.apps.public_app]
114
apps.call_app(app.dir, req)
59
# TODO: Nicer 404 message?
60
req.throw_error(Request.HTTP_NOT_FOUND)
117
62
# app is the App object for the chosen app
118
63
if req.app is None:
119
app = conf.apps.app_url[conf.apps.default_app]
64
app = conf.apps.app_url[conf.default_app]
121
66
app = conf.apps.app_url[req.app]
123
68
# Check if app requires auth. If so, perform authentication and login.
124
# This will either return a User object, None, or perform a redirect
125
# which we will not catch here.
126
69
if app.requireauth:
127
req.user = login.login(req)
128
logged_in = req.user is not None
70
req.username = login.login(req)
71
logged_in = req.username is not None
130
req.user = login.get_user_details(req)
73
req.username = login.get_username(req)
134
# Keep the user's session alive by writing to the session object.
135
# req.get_session().save()
136
# Well, it's a fine idea, but it creates considerable grief in the
137
# concurrent update department, so instead, we'll just make the
138
# sessions not time out.
140
77
# If user did not specify an app, HTTP redirect to default app and
142
79
if req.app is None:
143
req.throw_redirect(util.make_path(conf.apps.default_app))
80
req.throw_redirect(util.make_path(conf.default_app))
145
82
# Set the default title to the app's tab name, if any. Otherwise URL
177
110
session = req.get_session()
178
111
session.invalidate()
180
# Invalidates all IVLE cookies
181
all_cookies = Cookie.get_cookies(req)
182
for cookie in all_cookies:
183
if cookie in ivle_cookies:
184
req.add_cookie(Cookie.Cookie(cookie,'',expires=1,path='/'))
185
req.throw_redirect(util.make_path(''))
187
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
189
Given an exception that has just been thrown from IVLE, print its details
191
This is a full handler. It assumes nothing has been written, and writes a
193
req: May be EITHER an IVLE req or an Apache req.
194
IVLE reqs may have the HTML head/foot written (on a 400 error), but
195
the handler code may pass an apache req if an exception occurs before
196
the IVLE request is created.
198
req.content_type = "text/html"
199
logfile = os.path.join(conf.conf.log_path, 'ivle_error.log')
201
# For some reason, some versions of mod_python have "_server" instead of
202
# "main_server". So we check for both.
204
admin_email = apache.main_server.server_admin
205
except AttributeError:
207
admin_email = apache._server.server_admin
208
except AttributeError:
211
httpcode = exc_value.httpcode
212
req.status = httpcode
213
except AttributeError:
215
req.status = apache.HTTP_INTERNAL_SERVER_ERROR
217
login = req.user.login
218
except AttributeError:
223
logging.basicConfig(level=logging.INFO,
224
format='%(asctime)s %(levelname)s: ' +
225
'(HTTP: ' + str(req.status) +
226
', Ref: ' + str(login) + '@' +
227
str(socket.gethostname()) + str(req.uri) +
233
logging.debug('Logging Unhandled Exception')
235
# We handle 3 types of error.
236
# IVLEErrors with 4xx response codes (client error).
237
# IVLEErrors with 5xx response codes (handled server error).
238
# Other exceptions (unhandled server error).
239
# IVLEErrors should not have other response codes than 4xx or 5xx
240
# (eg. throw_redirect should have been used for 3xx codes).
241
# Therefore, that is treated as an unhandled error.
243
if (exc_type == util.IVLEError and httpcode >= 400
244
and httpcode <= 499):
245
# IVLEErrors with 4xx response codes are client errors.
246
# Therefore, these have a "nice" response (we even coat it in the IVLE
249
req.write_html_head_foot = True
250
req.write('<div id="ivle_padding">\n')
252
codename, msg = req.get_http_codename(httpcode)
253
except AttributeError:
254
codename, msg = None, None
255
# Override the default message with the supplied one,
257
if exc_value.message is not None:
258
msg = exc_value.message
259
if codename is not None:
260
req.write("<h1>Error: %s</h1>\n" % cgi.escape(codename))
262
req.write("<h1>Error</h1>\n")
264
req.write("<p>%s</p>\n" % cgi.escape(msg))
266
req.write("<p>An unknown error occured.</p>\n")
269
logging.info(str(msg))
271
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
273
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
274
%cgi.escape(logfile))
275
req.write('</div>\n')
277
# A "bad" error message. We shouldn't get here unless IVLE
278
# misbehaves (which is currently very easy, if things aren't set up
280
# Write the traceback.
281
# If this is a non-4xx IVLEError, get the message and httpcode and
282
# make the error message a bit nicer (but still include the
284
# We also need to special-case IVLEJailError, as we can get another
285
# almost-exception out of it.
287
codename, msg = None, None
289
if exc_type is util.IVLEJailError:
290
msg = exc_value.type_str + ": " + exc_value.message
291
tb = 'Exception information extracted from IVLEJailError:\n'
292
tb += urllib.unquote(exc_value.info)
295
codename, msg = req.get_http_codename(httpcode)
296
except AttributeError:
298
# Override the default message with the supplied one,
300
if hasattr(exc_value, 'message') and exc_value.message is not None:
301
msg = exc_value.message
302
# Prepend the exception type
303
if exc_type != util.IVLEError:
304
msg = exc_type.__name__ + ": " + msg
306
tb = ''.join(traceback.format_exception(exc_type, exc_value,
310
logging.error('%s\n%s'%(str(msg), tb))
313
<head><title>IVLE Internal Server Error</title></head>
315
<h1>IVLE Internal Server Error""")
316
if (codename is not None
317
and httpcode != apache.HTTP_INTERNAL_SERVER_ERROR):
318
req.write(": %s" % cgi.escape(codename))
320
<p>An error has occured which is the fault of the IVLE developers or
324
req.write("<p>%s</p>\n" % cgi.escape(msg))
325
if httpcode is not None:
326
req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
328
<p>Please report this to <a href="mailto:%s">%s</a> (the system
329
administrator). Include the following information:</p>
330
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
332
req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
334
req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
335
%cgi.escape(logfile))
113
req.throw_redirect(util.make_path(''))