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

« back to all changes in this revision

Viewing changes to ivle/dispatch/__init__.py

  • Committer: me at id
  • Date: 2009-01-15 06:11:32 UTC
  • mto: This revision was merged to the branch mainline in revision 1090.
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:branches%2Fstorm:1164
ivle.db: Remove get_enrolment and get_subjects_status. They're unused.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# IVLE - Informatics Virtual Learning Environment
2
 
# Copyright (C) 2007-2009 The University of Melbourne
 
1
# IVLE
 
2
# Copyright (C) 2007-2008 The University of Melbourne
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 
18
 
# Author: Matt Giuca, Will Grant
19
 
 
20
 
"""
21
 
This is a mod_python handler program. The correct way to call it is to have
22
 
Apache send all requests to be handled by the module 'dispatch'.
23
 
 
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.
27
 
"""
 
18
# Module: dispatch
 
19
# Author: Matt Giuca
 
20
# Date: 11/12/2007
 
21
 
 
22
# This is a mod_python handler program. The correct way to call it is to have
 
23
# Apache send all requests to be handled by the module 'dispatch'.
 
24
 
 
25
# Top-level handler. Handles all requests to all pages in IVLE.
 
26
# Handles authentication (not authorization).
 
27
# Then passes the request along to the appropriate ivle app.
28
28
 
29
29
import sys
30
30
import os
35
35
import logging
36
36
import socket
37
37
import time
38
 
import inspect
39
38
 
40
39
import mod_python
41
 
import routes
 
40
from mod_python import apache, Cookie
42
41
 
43
42
from ivle import util
44
43
import ivle.conf
45
44
import ivle.conf.apps
46
 
from ivle.dispatch.request import Request
47
 
from ivle.dispatch import login
48
 
from ivle.webapp.base.plugins import ViewPlugin, ErrorPlugin
49
 
from ivle.webapp.errors import HTTPError
50
45
import apps
 
46
import login
51
47
import html
52
 
 
53
 
# XXX List of plugins, which will eventually be read in from conf
54
 
