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

« back to all changes in this revision

Viewing changes to ivle/dispatch/request.py

  • Committer: Matt Giuca
  • Date: 2009-05-12 13:50:49 UTC
  • mto: This revision was merged to the branch mainline in revision 1247.
  • Revision ID: matt.giuca@gmail.com-20090512135049-mlg7kqdpcqmdgphe
ivle.database: User/ProjectGroup: Added 'short_name' methods so we have a
        general interface for displaying the short name.
    ProjectGroup: Changed display_name from showing the name (short name) to
        the nick (friendly name).
    Added docstrings.

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
 
35
 
 
36
import os.path
28
37
 
29
38
import ivle.util
30
 
import ivle.conf
31
 
import plugins.console # XXX: Relies on www/ being in the Python path.
 
39
import ivle.database
 
40
from ivle.webapp.base.plugins import CookiePlugin
32
41
 
33
42
class Request:
34
43
    """An IVLE request object. This is presented to the IVLE apps as a way of
48
57
        user (read)
49
58
            User object. Details of the user who is currently logged in, or
50
59
            None.
 
60
        store (read)
 
61
            storm.store.Store instance. Holds a database transaction open,
 
62
            which is available for the entire lifetime of the request.
51
63
        hostname (read)
52
64
            String. Hostname the server is running on.
53
65
        headers_in (read)
67
79
        location (write)
68
80
            String. Response "Location" header value. Used with HTTP redirect
69
81
            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
82
        styles (write)
74
83
            List of strings. Write a list of URLs to CSS files here, and they
75
84
            will be incorporated as <link rel="stylesheet" type="text/css">
88
97
            in the head, if write_html_head_foot is True.
89
98
            This is the propper way to specify functions that need to run at 
90
99
            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
100
    """
104
101
 
105
102
    # Special code for an OK response.
158
155
    HTTP_INSUFFICIENT_STORAGE         = 507
159
156
    HTTP_NOT_EXTENDED                 = 510
160
157
 
161
 
    def __init__(self, req, write_html_head):
162
 
        """Builds an IVLE request object from a mod_python request object.
163
 
        This results in an object with all of the necessary methods and
164
 
        additional fields.
 
158
    def __init__(self, req, config):
 
159
        """Create an IVLE request from a mod_python one.
165
160
 
166
 
        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.
 
161
        @param req: A mod_python request.
 
162
        @param config: An IVLE configuration.
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
 
167
        self.config = config
174
168
        self.headers_written = False
175
169
 
176
170
        # Determine if the browser used the public host name to make the
177
171
        # request (in which case we are in "public mode")
178
 
        if req.hostname == ivle.conf.public_host:
 
172
        if req.hostname == config['urls']['public_host']:
179
173
            self.publicmode = True
180
174
        else:
181
175
            self.publicmode = False
185
179
        self.uri = req.uri
186
180
        # Split the given path into the app (top-level dir) and sub-path
187
181
        # (after first stripping away the root directory)
188
 
        path = ivle.util.unmake_path(req.uri)
 
182
        path = self.unmake_path(req.uri)
189
183
        (self.app, self.path) = (ivle.util.split_path(path))
190
184
        self.user = None
191
185
        self.hostname = req.hostname
192
186
        self.headers_in = req.headers_in
193
187
        self.headers_out = req.headers_out
194
188
 
 
189
        # Open a database connection and transaction, keep it around for users
 
190
        # of the Request object to use
 
191
        self.store = ivle.database.get_store(config)
 
192
 
195
193
        # Default values for the output members
196
194
        self.status = Request.HTTP_OK
197
195
        self.content_type = None        # Use Apache's default
198
196
        self.location = None
199
 
        self.title = None     # Will be set by dispatch before passing to app
200
197
        self.styles = []
201
198
        self.scripts = []
202
199
        self.scripts_init = []
203
 
        self.write_html_head_foot = False
204
200
        # In some cases we don't want the template JS (such as the username
205
201
        # and public FQDN) in the output HTML. In that case, set this to 0.
206
202
        self.write_javascript_settings = True
207
203
        self.got_common_vars = False
208
204
 
 
205
    def __del__(self):
 
206
        """Cleanup."""
 
207
        self.store.close()
 
208
 
209
209
    def __writeheaders(self):
210
210
        """Writes out the HTTP and HTML headers before any real data is
211
211
        written."""
212
212
        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
213
 
225
214
        # Prepare the HTTP and HTML headers before the first write is made
226
215
        if self.content_type != None:
228
217
        self.apache_req.status = self.status
229
218
        if self.location != None:
230
219
            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
220
 
235
221
    def ensure_headers_written(self):
236
222
        """Writes out the HTTP and HTML headers if they haven't already been
256
242
    def logout(self):
257
243
        """Log out the current user by destroying the session state.
