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

« back to all changes in this revision

Viewing changes to ivle/studpath.py

  • Committer: drtomc
  • Date: 2008-01-31 08:11:37 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:352
Changed console so it no longer uses HTTP, just sends JSON over a normal socket.
Reason: Easier to control (since web.py offered limited control over *when* to Daemonise). Ultimately, this was necessary to get the port allocation strategy working.

* Replaced the HTTP / web.py code with socket code. (Web.py is no longer a dependency).
* Sundry bug fixes.
* Daemonization code - moved out of a Shell "&" call on the Apache side to a proper Daemon code on the spawned server side.

The upshot is we can now spawn any number of servers. Console is DONE for Alpha release.


YOU HAVE NO IDEA HOW TRICKY THIS WAS!!!

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(config, 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
 
    >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}}
55
 
    >>> url_to_local(stubconfig, '')
56
 
    (None, None)
57
 
    >>> url_to_local(stubconfig, 'joe/foo/bar/baz')
58
 
    ('joe', '/jails/joe/home/joe/foo/bar/baz')
59
 
    """
60
 
 
61
 
    # First normalise the path
62
 
    urlpath = os.path.normpath(urlpath)
63
 
    # Now if it begins with ".." or separator, then it's illegal
64
 
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
65
 
        return (None, None)
66
 
    # Note: User can be a group name. There is absolutely no difference in our
67
 
    # current directory scheme.
68
 
    (user, subpath) = util.split_path(urlpath)
69
 
    if user is None: return (None, None)
70
 
 
71
 
    # Join the user onto 'home' then the full path specified.
72
 
    # This results in the user's name being repeated twice, which is in
73
 
    # accordance with our directory scheme.
74
 
    # (The first time is the name of the jail, the second is the user's home
75
 
    # directory within the jail).
76
 
    path = os.path.join(config['paths']['jails']['mounts'],
77
 
                        user, 'home', urlpath)
78
 
 
79
 
    return (user, path)
80
 
 
81
 
def url_to_jailpaths(urlpath):
82
 
    """Given a URL path (part of a URL query string), returns a tuple of
83
 
        * the username of the student whose directory is being browsed
84
 
        * the absolute path where the jail will be located.
85
 
        * the path of the file relative to the jail.
86
 
 
87
 
    urlpath: See urlpath in url_to_local.
88
 
 
89
 
    >>> url_to_jailpaths("joe/mydir/myfile")
90
 
    ('joe', '/var/lib/ivle/jailmounts/joe', '/home/joe/mydir/myfile')
91
 
 
92
 
    >>> url_to_jailpaths("")
93
 
    (None, None, None)
94
 
    """
95
 
    # First normalise the path
96
 
    urlpath = os.path.normpath(urlpath)
97
 
    # Now if it begins with ".." then it's illegal
98
 
    if urlpath.startswith(".."):
99
 
        return (None, None, None)
100
 
    # Note: User can be a group name. There is absolutely no difference in our
101
 
    # current directory scheme.
102
 
    (user, subpath) = util.split_path(urlpath)
103
 
    if user is None: return (None, None, None)
104
 
 
105
 
    jail = os.path.join(ivle.conf.jail_base, user)
106
 
    path = os.path.join('/home', urlpath)
107
 
 
108
 
    return (user, jail, path)
109
 
 
110
 
def svnpublished(path):
111
 
    """Given a path on the LOCAL file system, determines whether the path has
112
 
    its "ivle:published" property active (in subversion). Returns True
113
 
    or False."""
114
 
    # Read SVN properties for this path
115
 
    try:
116
 
        props = svnclient.propget("ivle:published", path, recurse=False)
117
 
    except pysvn.ClientError:
118
 
        # Not under version control? Then it isn't published.
119
 
        return False
120
 
    return len(props) > 0
121
 
 
122
 
def published(path):
123
 
    """Given a path on the LOCAL file system, determines whether the path has a 
124
 
    '.published' file.  Returns True or False."""
125
 
    publish_file_path = os.path.join(path,'.published')
126
 
    return os.access(publish_file_path,os.F_OK)
127
 
 
128
 
def worldreadable(path):
129
 
    """Given a path on the LOCAL file system, determines whether the path is 
130
 
    world readble. Returns True or False."""
131
 
    try:
132
 
        mode = os.stat(path).st_mode
133
 
        if mode & stat.S_IROTH:
134
 
            return True
135
 
        else:
136
 
            return False
137
 
    except OSError, e:
138
 
        return False
139
 
 
140
 
 
141
 
def authorize(req, user):
142
 
    """Given a request, checks whether req.user is allowed to
143
 
    access req.path. Returns None on authorization success. Raises
144
 
    HTTP_FORBIDDEN on failure.
145
 
 
146
 
    This is for general authorization (assuming not in public mode; this is
147
 
    the standard auth code for fileservice, download and serve).
148
 
    """
149
 
    # TODO: Groups
150
 
    # First normalise the path
151
 
    urlpath = os.path.normpath(req.path)
152
 
    # Now if it begins with ".." or separator, then it's illegal
153
 
    if urlpath.startswith("..") or urlpath.startswith(os.sep):
154
 
        return False
155
 
 
156
 
    (owner, _) = util.split_path(urlpath)
157
 
    if user.login != owner:
158
 
        return False
159
 
    return True
160
 
 
161
 
def authorize_public(req):
162
 
    """A different kind of authorization. Rather than making sure the
163
 
    logged-in user owns the file, this checks if the file is in a published
164
 
    directory.
165
 
 
166
 
    This is for the "public mode" of the serve app.
167
 
 
168
 
    Same interface as "authorize" - None on success, HTTP_FORBIDDEN exception
169
 
    raised on failure.
170
 
    """
171
 
    _, path = url_to_local(req.config, req.path)
172
 
 
173
 
    # Walk up the tree, and find the deepest directory.
174
 
    while not os.path.isdir(path):
175
 
        path = os.path.dirname(path)
176
 
 
177
 
    if not (worldreadable(path) and published(path)):
178
 
        return False
179
 
    return True