plugins_HACK = [
55
 
    'ivle.webapp.core#Plugin',
56
 
    'ivle.webapp.base#Plugin',
57
 
    'ivle.webapp.admin.user#Plugin',
58
 
    'ivle.webapp.tutorial#Plugin',
59
 
    'ivle.webapp.admin.subject#Plugin',
60
 
    'ivle.webapp.filesystem.browser#Plugin',
61
 
    'ivle.webapp.filesystem.diff#Plugin',
62
 
    'ivle.webapp.filesystem.svnlog#Plugin',
63
 
    'ivle.webapp.groups#Plugin',
64
 
    'ivle.webapp.console#Plugin',
65
 
    'ivle.webapp.security#Plugin',
66
 
    'ivle.webapp.media#Plugin',
67
 
    'ivle.webapp.forum#Plugin',
68
 
69
 
 
70
 
def generate_route_mapper(view_plugins):
71
 
    """
72
 
    Build a Mapper object for doing URL matching using 'routes', based on the
73
 
    given plugin registry.
74
 
    """
75
 
    m = routes.Mapper(explicit=True)
76
 
    for plugin in view_plugins:
77
 
        # Establish a URL pattern for each element of plugin.urls
78
 
        assert hasattr(plugin, 'urls'), "%r does not have any urls" % plugin 
79
 
        for url in plugin.urls:
80
 
            routex = url[0]
81
 
            view_class = url[1]
82
 
            kwargs_dict = url[2] if len(url) >= 3 else {}
83
 
            m.connect(routex, view=view_class, **kwargs_dict)
84
 
    return m
85
 
 
86
 
def get_plugin(pluginstr):
87
 
    plugin_path, classname = pluginstr.split('#')
88
 
    # Load the plugin module from somewhere in the Python path
89
 
    # (Note that plugin_path is a fully-qualified Python module name).
90
 
    return (plugin_path,
91
 
            getattr(__import__(plugin_path, fromlist=[classname]), classname))
92
 
 
93
 
def get_error_view(req, viewcls):
94
 
    if ErrorPlugin not in req.plugin_index:
95
 
        return
96
 
 
97
 
    error_plugins = req.plugin_index[ErrorPlugin]
98
 
 
99
 
    view_map = {}
100
 
 
101
 
    for plugin in error_plugins:
102
 
        for src in plugin.error_views:
103
 
            view_map[src] = plugin.error_views[src]
104
 
 
105
 
    for cls in inspect.getmro(viewcls):
106
 
        if cls in view_map:
107
 
            return view_map[cls]
 
48
from request import Request
 
49
import plugins.console # XXX: Relies on www/ being in the Python path.
 
50
 
 
51
# List of cookies that IVLE uses (to be removed at logout)
 
52
ivle_cookies = ["ivleforumcookie", "clipboard"]
108
53
 
109
54
def handler(req):
110
55
    """Handles a request which may be to anywhere in the site except media.
121
66
        # yet.
122
67
        handle_unknown_exception(apachereq, *sys.exc_info())
123
68
        # Tell Apache not to generate its own errors as well
124
 
        return mod_python.apache.OK
 
69
        return apache.OK
125
70
 
126
71
    # Run the main handler, and catch all exceptions
127
72
    try:
133
78
    except Exception:
134
79
        handle_unknown_exception(req, *sys.exc_info())
135
80
        # Tell Apache not to generate its own errors as well
136
 
        return mod_python.apache.OK
 
81
        return apache.OK
137
82
 
138
83
def handler_(req, apachereq):
139
84
    """
146
91
    if not req.publicmode:
147
92
        req.user = login.get_user_details(req)
148
93
 
149
 
    ### BEGIN New plugins framework ###
150
 
    # XXX This should be done ONCE per Python process, not per request.
151
 
    # (Wait till WSGI)
152
 
    # XXX No authentication is done here
153
 
    req.plugins = dict([get_plugin(pluginstr) for pluginstr in plugins_HACK])
154
 
    # Index the plugins by base class
155
 
    req.plugin_index = {}
156
 
    for plugin in req.plugins.values():
157
 
        # Getmro returns a tuple of all the super-classes of the plugin
158
 
        for base in inspect.getmro(plugin):
159
 
            if base not in req.plugin_index:
160
 
                req.plugin_index[base] = []
161
 
            req.plugin_index[base].append(plugin)
162
 
    req.reverse_plugins = dict([(v, k) for (k, v) in req.plugins.items()])
163
 
    req.mapper = generate_route_mapper(req.plugin_index[ViewPlugin])
164
 
 
165
 
    matchdict = req.mapper.match(req.uri)
166
 
    if matchdict is not None:
167
 
        viewcls = matchdict['view']
168
 
        # Get the remaining arguments, less 'view', 'action' and 'controller'
169
 
        # (The latter two seem to be built-in, and we don't want them).
170
 
        kwargs = matchdict.copy()
171
 
        del kwargs['view']
172
 
        try:
173
 
            # Instantiate the view, which should be a BaseView class
174
 
            view = viewcls(req, **kwargs)
175
 
            # Render the output
176
 
            view.render(req)
177
 
        except HTTPError, e:
178
 
            # A view explicitly raised an HTTP error. Respect it.
179
 
            req.status = e.code
180
 
 
181
 
            # Try to find a custom error view.
182
 
            errviewcls = get_error_view(req, viewcls)
183
 
            if errviewcls:
184
 
                errview = errviewcls(req, e)
185
 
                errview.render(req)
186
 
                return req.OK
187
 
            else:
188
 
                req.write(e.message)
189
 
                return e.code
190
 
        except Exception, e:
191
 
            # A non-HTTPError appeared. We have an unknown exception. Panic.
192
 
            handle_unknown_exception(req, *sys.exc_info())
193
 
            return req.OK
194
 
        else:
195
 
            req.store.commit()
196
 
            return req.OK
197
 
    ### END New plugins framework ###
198
 
 
199
94
    # Check req.app to see if it is valid. 404 if not.
200
95
    if req.app is not None and req.app not in ivle.conf.apps.app_url:
201
 
        req.throw_error(Request.HTTP_NOT_FOUND,
202
 
            "There is no application called %s." % repr(req.app))
 
96
        # Maybe it is a special app!
 
97
        if req.app == 'logout':
 
98
            logout(req)
 
99
        else:
 
100
            req.throw_error(Request.HTTP_NOT_FOUND,
 
101
                "There is no application called %s." % repr(req.app))
203
102
 
204
103
    # Special handling for public mode - only allow the public app, call it
205
104
    # and get out.
262
161
 
263
162
    # When done, write out the HTML footer if the app has requested it
264
163
    if req.write_html_head_foot:
 
164
        # Show the console if required
 
165
        if logged_in and app.useconsole:
 
166
            plugins.console.present(req, windowpane=True)
265
167
        html.write_html_foot(req)
266
168
 
267
169
    # Note: Apache will not write custom HTML error messages here.
268
170
    # Use req.throw_error to do that.
269
171
    return req.OK
270
172
 
 
173
def logout(req):
 
174
    """Log out the current user (if any) by destroying the session state.
 
175
    Then redirect to the top-level IVLE page."""
 
176
    session = req.get_session()
 
177
    session.invalidate()
 
178
    session.delete()
 
179
    # Invalidates all IVLE cookies
 
180
    all_cookies = Cookie.get_cookies(req)
 
181
    for cookie in all_cookies:
 
182
        if cookie in ivle_cookies:
 
183
            req.add_cookie(Cookie.Cookie(cookie,'',expires=1,path='/'))
 
184
    req.throw_redirect(util.make_path('')) 
 
185
 
271
186
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
272
187
    """
273
188
    Given an exception that has just been thrown from IVLE, print its details
285
200
    # For some reason, some versions of mod_python have "_server" instead of
286
201
    # "main_server". So we check for both.
287
202
    try:
288
 
        admin_email = mod_python.apache.main_server.server_admin
 
203
        admin_email = apache.main_server.server_admin
289
204
    except AttributeError:
290
205
        try:
291
 
            admin_email = mod_python.apache._server.server_admin
 
206
            admin_email = apache._server.server_admin
292
207
        except AttributeError:
293
208
            admin_email = ""
294
209
    try:
296
211
        req.status = httpcode
297
212
    except AttributeError:
298
213
        httpcode = None
299
 
        req.status = mod_python.apache.HTTP_INTERNAL_SERVER_ERROR
300
 
    try:
301
 
        publicmode = req.publicmode
302
 
    except AttributeError:
303
 
        publicmode = True
 
214
        req.status = apache.HTTP_INTERNAL_SERVER_ERROR
304
215
    try:
305
216
        login = req.user.login
306
217
    except AttributeError:
307
218
        login = None
308
 
    try:
309
 
        role = req.user.role
310
 
    except AttributeError:
311
 
        role = None
312
219
 
313
220
    # Log File
314
221
    try:
404
311
 
405
312
        # Logging
406
313
        logging.error('%s\n%s'%(str(msg), tb))
407
 
        # Error messages are only displayed is the user is NOT a student,
408
 
        # or if there has been a problem logging the error message
409
 
        show_errors = (not publicmode) and ((login and \
410
 
                            str(role) != "student") or logfail)
 
314
 
411
315
        req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"                 
412
316
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">                                      
413
317
<html xmlns="http://www.w3.org/1999/xhtml">
414
318
<head><title>IVLE Internal Server Error</title></head>
415
319
<body>
416
320
<h1>IVLE Internal Server Error""")
417
 
        if (show_errors):
