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

« back to all changes in this revision

Viewing changes to ivle/dispatch/__init__.py

  • Committer: mattgiuca
  • Date: 2008-01-12 15:35:53 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:201
Added "test" directory.
Added make_date_test.py, a short script I wrote to test the date format
algorithm committed in the previous revision.

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
3
 
#
4
 
# This program is free software; you can redistribute it and/or modify
5
 
# it under the terms of the GNU General Public License as published by
6
 
# the Free Software Foundation; either version 2 of the License, or
7
 
# (at your option) any later version.
8
 
#
9
 
# This program is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU General Public License
15
 
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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 and delegates to views for authorization,
26
 
then passes the request along to the appropriate view.
27
 
"""
28
 
 
29
 
import sys
30
 
import os
31
 
import os.path
32
 
import urllib
33
 
import cgi
34
 
import traceback
35
 
import logging
36
 
import socket
37
 
import time
38
 
 
39
 
import mod_python
40
 
import routes
41
 
 
42
 
from ivle import util
43
 
import ivle.conf
44
 
from ivle.dispatch.request import Request
45
 
import ivle.webapp.security
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):
50
 
    """
51
 
    Build a Mapper object for doing URL matching using 'routes', based on the
52
 
    given plugin registry.
53
 
    """
54
 
    m = routes.Mapper(explicit=True)
55
 
    for plugin in view_plugins:
56
 
        # Establish a URL pattern for each element of plugin.urls
57
 
        assert hasattr(plugin, 'urls'), "%r does not have any urls" % plugin 
58
 
        for url in getattr(plugin, attr):
59
 
            routex = url[0]
60
 
            view_class = url[1]
61
 
            kwargs_dict = url[2] if len(url) >= 3 else {}
62
 
            m.connect(routex, view=view_class, **kwargs_dict)
63
 
    return m
64
 
 
65
 
def handler(apachereq):
66
 
    """Handles an HTTP request.
67
 
 
68
 
    Intended to be called by mod_python, as a handler.
69
 
 
70
 
    @param apachereq: An Apache request object.
71
 
    """
72
 
    # Make the request object into an IVLE request which can be given to views
73
 
    req = Request(apachereq)
74
 
 
75
 
    # Hack? Try and get the user login early just in case we throw an error
76
 
    # (most likely 404) to stop us seeing not logged in even when we are.
77
 
    if not req.publicmode:
78
 
        user = ivle.webapp.security.get_user_details(req)
79
 
 
80
 
        # Don't set the user if it is disabled or hasn't accepted the ToS.
81
 
        if user and user.valid:
82
 
            req.user = user
83
 
 
84
 
    conf = ivle.config.Config()
85
 
    req.config = conf
86
 
 
87
 
    if req.publicmode:
88
 
        req.mapper = generate_route_mapper(conf.plugin_index[PublicViewPlugin],
89
 
                                           'public_urls')
90
 
    else:
91
 
        req.mapper = generate_route_mapper(conf.plugin_index[ViewPlugin],
92
 
                                           'urls')
93
 
 
94
 
    matchdict = req.mapper.match(req.uri)
95
 
    if matchdict is not None:
96
 
        viewcls = matchdict['view']
97
 
        # Get the remaining arguments, less 'view', 'action' and 'controller'
98
 
        # (The latter two seem to be built-in, and we don't want them).
99
 
        kwargs = matchdict.copy()
100
 
        del kwargs['view']
101
 
        try:
102
 
            # Instantiate the view, which should be a BaseView class
103
 
            view = viewcls(req, **kwargs)
104
 
 
105
 
            # Check that the request (mainly the user) is permitted to access
106
 
            # the view.
107
 
            if not view.authorize(req):
108
 
                raise Unauthorized()
109
 
            # Render the output
110
 
            view.render(req)
111
 
        except HTTPError, e:
112
 
            # A view explicitly raised an HTTP error. Respect it.
113
 
            req.status = e.code
114
 
 
115
 
            # Try to find a custom error view.
116
 
            if hasattr(viewcls, 'get_error_view'):
117
 
                errviewcls = viewcls.get_error_view(e)
118
 
            else:
119
 
                errviewcls = None
120
 
 
121
 
            if errviewcls:
122
 
                errview = errviewcls(req, e)
123
 
                errview.render(req)
124
 
                return req.OK
125
 
            elif e.message:
126
 
                req.write(e.message)
127
 
                return req.OK
128
 
            else:
129
 
                return e.code
130
 
        except Exception, e:
131
 
            # A non-HTTPError appeared. We have an unknown exception. Panic.
132
 
            handle_unknown_exception(req, *sys.exc_info())
133
 
            return req.OK
134
 
        else:
135
 
            req.store.commit()
136
 
            return req.OK
137
 
    else:
138
 
        return req.HTTP_NOT_FOUND # TODO: Prettify.
139
 
 
140
 
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
141
 
    """
