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

« back to all changes in this revision

Viewing changes to ivle/studpath.py

  • Committer: David Coles
  • Date: 2010-08-30 03:26:13 UTC
  • Revision ID: coles.david@gmail.com-20100830032613-d14vng0jkelniu3l
python-console: Fix globals broken with new JSON library.

simplejson always returns unicode strings. cJSON would return ordinary strings 
if possible. cPickle.loads() only accepts strings. At present we use pickle 
version 0 so they should all works as ASCII strings. Higher versions of pickle 
are not plain ASCII and are likely to break this and so this should be fixed 
at some point.

Also replaced unconditional exception with one that catches Pickle errors. Not 
sure the best way to report failures of these functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
import os
28
28
import stat
29
 
import pysvn
30
29
 
31
 
import ivle.conf
32
30
from ivle import util
33
31
 
34
 
# Make a Subversion client object (for published)
35
 
svnclient = pysvn.Client()
36
 
 
37
 
def url_to_local(urlpath):
 
32
def url_to_local(config, urlpath):
38
33
    """Given a URL path (part of a URL query string, see below), returns a
39
34
    tuple of
40
35
        * the username of the student whose directory is being browsed
51
46
 
52
47
    Returns (None, None) if the path is empty.
53
48
 
54
 
    See also: ivle.conf.jail_base
 
49
    >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}}
 
50
 
 
51
    >>> url_to_local(stubconfig, 'joe/foo/bar/baz')
 
52
    ('joe', '/jails/joe/home/joe/foo/bar/baz')
 
53
    >>> url_to_local(stubconfig, 'joe')
 
54
    ('joe', '/jails/joe/home/joe')
 
55
    >>> url_to_local(stubconfig, 'joe/')
 
56
    ('joe', '/jails/joe/home/joe')
 
57
 
 
58
    We have some protection from various potential attacks. An empty,
 
59
    absolute, or ..-prefixed path yields a special result.
 
60
 
 
61
    >>> url_to_local(stubconfig, '')
 
62
    (None, None)
 
63
    >>> url_to_local(stubconfig, '/foo')
 
64
    (None, None)
 
65
    >>> url_to_local(stubconfig, '../bar')
 
66
    (None, None)
55
67
    """
 
68
 
56
69
    # First normalise the path
57
70
    urlpath = os.path.normpath(urlpath)
58
71
    # Now if it begins with ".." or separator, then it's illegal
68
81
    # accordance with our directory scheme.
69
82
    # (The first time is the name of the jail, the second is the user's home
70
83
    # directory within the jail).
71
 
    path = os.path.join(ivle.conf.jail_base, user, 'home', urlpath)
 
84
    path = os.path.join(config['paths']['jails']['mounts'],
 
85
                        user, 'home', urlpath)
72
86
 
73
87
    return (user, path)
74
88
 
75
 
def url_to_jailpaths(urlpath):
 
89
def url_to_jailpaths(config, urlpath):
76
90
    """Given a URL path (part of a URL query string), returns a tuple of
77
91
        * the username of the student whose directory is being browsed
78
92
        * the absolute path where the jail will be located.
80
94
 
81
95
    urlpath: See urlpath in url_to_local.
82
96
 
83
 
    >>> url_to_jailpaths("joe/mydir/myfile")
84
 
    ("joe", "/home/informatics/jails/joe", "home/joe/mydir/myfile")
 
97
    >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}}
85
98
 
86
 
    >>> url_to_jailpaths("")
 
99
    >>> url_to_jailpaths(stubconfig, "joe/mydir//myfile/.././myfile")
 
100
    ('joe', '/jails/joe', '/home/joe/mydir/myfile')
 
101
    >>> url_to_jailpaths(stubconfig, "")
 
102
    (None, None, None)
 
103
    >>> url_to_jailpaths(stubconfig, "../foo")
 
104
    (None, None, None)
 
105
    >>> url_to_jailpaths(stubconfig, "/foo")
87
106
    (None, None, None)
88
107
    """
89
108
    # First normalise the path
90
109
    urlpath = os.path.normpath(urlpath)
91
 
    # Now if it begins with ".." then it's illegal
92
 
    if urlpath.startswith(".."):
 
110
    # Now if it begins with "..", or is absolute, then it's illegal
 
111
    if urlpath.startswith("..") or os.path.isabs(urlpath):
93
112
        return (None, None, None)
94
113
    # Note: User can be a group name. There is absolutely no difference in our
95
114
    # current directory scheme.
96
115
    (user, subpath) = util.split_path(urlpath)
97
116
    if user is None: return (None, None, None)
98
117
 
99
 
    jail = os.path.join(ivle.conf.jail_base, user)
100
 
    path = os.path.join('/home', urlpath)
 
118
    jail = os.path.join(config['paths']['jails']['mounts'], user)
 
119
    path = to_home_path(urlpath)
101
120
 
102
121
    return (user, jail, path)
103
122
 
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
 
123
def to_home_path(urlpath):
 
124
    """Given a URL path (eg. joe/foo/bar/baz), returns a path within the home.
 
125
 
 
126
    >>> to_home_path('joe/foo/bar/baz')
 
127
    '/home/joe/foo/bar/baz'
 
128
    >>> to_home_path('joe/foo//bar/baz/../../')
 
129
    '/home/joe/foo'
 
130
    >>> to_home_path('joe/foo//bar/baz/../../../../../') is None
 
131
    True
 
132
    """
 
133
 
 
134
    urlpath = os.path.normpath(urlpath)
 
135
    # If it begins with '..', it's illegal.
 
136
    if urlpath.startswith(".."):
 
137
        return None
 
138
 
 
139
    return os.path.join('/home', urlpath)
115
140
 
116
141
def published(path):
117
142
    """Given a path on the LOCAL file system, determines whether the path has a 
132
157
        return False
133
158
 
134
159
 
135
 
def authorize(req):
 
160
def authorize(req, user):
136
161
    """Given a request, checks whether req.user is allowed to
137
162
    access req.path. Returns None on authorization success. Raises
138
163
    HTTP_FORBIDDEN on failure.
145
170
    urlpath = os.path.normpath(req.path)
146
171
    # Now if it begins with ".." or separator, then it's illegal
147
172
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
148
 
        req.throw_error(req.HTTP_FORBIDDEN)
 
173
        return False
149
174
 
150
175
    (owner, _) = util.split_path(urlpath)
151
 
    if req.user.login != owner:
152
 
        req.throw_error(req.HTTP_FORBIDDEN)
 
176
    if user.login != owner:
 
177
        return False
 
178
    return True
153
179
 
154
180
def authorize_public(req):
155
181
    """A different kind of authorization. Rather than making sure the
161
187
    Same interface as "authorize" - None on success, HTTP_FORBIDDEN exception
162
188
    raised on failure.
163
189
    """
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)
 
190
    _, path = url_to_local(req.config, req.path)
 
191
 
 
192
    # Walk up the tree, and find the deepest directory.
 
193
    while not os.path.isdir(path):
 
194
        path = os.path.dirname(path)
 
195
 
 
196
    if not (worldreadable(path) and published(path)):
 
197
        return False
 
198
    return True