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

« back to all changes in this revision

Viewing changes to ivle/studpath.py

  • Committer: stevenbird
  • Date: 2008-02-19 07:59:12 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:507
Extended code test framework to support tests on the code string, rather
than just its outputs.  This makes it possible to check the method being
used by the code to do its work.  For example, if the exercise is to
write code that computes 10! using multiplication, a response that
simply prints 3628800 produces the correct output, but using the
incorrect method.  A regular expression that tests the code could check
for the presence of a multiplication operation.  The XML format is:
<code type="check"> lambda x,y: '*' in y </code>

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
 
from ivle import util
32
 
 
33
 
# Make a Subversion client object (for published)
34
 
svnclient = pysvn.Client()
35
 
 
36
 
def url_to_local(config, urlpath):
37
 
    """Given a URL path (part of a URL query string, see below), returns a
38
 
    tuple of
39
 
        * the username of the student whose directory is being browsed
40
 
        * the absolute path in the file system where that file will be
41
 
            found within the student directories.
42
 
 
43
 
    urlpath: Part of the URL, but only the part *after* the application. For
44
 
    instance, given the URL "/ivle/browse/joe/mydir/myfile", urlpath will
45
 
    be just "joe/mydir/myfile". The expected result is something like
46
 
    ("joe", "/home/informatics/jails/joe/home/joe/mydir/myfile").
47
 
    Note that the actual location is not guaranteed by this interface (this
48
 
    function serves as a single point of control as to how URLs map onto
49
 
    student directories).
50
 
 
51
 
    Returns (None, None) if the path is empty.
52
 
 
53
 
    >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}}
54
 
 
55
 
    >>> url_to_local(stubconfig, 'joe/foo/bar/baz')
56
 
    ('joe', '/jails/joe/home/joe/foo/bar/baz')
57
 
    >>> url_to_local(stubconfig, 'joe')
58
 
    ('joe', '/jails/joe/home/joe')
59
 
    >>> url_to_local(stubconfig, 'joe/')
60
 
    ('joe', '/jails/joe/home/joe')
61
 
 
62
 
    We have some protection from various potential attacks. An empty,
63
 
    absolute, or ..-prefixed path yields a special result.
64
 
 
65
 
    >>> url_to_local(stubconfig, '')
66
 
    (None, None)
67
 
    >>> url_to_local(stubconfig, '/foo')
68
 
    (None, None)
69
 
    >>> url_to_local(stubconfig, '../bar')
70
 
    (None, None)
71
 
    """
72
 
 
73
 
    # First normalise the path
74
 
    urlpath = os.path.normpath(urlpath)
75
 
    # Now if it begins with ".." or separator, then it's illegal
76
 
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
77
 
        return (None, None)
78
 
    # Note: User can be a group name. There is absolutely no difference in our
79
 
    # current directory scheme.
80
 
    (user, subpath) = util.split_path(urlpath)
81
 
    if user is None: return (None, None)
82
 
 
83
 
    # Join the user onto 'home' then the full path specified.
84
 
    # This results in the user's name being repeated twice, which is in
85
 
    # accordance with our directory scheme.
86
 
    # (The first time is the name of the jail, the second is the user's home
87
 
    # directory within the jail).
88
 
    path = os.path.join(config['paths']['jails']['mounts'],
89
 
                        user, 'home', urlpath)
90
 
 
91
 
    return (user, path)
92
 
 
93
 
def url_to_jailpaths(config, urlpath):
94
 
    """Given a URL path (part of a URL query string), returns a tuple of
95
 
        * the username of the student whose directory is being browsed
96
 
        * the absolute path where the jail will be located.
97
 
        * the path of the file relative to the jail.
98
 
 
99
 
    urlpath: See urlpath in url_to_local.
100
 
 
101
 
    >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}}
102
 
 
103
 
    >>> url_to_jailpaths(stubconfig, "joe/mydir//myfile/.././myfile")
104
 
    ('joe', '/jails/joe', '/home/joe/mydir/myfile')
105
 
    >>> url_to_jailpaths(stubconfig, "")
106
 
    (None, None, None)
107
 
    >>> url_to_jailpaths(stubconfig, "../foo")
108
 
    (None, None, None)
109
 
    >>> url_to_jailpaths(stubconfig, "/foo")
110
 
    (None, None, None)
111
 
    """
