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

« back to all changes in this revision

Viewing changes to ivle/dispatch/request.py

XHTMLErrorView is now the default error view, so we get nice 404s.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# IVLE - Informatics Virtual Learning Environment
2
 
# Copyright (C) 2007-2008 The University of Melbourne
 
2
# Copyright (C) 2007-2009 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
 
# Module: dispatch.request
19
18
# Author: Matt Giuca
20
 
# Date:   12/12/2007
21
 
 
22
 
# Builds an IVLE request object from a mod_python request object.
23
 
# See design notes/apps/dispatch.txt for a full specification of this request
24
 
# object.
25
 
 
26
 
import mod_python
27
 
from mod_python import (util, Session, Cookie)
 
19
 
 
20
"""
 
21
IVLE Request Object
 
22
 
 
23
Builds an IVLE request object from a mod_python request object.
 
24
See design notes/apps/dispatch.txt for a full specification of this request
 
25
object.
 
26
"""
 
27
 
 
28
try:
 
29
    import mod_python.Session
 
30
    import mod_python.Cookie
 
31
    import mod_python.util
 
32
except ImportError:
 
33
    # This needs to be importable from outside Apache.
 
34
    pass
28
35
 
29
36
import ivle.util
30
37
import ivle.conf
31
 
import plugins.console # XXX: Relies on www/ being in the Python path.
 
38
import ivle.database
 
39
from ivle.webapp.base.plugins import CookiePlugin
32
40
 
33
41
class Request:
34
42
    """An IVLE request object. This is presented to the IVLE apps as a way of
48
56
        user (read)
49
57
            User object. Details of the user who is currently logged in, or
50
58
            None.
 
59
        store (read)
 
60
            storm.store.Store instance. Holds a database transaction open,
 
61
            which is available for the entire lifetime of the request.
51
62
        hostname (read)
52
63
            String. Hostname the server is running on.
53
64
        headers_in (read)
67
78
        location (write)
68
79
            String. Response "Location" header value. Used with HTTP redirect
69
80
            responses.
70
 
        title (write)
71
 
            String. HTML page title. Used if write_html_head_foot is True, in
72
 
            the HTML title element text.
73
81
        styles (write)
74
82
            List of strings. Write a list of URLs to CSS files here, and they
75
83
            will be incorporated as <link rel="stylesheet" type="text/css">
88
96
            in the head, if write_html_head_foot is True.
89
97
            This is the propper way to specify functions that need to run at 
90
98
            page load time.
91
 
        write_html_head_foot (write)
92
 
            Boolean. If True, dispatch assumes that this is an XHTML page, and
93
 
            will immediately write a full HTML head, open the body element,
94
 
            and write heading contents to the page, before any bytes are
95
 
            written. It will then write footer contents and close the body and
96
 
            html elements at the end of execution.  
97
 
 
98
 
            This value should be set to true by all applications for all HTML
99
 
            output (unless there is a good reason, eg. exec). The
100
 
            applications should therefore output HTML content assuming that
101
 
            it will be written inside the body tag. Do not write opening or
102
 
            closing <html> or <body> tags.
103
99
    """
104
100
 
105
101
    # Special code for an OK response.
158
154
    HTTP_INSUFFICIENT_STORAGE         = 507
159
155
    HTTP_NOT_EXTENDED                 = 510
160
156
 
161
 
    def __init__(self, req, write_html_head):
 
157
    def __init__(self, req):
162
158
        """Builds an IVLE request object from a mod_python request object.
163
159
        This results in an object with all of the necessary methods and
164
160
        additional fields.
165
161
 
166
162
        req: A mod_python request object.
167
 
        write_html_head: Function which is called when writing the automatic
168
 
            HTML header. Accepts a single argument, the IVLE request object.
169
163
        """
170
164
 
171
165
        # Methods are mostly wrappers around the Apache request object
172
166
        self.apache_req = req
173
 
        self.func_write_html_head = write_html_head
174
167
        self.headers_written = False
175
168
 
176
169
        # Determine if the browser used the public host name to make the
192
185
        self.headers_in = req.headers_in
193
186
        self.headers_out = req.headers_out
194
187
 
 
188
        # Open a database connection and transaction, keep it around for users
 
189
        # of the Request object to use
 
190
        self.store = ivle.database.get_store()
 
191
 
195
192
        # Default values for the output members
196
193
        self.status = Request.HTTP_OK
197
194
        self.content_type = None        # Use Apache's default
198
195
        self.location = None
199
 
        self.title = None     # Will be set by dispatch before passing to app
200
196
        self.styles = []
201
197
        self.scripts = []
202
198
        self.scripts_init = []
203
 
        self.write_html_head_foot = False
204
199
        # In some cases we don't want the template JS (such as the username
205
200
        # and public FQDN) in the output HTML. In that case, set this to 0.
206
201
        self.write_javascript_settings = True
