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

1099 by matt.giuca
dispatch/__init__.py: Updated header comments to new policy, updated copyright.
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2009 The University of Melbourne
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
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
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
18
# Author: Matt Giuca, Will Grant
1099 by matt.giuca
dispatch/__init__.py: Updated header comments to new policy, updated copyright.
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
"""
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
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
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
40
import routes
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
41
42
from ivle import util
43
import ivle.conf
1099.1.5 by William Grant
ivle.dispatch{,.{login,request}}: Fix mod_python imports to ensure that we can
44
from ivle.dispatch.request import Request
1099.1.161 by William Grant
Move ivle.dispatch.login.get_user_details() to ivle.webapp.security.
45
import ivle.webapp.security
1099.1.146 by William Grant
Add support for public mode views to the new framework.
46
from ivle.webapp.base.plugins import ViewPlugin, PublicViewPlugin
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
47
from ivle.webapp.errors import HTTPError, Unauthorized
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
48
1099.1.146 by William Grant
Add support for public mode views to the new framework.
49
def generate_route_mapper(view_plugins, attr):
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
50
    """
51
    Build a Mapper object for doing URL matching using 'routes', based on the
1099.1.59 by William Grant
Provide a media file framework in ivle.webapp.media.
52
    given plugin registry.
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
53
    """
1099.1.13 by William Grant
ivle.dispatch: Throw the routes mapper into req.mapper, and make it explicit.
54
    m = routes.Mapper(explicit=True)
1099.1.72 by Nick Chadwick
Dispatch now generates an index for each plugin type, allowing plugins to
55
    for plugin in view_plugins:
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
56
        # Establish a URL pattern for each element of plugin.urls
1099.1.72 by Nick Chadwick
Dispatch now generates an index for each plugin type, allowing plugins to
57
        assert hasattr(plugin, 'urls'), "%r does not have any urls" % plugin 
1099.1.146 by William Grant
Add support for public mode views to the new framework.
58
        for url in getattr(plugin, attr):
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
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
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
65
def handler(req):
66
    """Handles a request which may be to anywhere in the site except media.
67
    Intended to be called by mod_python, as a handler.
68
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:
1099.1.160 by William Grant
Remove HTML support from ivle.request.Request.
74
        req = Request(req)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
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
1099.1.4 by William Grant
ivle.dispatch: Move some imports around so that it can be imported from
80
        return mod_python.apache.OK
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
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
1099.1.4 by William Grant
ivle.dispatch: Move some imports around so that it can be imported from
92
        return mod_python.apache.OK
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
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
    """
100
    # Hack? Try and get the user login early just in case we throw an error
101
    # (most likely 404) to stop us seeing not logged in even when we are.
102
    if not req.publicmode:
1099.1.161 by William Grant
Move ivle.dispatch.login.get_user_details() to ivle.webapp.security.
103
        user = ivle.webapp.security.get_user_details(req)
1099.1.121 by William Grant
Don't set req.user unless the login in the session specifies a valid user.
104
105
        # Don't set the user if it is disabled or hasn't accepted the ToS.
1099.1.123 by William Grant
Don't crash when not authenticated, and display an error on password absence.
106
        if user and user.valid:
1099.1.121 by William Grant
Don't set req.user unless the login in the session specifies a valid user.
107
            req.user = user
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
108
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
109
    conf = ivle.config.Config()
110
    req.config = conf
111
1099.1.146 by William Grant
Add support for public mode views to the new framework.
112
    if req.publicmode:
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
113
        req.mapper = generate_route_mapper(conf.plugin_index[PublicViewPlugin],
1099.1.146 by William Grant
Add support for public mode views to the new framework.
114
                                           'public_urls')
115
    else:
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
116
        req.mapper = generate_route_mapper(conf.plugin_index[ViewPlugin],
1099.1.146 by William Grant
Add support for public mode views to the new framework.
117
                                           'urls')
1099.1.59 by William Grant
Provide a media file framework in ivle.webapp.media.
118
1099.1.13 by William Grant
ivle.dispatch: Throw the routes mapper into req.mapper, and make it explicit.
119
    matchdict = req.mapper.match(req.uri)
1099.1.1 by Matt Giuca
Began implementing new dispatch framework (with Will Grant and Nick Chadwick).
120
    if matchdict is not None:
121
        viewcls = matchdict['view']
122
        # Get the remaining arguments, less 'view', 'action' and 'controller'
123
        # (The latter two seem to be built-in, and we don't want them).
124
        kwargs = matchdict.copy()
125
        del kwargs['view']
1099.1.84 by William Grant
Handle HTTPErrors nicely in the new framework. Currently there is no facility
126
        try:
1099.1.86 by William Grant
Also capture the view object creation in the new framework's exception handler.
127
            # Instantiate the view, which should be a BaseView class
128
            view = viewcls(req, **kwargs)
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
129
130
            # Check that the request (mainly the user) is permitted to access
131
            # the view.
132
            if not view.authorize(req):
133
                raise Unauthorized()
1099.1.86 by William Grant
Also capture the view object creation in the new framework's exception handler.
134
            # Render the output
1099.1.84 by William Grant
Handle HTTPErrors nicely in the new framework. Currently there is no facility
135
            view.render(req)
136
        except HTTPError, e:
137
            # A view explicitly raised an HTTP error. Respect it.
138
            req.status = e.code
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
139
140
            # Try to find a custom error view.
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
141
            if hasattr(viewcls, 'get_error_view'):
142
                errviewcls = viewcls.get_error_view(e)
143
            else:
144
                errviewcls = None
145
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
146
            if errviewcls:
147
                errview = errviewcls(req, e)
148
                errview.render(req)
149
                return req.OK
1099.1.135 by William Grant
In the new framework handler, either write the exception message or use
150
            elif e.message:
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
151
                req.write(e.message)
1099.1.135 by William Grant
In the new framework handler, either write the exception message or use
152
                return req.OK
153
            else:
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
154
                return e.code
1099.1.84 by William Grant
Handle HTTPErrors nicely in the new framework. Currently there is no facility
155
        except Exception, e:
156
            # A non-HTTPError appeared. We have an unknown exception. Panic.
157
            handle_unknown_exception(req, *sys.exc_info())
1099.1.88 by William Grant
Make sure that we don't use the old framework if the new framework crashes.
158
            return req.OK
1099.1.84 by William Grant
Handle HTTPErrors nicely in the new framework. Currently there is no facility
159
        else:
160
            req.store.commit()
161
            return req.OK
1099.1.149 by William Grant
Remove most of the remaining legacy app glue from dispatch. Only the stuff
162
    else:
1099.1.153 by William Grant
Old dispatch is dead - drop www/, old bits of ivle.dispatch, ivle.conf.apps.
163
        return req.HTTP_NOT_FOUND # TODO: Prettify.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
164
165
def handle_unknown_exception(req, exc_type, exc_value, exc_traceback):
166
    """