142
 
    Given an exception that has just been thrown from IVLE, print its details
143
 
    to the request.
144
 
    This is a full handler. It assumes nothing has been written, and writes a
145
 
    complete HTML page.
146
 
    req: May be EITHER an IVLE req or an Apache req.
147
 
    The handler code may pass an apache req if an exception occurs before
148
 
    the IVLE request is created.
149
 
    """
150
 
    req.content_type = "text/html"
151
 
    logfile = os.path.join(ivle.conf.log_path, 'ivle_error.log')
152
 
    logfail = False
153
 
    try:
154
 
        httpcode = exc_value.httpcode
155
 
        req.status = httpcode
156
 
    except AttributeError:
157
 
        httpcode = None
158
 
        req.status = mod_python.apache.HTTP_INTERNAL_SERVER_ERROR
159
 
    try:
160
 
        publicmode = req.publicmode
161
 
    except AttributeError:
162
 
        publicmode = True
163
 
    try:
164
 
        login = req.user.login
165
 
    except AttributeError:
166
 
        login = None
167
 
    try:
168
 
        role = req.user.role
169
 
    except AttributeError:
170
 
        role = None
171
 
 
172
 
    # Log File
173
 
    try:
174
 
        for h in logging.getLogger().handlers:
175
 
            logging.getLogger().removeHandler(h)
176
 
        logging.basicConfig(level=logging.INFO,
177
 
            format='%(asctime)s %(levelname)s: ' +
178
 
                '(HTTP: ' + str(req.status) +
179
 
                ', Ref: ' + str(login) + '@' +
180
 
                str(socket.gethostname()) + str(req.uri) +
181
 
                ') %(message)s',
182
 
            filename=logfile,
183
 
            filemode='a')
184
 
    except IOError:
185
 
        logfail = True
186
 
 
187
 
    # A "bad" error message. We shouldn't get here unless IVLE
188
 
    # misbehaves (which is currently very easy, if things aren't set up
189
 
    # correctly).
190
 
    # Write the traceback.
191
 
    # If this is a non-4xx IVLEError, get the message and httpcode and
192
 
    # make the error message a bit nicer (but still include the
193
 
    # traceback).
194
 
    # We also need to special-case IVLEJailError, as we can get another
195
 
    # almost-exception out of it.
196
 
 
197
 
    codename, msg = None, None
198
 
 
199
 
    if exc_type is util.IVLEJailError:
200
 
        msg = exc_value.type_str + ": " + exc_value.message
201
 
        tb = 'Exception information extracted from IVLEJailError:\n'
202
 
        tb += urllib.unquote(exc_value.info)
203
 
    else:
204
 
        try:
205
 
            codename, msg = req.get_http_codename(httpcode)
206
 
        except AttributeError:
207
 
            pass
208
 
 
209
 
        tb = ''.join(traceback.format_exception(exc_type, exc_value,
210
 
                                                exc_traceback))
211
 
 
212
 
    logging.error('%s\n%s'%(str(msg), tb))
213
 
 
214
 
    # Error messages are only displayed is the user is NOT a student,
215
 
    # or if there has been a problem logging the error message
216
 
    show_errors = (not publicmode) and ((login and \
217
 
                        str(role) != "student") or logfail)
218
 
    req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"                 
219
 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">                                      
220
 
<html xmlns="http://www.w3.org/1999/xhtml">
221
 
<head><title>IVLE Internal Server Error</title></head>
222
 
<body>
223
 
<h1>IVLE Internal Server Error""")
224
 
    if show_errors:
225
 
        if codename is not None and \
226
 
           httpcode != mod_python.apache.HTTP_INTERNAL_SERVER_ERROR:
227
 
            req.write(": %s" % cgi.escape(codename))
228
 
 
229
 
    req.write("""</h1>
230
 
<p>An error has occured which is the fault of the IVLE developers or
231
 
administrators. """)
232
 
 
233
 
    if logfail:
234
 
        req.write("Please report this issue to the server administrators, "
235
 
                  "along with the following information.")
236
 
    else:
237
 
        req.write("Details have been logged for further examination.")
238
 
    req.write("</p>")
239
 
 
240
 
    if show_errors:
241
 
        if msg is not None:
242
 
            req.write("<p>%s</p>\n" % cgi.escape(msg))
243
 
        if httpcode is not None:
244
 
            req.write("<p>(HTTP error code %d)</p>\n" % httpcode)
245
 
        req.write("<h2>Debugging information</h2>")
246
 
 
247
 
        req.write("<pre>\n%s\n</pre>\n"%cgi.escape(tb))
248
 
    req.write("</body></html>")