207
202
        self.got_common_vars = False
208
203
 
 
204
    def __del__(self):
 
205
        """Cleanup."""
 
206
        self.store.close()
 
207
 
209
208
    def __writeheaders(self):
210
209
        """Writes out the HTTP and HTML headers before any real data is
211
210
        written."""
212
211
        self.headers_written = True
213
 
        
214
 
        # app is the App object for the chosen app
215
 
        try:
216
 
            app = ivle.conf.apps.app_url[self.app]
217
 
        except KeyError:
218
 
            app = None
219
 
 
220
 
        # Write any final modifications to header content
221
 
        if app and app.useconsole and self.user:
222
 
            plugins.console.insert_scripts_styles(self.scripts, self.styles, \
223
 
                self.scripts_init)
224
212
 
225
213
        # Prepare the HTTP and HTML headers before the first write is made
226
214
        if self.content_type != None:
228
216
        self.apache_req.status = self.status
229
217
        if self.location != None:
230
218
            self.apache_req.headers_out['Location'] = self.location
231
 
        if self.write_html_head_foot:
232
 
            # Write the HTML header, pass "self" (request object)
233
 
            self.func_write_html_head(self)
234
219
 
235
220
    def ensure_headers_written(self):
236
221
        """Writes out the HTTP and HTML headers if they haven't already been
253
238
            # This includes binary strings.
254
239
            self.apache_req.write(string, flush)
255
240
 
 
241
    def logout(self):
 
242
        """Log out the current user by destroying the session state.
 
243
        Then redirect to the top-level IVLE page."""
 
244
        if hasattr(self, 'session'):
 
245
            self.session.invalidate()
 
246
            self.session.delete()
 
247
            # Invalidates all IVLE cookies
 
248
            all_cookies = mod_python.Cookie.get_cookies(self)
 
249
 
 
250
            # Create cookies for plugins that might request them.
 
251
            for plugin in self.config.plugin_index[CookiePlugin]:
 
252
                for cookie in plugin.cookies:
 
253
                    self.add_cookie(mod_python.Cookie.Cookie(cookie, '',
 
254
                                                    expires=1, path='/'))
 
255
        self.throw_redirect(ivle.util.make_path('')) 
 
256
 
 
257
 
256
258
    def flush(self):
257
259
        """Flushes the output buffer."""
258
260
        self.apache_req.flush()
271
273
        else:
272
274
            return self.apache_req.read(len)
273
275
 
274
 
    def throw_error(self, httpcode, message=None):
275
 
        """Writes out an HTTP error of the specified code. Raises an exception
276
 
        which is caught by the dispatch or web server, so any code following
277
 
        this call will not be executed.
278
 
 
279
 
        httpcode: An HTTP response status code. Pass a constant from the
280
 
        Request class.
281
 
        """
282
 
        raise ivle.util.IVLEError(httpcode, message)
283
 
 
284
276
    def throw_redirect(self, location):
285
277
        """Writes out an HTTP redirect to the specified URL. Raises an
286
278
        exception which is caught by the dispatch or web server, so any
289
281
        httpcode: An HTTP response status code. Pass a constant from the
290
282
        Request class.
291
283
        """
292
 
        mod_python.util.redirect(self.apache_req, location)
 
284
        # Note: location may be a unicode, but it MUST only have ASCII
 
285
        # characters (non-ascii characters should be URL-encoded).
 
286
        mod_python.util.redirect(self.apache_req, location.encode("ascii"))
293
287
 
294
288
    def add_cookie(self, cookie, value=None, **attributes):
295
289
        """Inserts a cookie into this request object's headers."""
296
290
        if value is None:
297
 
            Cookie.add_cookie(self.apache_req, cookie)
 
291
            mod_python.Cookie.add_cookie(self.apache_req, cookie)
298
292
        else:
299
 
            Cookie.add_cookie(self.apache_req, cookie, value, **attributes)
 
293
            mod_python.Cookie.add_cookie(self.apache_req, cookie, value, **attributes)
300
294
 
301
295
    def get_session(self):
302
296
        """Returns a mod_python Session object for this request.
304
298
        interface if porting away from mod_python."""
305
299
        # Cache the session object and set the timeout to 24 hours.
306
300
        if not hasattr(self, 'session'):
307
 
            self.session = Session.FileSession(self.apache_req,
 
301
            self.session = mod_python.Session.FileSession(self.apache_req,
308
302
                                               timeout = 60 * 60 * 24)
309
303
        return self.session
310
304
 
314
308
        interface if porting away from mod_python."""
315
309
        # Cache the fieldstorage object
316
310
        if not hasattr(self, 'fields'):
317
 
            self.fields = util.FieldStorage(self.apache_req)
 
311
            self.fields = mod_python.util.FieldStorage(self.apache_req)
318
312
        return self.fields
319
313
 
320
314
    def get_cgi_environ(self):