167
    Given an exception that has just been thrown from IVLE, print its details
168
    to the request.
169
    This is a full handler. It assumes nothing has been written, and writes a
170
    complete HTML page.
171
    req: May be EITHER an IVLE req or an Apache req.
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
172
    The handler code may pass an apache req if an exception occurs before
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
173
    the IVLE request is created.
174
    """
175
    req.content_type = "text/html"
176
    logfile = os.path.join(ivle.conf.log_path, 'ivle_error.log')
177
    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:
1099.1.4 by William Grant
ivle.dispatch: Move some imports around so that it can be imported from
181
        admin_email = mod_python.apache.main_server.server_admin
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
182
    except AttributeError:
183
        try:
1099.1.4 by William Grant
ivle.dispatch: Move some imports around so that it can be imported from
184
            admin_email = mod_python.apache._server.server_admin
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
185
        except AttributeError:
186
            admin_email = ""
187
    try:
188
        httpcode = exc_value.httpcode
189
        req.status = httpcode
190
    except AttributeError:
191
        httpcode = None
1099.1.4 by William Grant
ivle.dispatch: Move some imports around so that it can be imported from
192
        req.status = mod_python.apache.HTTP_INTERNAL_SERVER_ERROR
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
193
    try:
1087 by chadnickbok
Fixes Issue #3
194
        publicmode = req.publicmode
195
    except AttributeError:
1088 by chadnickbok
Fixed an issue with my previous patch to this file. Now, if
196
        publicmode = True
1087 by chadnickbok
Fixes Issue #3
197
    try:
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
198
        login = req.user.login
199
    except AttributeError:
200
        login = None
1087 by chadnickbok
Fixes Issue #3
201
    try:
202
        role = req.user.role
203
    except AttributeError:
204
        role = None
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
205
206
    # Log File
207
    try:
208
        for h in logging.getLogger().handlers:
209
            logging.getLogger().removeHandler(h)
210
        logging.basicConfig(level=logging.INFO,
211
            format='%(asctime)s %(levelname)s: ' +
212
                '(HTTP: ' + str(req.status) +
213
                ', Ref: ' + str(login) + '@' +
214
                str(socket.gethostname()) + str(req.uri) +
215
                ') %(message)s',
216
            filename=logfile,
217
            filemode='a')
218
    except IOError:
219
        logfail = True
220
    logging.debug('Logging Unhandled Exception')
221
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
222
    # A "bad" error message. We shouldn't get here unless IVLE
223
    # misbehaves (which is currently very easy, if things aren't set up
224
    # correctly).
225
    # 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
230
    # almost-exception out of it.
231
232
    codename, msg = None, None
233
234
    if exc_type is util.IVLEJailError:
235
        msg = exc_value.type_str + ": " + exc_value.message
236
        tb = 'Exception information extracted from IVLEJailError:\n'
237
        tb += urllib.unquote(exc_value.info)
238
    else:
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
239
        try:
240
            codename, msg = req.get_http_codename(httpcode)
241
        except AttributeError:
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
242
            pass
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
243
        # Override the default message with the supplied one,
244
        # if available.
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
245
        if hasattr(exc_value, 'message') and exc_value.message is not None:
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
246
            msg = exc_value.message
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
247
            # Prepend the exception type
248
            if exc_type != util.IVLEError:
249
                msg = exc_type.__name__ + ": " + repr(msg)
250
251
        tb = ''.join(traceback.format_exception(exc_type, exc_value,
252
                                                exc_traceback))
253
254
    # Logging
255
    logging.error('%s\n%s'%(str(msg), tb))
256
    # Error messages are only displayed is the user is NOT a student,
257
    # 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)
260
    req.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"                 
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
261
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">                                      
262
<html xmlns="http://www.w3.org/1999/xhtml">
263
<head><title>IVLE Internal Server Error</title></head>
264
<body>
265
<h1>IVLE Internal Server Error""")
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
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>
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
272
<p>An error has occured which is the fault of the IVLE developers or
1087 by chadnickbok
Fixes Issue #3
273
administration. The developers have been notified.</p>
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
274
""")
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
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)))
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
284
1099.1.157 by William Grant
Drop the 4xx-series exception handling ability from
285
        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
    req.write("</body></html>")