418
 
            if (codename is not None
419
 
                        and httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR):
420
 
                req.write(": %s" % cgi.escape(codename))
421
 
        
 
321
        if (codename is not None
 
322
            and httpcode != apache.HTTP_INTERNAL_SERVER_ERROR):
 
323
            req.write(": %s" % cgi.escape(codename))
422
324
        req.write("""</h1>
423
325
<p>An error has occured which is the fault of the IVLE developers or
424
 
administration. The developers have been notified.</p>
 
326
administration.</p>
425
327
""")
426
 
        if (show_errors):
427
 
            if msg is not None:
428
 
                req.write("<p>%s</p>\n" % cgi.escape(msg))
429
 
            if httpcode is not None:
430
 
                req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
431
 
            req.write("""
432
 
    <p>Please report this to <a href="mailto:%s">%s</a> (the system
433
 
    administrator). Include the following information:</p>
434
 
    """ % (cgi.escape(admin_email), cgi.escape(admin_email)))
 
328
        if msg is not None:
 
329
            req.write("<p>%s</p>\n" % cgi.escape(msg))
 
330
        if httpcode is not None:
 
331
            req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
 
332
        req.write("""
 
333
<p>Please report this to <a href="mailto:%s">%s</a> (the system
 
334
administrator). Include the following information:</p>
 
335
""" % (cgi.escape(admin_email), cgi.escape(admin_email)))
435
336
 
436
 
            req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
437
 
            if logfail:
438
 
                req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
439
 
                    %cgi.escape(logfile))
 
337
        req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
 
338
        if logfail:
 
339
            req.write("<p>Warning: Could not open Error Log: '%s'</p>\n"
 
340
                %cgi.escape(logfile))
440
341
        req.write("</body></html>")