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

« back to all changes in this revision

Viewing changes to ivle/studpath.py

Dispatch now generates an index for each plugin type, allowing plugins to
be written which are aware of other plugins, and other plugin types.

All view plugins now subclass from ivle.webapp.base.plugins.ViewPlugin,
as opposed to subclassing BasePlugin directly. This will allow us to
easily re-write console as an OverlayPlugin, and allow future new
plugins types to be created.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2008 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
# Module: studpath
 
19
# Author: Matt Giuca
 
20
# Date:   14/12/2007
 
21
 
 
22
# Provides functions for translating URLs into physical locations in the
 
23
# student directories in the local file system.
 
24
# Also performs common authorization, disallowing students from visiting paths
 
25
# they dont own.
 
26
 
 
27
import os
 
28
import stat
 
29
import pysvn
 
30
 
 
31
import ivle.conf
 
32
from ivle import util
 
33
 
 
34
# Make a Subversion client object (for published)
 
35
svnclient = pysvn.Client()
 
36
 
 
37
def url_to_local(urlpath):
 
38
    """Given a URL path (part of a URL query string, see below), returns a
 
39
    tuple of
 
40
        * the username of the student whose directory is being browsed
 
41
        * the absolute path in the file system where that file will be
 
42
            found within the student directories.
 
43
 
 
44
    urlpath: Part of the URL, but only the part *after* the application. For
 
45
    instance, given the URL "/ivle/browse/joe/mydir/myfile", urlpath will
 
46
    be just "joe/mydir/myfile". The expected result is something like
 
47
    ("joe", "/home/informatics/jails/joe/home/joe/mydir/myfile").
 
48
    Note that the actual location is not guaranteed by this interface (this
 
49
    function serves as a single point of control as to how URLs map onto
 
50
    student directories).
 
51
 
 
52
    Returns (None, None) if the path is empty.
 
53
 
 
54
    See also: ivle.conf.jail_base
 
55
    """
 
56
    # First normalise the path
 
57
    urlpath = os.path.normpath(urlpath)
 
58
    # Now if it begins with ".." or separator, then it's illegal
 
59
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
 
60
        return (None, None)
 
61
    # Note: User can be a group name. There is absolutely no difference in our
 
62
    # current directory scheme.
 
63
    (user, subpath) = util.split_path(urlpath)
 
64
    if user is None: return (None, None)
 
65
 
 
66
    # Join the user onto 'home' then the full path specified.
 
67
    # This results in the user's name being repeated twice, which is in
 
68
    # accordance with our directory scheme.
 
69
    # (The first time is the name of the jail, the second is the user's home
 
70
    # directory within the jail).
 
71
    path = os.path.join(ivle.conf.jail_base, user, 'home', urlpath)
 
72
 
 
73
    return (user, path)
 
74
 
 
75
def url_to_jailpaths(urlpath):
 
76
    """Given a URL path (part of a URL query string), returns a tuple of
 
77
        * the username of the student whose directory is being browsed
 
78
        * the absolute path where the jail will be located.
 
79
        * the path of the file relative to the jail.
 
80
 
 
81
    urlpath: See urlpath in url_to_local.
 
82
 
 
83
    >>> url_to_jailpaths("joe/mydir/myfile")
 
84
    ('joe', '/var/lib/ivle/jailmounts/joe', '/home/joe/mydir/myfile')
 
85
 
 
86
    >>> url_to_jailpaths("")
 
87
    (None, None, None)
 
88
    """
 
89
    # First normalise the path
 
90
    urlpath = os.path.normpath(urlpath)
 
91
    # Now if it begins with ".." then it's illegal
 
92
    if urlpath.startswith(".."):
 
93
        return (None, None, None)
 
94
    # Note: User can be a group name. There is absolutely no difference in our
 
95
    # current directory scheme.
 
96
    (user, subpath) = util.split_path(urlpath)
 
97
    if user is None: return (None, None, None)
 
98
 
 
99
    jail = os.path.join(ivle.conf.jail_base, user)
 
100
    path = os.path.join('/home', urlpath)
 
101
 
 
102
    return (user, jail, path)
 
103
 
 
104
def svnpublished(path):
 
105
    """Given a path on the LOCAL file system, determines whether the path has
 
106
    its "ivle:published" property active (in subversion). Returns True
 
107
    or False."""
 
108
    # Read SVN properties for this path
 
109
    try:
 
110
        props = svnclient.propget("ivle:published", path, recurse=False)
 
111
    except pysvn.ClientError:
 
112
        # Not under version control? Then it isn't published.
 
113
        return False
 
114
    return len(props) > 0
 
115
 
 
116
def published(path):
 
117
    """Given a path on the LOCAL file system, determines whether the path has a 
 
118
    '.published' file.  Returns True or False."""
 
119
    publish_file_path = os.path.join(path,'.published')
 
120
    return os.access(publish_file_path,os.F_OK)
 
121
 
 
122
def worldreadable(path):
 
123
    """Given a path on the LOCAL file system, determines whether the path is 
 
124
    world readble. Returns True or False."""
 
125
    try:
 
126
        mode = os.stat(path).st_mode
 
127
        if mode & stat.S_IROTH:
 
128
            return True
 
129
        else:
 
130
            return False
 
131
    except OSError, e:
 
132
        return False
 
133
 
 
134
 
 
135
def authorize(req):
 
136
    """Given a request, checks whether req.user is allowed to
 
137
    access req.path. Returns None on authorization success. Raises
 
138
    HTTP_FORBIDDEN on failure.
 
139
 
 
140
    This is for general authorization (assuming not in public mode; this is
 
141
    the standard auth code for fileservice, download and serve).
 
142
    """
 
143
    # TODO: Groups
 
144
    # First normalise the path
 
145
    urlpath = os.path.normpath(req.path)
 
146
    # Now if it begins with ".." or separator, then it's illegal
 
147
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
 
148
        req.throw_error(req.HTTP_FORBIDDEN)
 
149
 
 
150
    (owner, _) = util.split_path(urlpath)
 
151
    if req.user.login != owner:
 
152
        req.throw_error(req.HTTP_FORBIDDEN)
 
153
 
 
154
def authorize_public(req):
 
155
    """A different kind of authorization. Rather than making sure the
 
156
    logged-in user owns the file, this checks if the file is in a published
 
157
    directory.
 
158
 
 
159
    This is for the "public mode" of the serve app.
 
160
 
 
161
    Same interface as "authorize" - None on success, HTTP_FORBIDDEN exception
 
162
    raised on failure.
 
163
    """
 
164
    _, path = url_to_local(req.path)
 
165
    dirpath, _ = os.path.split(path)
 
166
    if not (worldreadable(dirpath) and published(dirpath)):
 
167
        req.throw_error(req.HTTP_FORBIDDEN)