258
244
        Then redirect to the top-level IVLE page."""
259
 
        # List of cookies that IVLE uses (to be removed at logout)
260
 
        ivle_cookies = ["ivleforumcookie", "clipboard"]
261
 
        
262
245
        if hasattr(self, 'session'):
263
246
            self.session.invalidate()
264
247
            self.session.delete()
265
248
            # Invalidates all IVLE cookies
266
 
            all_cookies = Cookie.get_cookies(self)
267
 
            for cookie in all_cookies:
268
 
                if cookie in ivle_cookies:
269
 
                    self.add_cookie(Cookie.Cookie(cookie,'',expires=1,path='/'))
270
 
        self.throw_redirect(ivle.util.make_path('')) 
 
249
            all_cookies = mod_python.Cookie.get_cookies(self)
 
250
 
 
251
            # Create cookies for plugins that might request them.
 
252
            for plugin in self.config.plugin_index[CookiePlugin]:
 
253
                for cookie in plugin.cookies:
 
254
                    self.add_cookie(mod_python.Cookie.Cookie(cookie, '',
 
255
                                                    expires=1, path='/'))
 
256
        self.throw_redirect(self.make_path(''))
271
257
 
272
258
 
273
259
    def flush(self):
288
274
        else:
289
275
            return self.apache_req.read(len)
290
276
 
291
 
    def throw_error(self, httpcode, message=None):
292
 
        """Writes out an HTTP error of the specified code. Raises an exception
293
 
        which is caught by the dispatch or web server, so any code following
294
 
        this call will not be executed.
295
 
 
296
 
        httpcode: An HTTP response status code. Pass a constant from the
297
 
        Request class.
298
 
        """
299
 
        raise ivle.util.IVLEError(httpcode, message)
300
 
 
301
277
    def throw_redirect(self, location):
302
278
        """Writes out an HTTP redirect to the specified URL. Raises an
303
279
        exception which is caught by the dispatch or web server, so any
306
282
        httpcode: An HTTP response status code. Pass a constant from the
307
283
        Request class.
308
284
        """
309
 
        mod_python.util.redirect(self.apache_req, location)
 
285
        # Note: location may be a unicode, but it MUST only have ASCII
 
286
        # characters (non-ascii characters should be URL-encoded).
 
287
        mod_python.util.redirect(self.apache_req, location.encode("ascii"))
310
288
 
311
289
    def add_cookie(self, cookie, value=None, **attributes):
312
290
        """Inserts a cookie into this request object's headers."""
313
291
        if value is None:
314
 
            Cookie.add_cookie(self.apache_req, cookie)
 
292
            mod_python.Cookie.add_cookie(self.apache_req, cookie)
315
293
        else:
316
 
            Cookie.add_cookie(self.apache_req, cookie, value, **attributes)
 
294
            mod_python.Cookie.add_cookie(self.apache_req, cookie, value, **attributes)
 
295
 
 
296
    def make_path(self, path):
 
297
        """Prepend the IVLE URL prefix to the given path.
 
298
 
 
299
        This is used when generating URLs to send to the client.
 
300
 
 
301
        This method is DEPRECATED. We no longer support use of a prefix.
 
302
        """
 
303
        return os.path.join(self.config['urls']['root'], path)
 
304
 
 
305
    def unmake_path(self, path):
 
306
        """Strip the IVLE URL prefix from the given path, if present.
 
307
 
 
308
        Also normalises the path.
 
309
 
 
310
        This method is DEPRECATED. We no longer support use of a prefix.
 
311
        """
 
312
        path = os.path.normpath(path)
 
313
        root = os.path.normpath(self.config['urls']['root'])
 
314
 
 
315
        if path.startswith(root):
 
316
            path = path[len(root):]
 
317
            # Take out the slash as well
 
318
            if len(path) > 0 and path[0] == os.sep:
 
319
                path = path[1:]
 
320
 
 
321
        return path
317
322
 
318
323
    def get_session(self):
319
324
        """Returns a mod_python Session object for this request.
320
325
        Note that this is dependent on mod_python and may need to change
321
 
        interface if porting away from mod_python."""
 
326
        interface if porting away from mod_python.
 
327
 
 
328
        IMPORTANT: Call unlock() on the session as soon as you are done with
 
329
                   it! If you don't, all other requests will block!
 
330
        """
322
331
        # Cache the session object and set the timeout to 24 hours.
323
332
        if not hasattr(self, 'session'):
324
 
            self.session = Session.FileSession(self.apache_req,
 
333
            self.session = mod_python.Session.FileSession(self.apache_req,
325
334
                                               timeout = 60 * 60 * 24)
326
335
        return self.session
327
336
 
331
340
        interface if porting away from mod_python."""
332
341
        # Cache the fieldstorage object
333
342
        if not hasattr(self, 'fields'):
334
 
            self.fields = util.FieldStorage(self.apache_req)
 
343
            self.fields = mod_python.util.FieldStorage(self.apache_req)
335
344
        return self.fields
336
345
 
337
346
    def get_cgi_environ(self):