~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/dispatch/__init__.py

  • Committer: David Coles
  • Date: 2009-08-13 06:23:19 UTC
  • Revision ID: coles.david@gmail.com-20090813062319-nczwvqcr5mzoskh5
Degrade text editor to textarea in KHTML

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
Apache send all requests to be handled by the module 'dispatch'.
23
23
 
24
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.
 
25
Handles authentication and delegates to views for authorization,
 
26
then passes the request along to the appropriate view.
27
27
"""
28
28
 
29
29
import sys
40
40
import routes
41
41
 
42
42
from ivle import util
43
 
import ivle.conf
 
43
import ivle.config
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
48
 
 
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
 
49
 
 
50
config = ivle.config.Config()
 
51
 
 
52
def generate_router(view_plugins, attr):
50
53
    """
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)
63
66
    return m
64
67
 
65
 
def handler(req):
66
 
    """Handles a request which may be to anywhere in the site except media.
 
68
def handler(apachereq):
 
69
    """Handles an HTTP request.
 
70
 
67
71
    Intended to be called by mod_python, as a handler.
68
72
 
69
 
    req: An Apache request object.
70
 
    """
71
 
    # Make the request object into an IVLE request which can be passed to apps
72
 
    apachereq = req
73
 
    try:
74
 
        req = Request(req)
75
 
    except Exception:
76
 
        # Pass the apachereq to error reporter, since ivle req isn't created
77
 
        # yet.
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
81
 
 
82
 
    # Run the main handler, and catch all exceptions
83
 
    try:
84
 
        return handler_(req, apachereq)
85
 
    except mod_python.apache.SERVER_RETURN:
86
 
        # An apache error. We discourage these, but they might still happen.
87
 
        # Just raise up.
88
 
        raise
89
 
    except Exception:
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
93
 
 
94
 
def handler_(req, apachereq):
95
 
    """
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.
99
 
    """
 
73
    @param apachereq: An Apache request object.
 
74
    """
 
75
    # Make the request object into an IVLE request which can be given to views
 
76
    req = Request(apachereq, config)
 
77
 
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:
107
85
            req.user = user
108
86
 
109
 
    conf = ivle.config.Config()
110
 
    req.config = conf
111
 
 
112
87
    if req.publicmode:
113
 
        req.mapper = generate_route_mapper(conf.plugin_index[PublicViewPlugin],
114
 
                                           'public_urls')
 
88
        req.mapper = generate_router(config.plugin_index[PublicViewPlugin],
 
89
                                    'public_urls')
115
90
    else:
116
 
        req.mapper = generate_route_mapper(conf.plugin_index[ViewPlugin],
117
 
                                           'urls')
 
91
        req.mapper = generate_router(config.plugin_index[ViewPlugin], 'urls')
118
92
 
119
93
    matchdict = req.mapper.match(req.uri)
120
94
    if matchdict is not None:
141
115
            if hasattr(viewcls, 'get_error_view'):
142
116
                errviewcls = viewcls.get_error_view(e)
143
117
            else:
144
 
                errviewcls = None
 
118
                errviewcls = XHTMLView.get_error_view(e)
145
119
 
146
120
            if errviewcls:
147
121
                errview = errviewcls(req, e)
152
126
                return req.OK
153
127
            else:
154
128
                return e.code
 
129
        except mod_python.apache.SERVER_RETURN:
 
130
            # A mod_python-specific Apache error.
 
131
            # XXX: We need to raise these because req.throw_error() uses them.
 
132
            # Remove this after Google Code issue 117 is fixed.
 
133
            raise
155
134
        except Exception, e:
156
135
            # A non-HTTPError appeared. We have an unknown exception. Panic.
157
136
            handle_unknown_exception(req, *sys.exc_info())
160
139
            req.store.commit()
161
140
            return req.OK
162
141
    else:
163
 
        return req.HTTP_NOT_FOUND # TODO: Prettify.
 
142
        req.status = 404
 
143
        XHTMLErrorView(req, NotFound()).render(req)
 
144
        return req.OK
164
145
 
165
146
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
166
147
    """
173
154
    the IVLE request is created.
174
155
    """
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')
177
158
    logfail = False
178
 
    # For some reason, some versions of mod_python have "_server" instead of
179
 
    # "main_server". So we check for both.
180
 
    try:
181
 
        admin_email = mod_python.apache.main_server.server_admin
182
 
    except AttributeError:
183
 
        try:
184
 
            admin_email = mod_python.apache._server.server_admin
185
 
        except AttributeError:
186
 
            admin_email = ""
 
159
 
 
160
    # XXX: This remains here for ivle.interpret's IVLEErrors. Once we rewrite
 
161
    #      fileservice, req.status should always be 500 (ISE) here.
187
162
    try:
188
163
        httpcode = exc_value.httpcode
189
164
        req.status = httpcode
190
165
    except AttributeError:
191
166
        httpcode = None
192
167
        req.status = mod_python.apache.HTTP_INTERNAL_SERVER_ERROR
 
168
 
193
169
    try:
194
170
        publicmode = req.publicmode
195
171
    except AttributeError:
198
174
        login = req.user.login
199
175
    except AttributeError:
200
176
        login = None
201
 
    try:
202
 
        role = req.user.role
203
 
    except AttributeError:
204
 
        role = None
205
177
 
206
178
    # Log File
207
179
    try:
217
189
            filemode='a')
218
190
    except IOError:
219
191
        logfail = True
220
 
    logging.debug('Logging Unhandled Exception')
221
192
 
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
224
195
    # correctly).
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
228
 
    # traceback).
229
 
    # We also need to special-case IVLEJailError, as we can get another
 
197
 
 
198
    # We need to special-case IVLEJailError, as we can get another
230
199
    # almost-exception out of it.
231
 
 
232
 
    codename, msg = None, None
233
 
 
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)
238
203
    else:
239
 
        try:
240
 
            codename, msg = req.get_http_codename(httpcode)
241
 
        except AttributeError:
242
 
            pass
243
 
        # Override the default message with the supplied one,
244
 
        # if available.
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)
250
 
 
251
204
        tb = ''.join(traceback.format_exception(exc_type, exc_value,
252
205
                                                exc_traceback))
253
206
 
254
 
    # Logging
255
 
    logging.error('%s\n%s'%(str(msg), tb))
 
207
    logging.error('\n' + tb)
 
208
 
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>
264
216
<body>
265
 
<h1>IVLE Internal Server Error""")
266
 
    if (show_errors):
267
 
        if (codename is not None
268
 
                    and httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR):
269
 
            req.write(": %s" % cgi.escape(codename))
270
 
 
271
 
    req.write("""</h1>
 
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>
274
 
""")
275
 
    if (show_errors):
276
 
        if msg is not None:
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)
280
 
        req.write("""
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)))
284
 
 
 
219
administrators. """)
 
220
 
 
221
    if logfail:
 
222
        req.write("Please report this issue to the server administrators, "
 
223
                  "along with the following information.")
 
224
    else:
 
225
        req.write("Details have been logged for further examination.")
 
226
    req.write("</p>")
 
227
 
 
228
    if show_errors:
 
229
        req.write("<h2>Debugging information</h2>")
285
230
        req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
286
 
        if logfail:
287
 
            req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
288
 
                %cgi.escape(logfile))
289
231
    req.write("</body></html>")