93
by mattgiuca
New directory hierarchy. |
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: common.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.
|
|
262
by mattgiuca
studpath: Added "authorize" function which checks the logged in user against |
24 |
# Also performs common authorization, disallowing students from visiting paths
|
25 |
# they dont own.
|
|
93
by mattgiuca
New directory hierarchy. |
26 |
|
27 |
import os |
|
28 |
||
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
29 |
import pysvn |
30 |
||
93
by mattgiuca
New directory hierarchy. |
31 |
import conf |
32 |
from common import util |
|
33 |
||
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
34 |
# Make a Subversion client object (for published)
|
35 |
svnclient = pysvn.Client() |
|
36 |
||
93
by mattgiuca
New directory hierarchy. |
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/home/mydir/myfile", urlpath will
|
|
46 |
be just "joe/home/mydir/myfile". The expected result is something like
|
|
47 |
("joe", "/home/informatics/jails/joe/home/joe/home/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 |
||
106
by mattgiuca
Renamed "student_dir" to "jail_base" across the suite. |
54 |
See also: conf.jail_base
|
93
by mattgiuca
New directory hierarchy. |
55 |
"""
|
125
by mattgiuca
common/studpath.py: Normalise and check path for ".." to disallow |
56 |
# First normalise the path
|
57 |
urlpath = os.path.normpath(urlpath) |
|
151
by mattgiuca
studpath: Security fix: Disallows paths beginning with os.sep. |
58 |
# Now if it begins with ".." or separator, then it's illegal
|
59 |
if urlpath.startswith("..") or urlpath.startswith(os.sep): |
|
125
by mattgiuca
common/studpath.py: Normalise and check path for ".." to disallow |
60 |
return (None, None) |
93
by mattgiuca
New directory hierarchy. |
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).
|
|
106
by mattgiuca
Renamed "student_dir" to "jail_base" across the suite. |
71 |
path = os.path.join(conf.jail_base, user, 'home', urlpath) |
93
by mattgiuca
New directory hierarchy. |
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/home/mydir/myfile")
|
|
84 |
("joe", "/home/informatics/jails/joe", "home/joe/home/mydir/myfile")
|
|
85 |
||
86 |
>>> url_to_jailpaths("")
|
|
87 |
(None, None, None)
|
|
88 |
"""
|
|
125
by mattgiuca
common/studpath.py: Normalise and check path for ".." to disallow |
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) |
|
93
by mattgiuca
New directory hierarchy. |
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 |
||
106
by mattgiuca
Renamed "student_dir" to "jail_base" across the suite. |
99 |
jail = os.path.join(conf.jail_base, user) |
93
by mattgiuca
New directory hierarchy. |
100 |
path = os.path.join('home', urlpath) |
101 |
||
102 |
return (user, jail, path) |
|
262
by mattgiuca
studpath: Added "authorize" function which checks the logged in user against |
103 |
|
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
104 |
def published(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 |
||
262
by mattgiuca
studpath: Added "authorize" function which checks the logged in user against |
116 |
def authorize(req): |
117 |
"""Given a request, checks whether req.username is allowed to
|
|
118 |
access req.path. Returns None on authorization success. Raises
|
|
119 |
HTTP_FORBIDDEN on failure.
|
|
120 |
||
121 |
This is for general authorization (assuming not in public mode; this is
|
|
122 |
the standard auth code for fileservice, download and serve).
|
|
123 |
"""
|
|
124 |
# TODO: Groups
|
|
125 |
# First normalise the path
|
|
126 |
urlpath = os.path.normpath(req.path) |
|
127 |
# Now if it begins with ".." or separator, then it's illegal
|
|
128 |
if urlpath.startswith("..") or urlpath.startswith(os.sep): |
|
129 |
req.throw_error(req.HTTP_FORBIDDEN) |
|
130 |
||
131 |
(owner, _) = util.split_path(urlpath) |
|
132 |
if req.username != owner: |
|
133 |
req.throw_error(req.HTTP_FORBIDDEN) |
|
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
134 |
|
135 |
def authorize_public(req): |
|
136 |
"""A different kind of authorization. Rather than making sure the
|
|
267
by mattgiuca
Changed semantics of "published" property: Now applies to directories, not |
137 |
logged-in user owns the file, this checks if the file is in a published
|
138 |
directory.
|
|
139 |
||
140 |
This is for the "public mode" of the serve app.
|
|
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
141 |
|
142 |
Same interface as "authorize" - None on success, HTTP_FORBIDDEN exception
|
|
143 |
raised on failure.
|
|
144 |
"""
|
|
145 |
_, path = url_to_local(req.path) |
|
267
by mattgiuca
Changed semantics of "published" property: Now applies to directories, not |
146 |
dirpath, _ = os.path.split(path) |
147 |
if not published(dirpath): |
|
266
by mattgiuca
Added Publishing feature. This feature is complete except it currently isn't |
148 |
req.throw_error(req.HTTP_FORBIDDEN) |