112
 
    # First normalise the path
113
 
    urlpath = os.path.normpath(urlpath)
114
 
    # Now if it begins with "..", or is absolute, then it's illegal
115
 
    if urlpath.startswith("..") or os.path.isabs(urlpath):
116
 
        return (None, None, None)
117
 
    # Note: User can be a group name. There is absolutely no difference in our
118
 
    # current directory scheme.
119
 
    (user, subpath) = util.split_path(urlpath)
120
 
    if user is None: return (None, None, None)
121
 
 
122
 
    jail = os.path.join(config['paths']['jails']['mounts'], user)
123
 
    path = to_home_path(urlpath)
124
 
 
125
 
    return (user, jail, path)
126
 
 
127
 
def to_home_path(urlpath):
128
 
    """Given a URL path (eg. joe/foo/bar/baz), returns a path within the home.
129
 
 
130
 
    >>> to_home_path('joe/foo/bar/baz')
131
 
    '/home/joe/foo/bar/baz'
132
 
    >>> to_home_path('joe/foo//bar/baz/../../')
133
 
    '/home/joe/foo'
134
 
    >>> to_home_path('joe/foo//bar/baz/../../../../../') is None
135
 
    True
136
 
    """
137
 
 
138
 
    urlpath = os.path.normpath(urlpath)
139
 
    # If it begins with '..', it's illegal.
140
 
    if urlpath.startswith(".."):
141
 
        return None
142
 
 
143
 
    return os.path.join('/home', urlpath)
144
 
 
145
 
def svnpublished(path):
146
 
    """Given a path on the LOCAL file system, determines whether the path has
147
 
    its "ivle:published" property active (in subversion). Returns True
148
 
    or False."""
149
 
    # Read SVN properties for this path
150
 
    try:
151
 
        props = svnclient.propget("ivle:published", path, recurse=False)
152
 
    except pysvn.ClientError:
153
 
        # Not under version control? Then it isn't published.
154
 
        return False
155
 
    return len(props) > 0
156
 
 
157
 
def published(path):
158
 
    """Given a path on the LOCAL file system, determines whether the path has a 
159
 
    '.published' file.  Returns True or False."""
160
 
    publish_file_path = os.path.join(path,'.published')
161
 
    return os.access(publish_file_path,os.F_OK)
162
 
 
163
 
def worldreadable(path):
164
 
    """Given a path on the LOCAL file system, determines whether the path is 
165
 
    world readble. Returns True or False."""
166
 
    try:
167
 
        mode = os.stat(path).st_mode
168
 
        if mode & stat.S_IROTH:
169
 
            return True
170
 
        else:
171
 
            return False
172
 
    except OSError, e:
173
 
        return False
174
 
 
175
 
 
176
 
def authorize(req, user):
177
 
    """Given a request, checks whether req.user is allowed to
178
 
    access req.path. Returns None on authorization success. Raises
179
 
    HTTP_FORBIDDEN on failure.
180
 
 
181
 
    This is for general authorization (assuming not in public mode; this is
182
 
    the standard auth code for fileservice, download and serve).
183
 
    """
184
 
    # TODO: Groups
185
 
    # First normalise the path
186
 
    urlpath = os.path.normpath(req.path)
187
 
    # Now if it begins with ".." or separator, then it's illegal
188
 
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
189
 
        return False
190
 
 
191
 
    (owner, _) = util.split_path(urlpath)
192
 
    if user.login != owner:
193
 
        return False
194
 
    return True
195
 
 
196
 
def authorize_public(req):
197
 
    """A different kind of authorization. Rather than making sure the
198
 
    logged-in user owns the file, this checks if the file is in a published
199
 
    directory.
200
 
 
201
 
    This is for the "public mode" of the serve app.
202
 
 
203
 
    Same interface as "authorize" - None on success, HTTP_FORBIDDEN exception
204
 
    raised on failure.
205
 
    """
206
 
    _, path = url_to_local(req.config, req.path)
207
 
 
208
 
    # Walk up the tree, and find the deepest directory.
209
 
    while not os.path.isdir(path):
210
 
        path = os.path.dirname(path)
211
 
 
212
 
    if not (worldreadable(path) and published(path)):
213
 
        return False
214
 
    return True