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

93 by mattgiuca
New directory hierarchy.
1
# IVLE
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
# App: server
19
# Author: Tom Conway, Matt Giuca
20
# Date: 13/12/2007
21
22
# Serves content to the user (acting as a web server for students files).
23
# For most file types we just serve the static file, but
24
# for python files, we evaluate the python script inside
25
# our safe execution environment.
26
130 by mattgiuca
server: Imports os module correctly (needed by serve_file_directly).
27
import os
93 by mattgiuca
New directory hierarchy.
28
1099.3.7 by William Grant
Fix ServeView to use the new serveservice protocol.
29
import cjson
30
1099.3.15 by William Grant
Remove interpretservice, and clean up ivle.webapp.filesystem.serve.
31
from ivle import (studpath, interpret)
1080.1.65 by William Grant
www/apps/server: Don't use ivle.interpret.get_uid() just to check that a user
32
from ivle.database import User
1099.3.6 by William Grant
Move serve over to the new framework. It sort of works, except not.
33
from ivle.webapp.base.views import BaseView
1099.1.203 by William Grant
Fix PublicServeView authorisation.
34
from ivle.webapp.base.xhtml import XHTMLErrorView
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
35
from ivle.webapp.base.plugins import ViewPlugin, PublicViewPlugin
1099.3.6 by William Grant
Move serve over to the new framework. It sort of works, except not.
36
from ivle.webapp.errors import NotFound, Unauthorized, Forbidden
1294.2.57 by William Grant
Serve/Download done too.
37
from ivle.webapp import ApplicationRoot
38
1099.3.6 by William Grant
Move serve over to the new framework. It sort of works, except not.
39
class ServeView(BaseView):
1294.2.60 by William Grant
Move the already-ported filesystem views to use subpaths.
40
    subpath_allowed = True
41
1099.3.6 by William Grant
Move serve over to the new framework. It sort of works, except not.
42
    def authorize(self, req):
43
        return req.user is not None
44
45
    def render(self, req):
46
        """Handler for the Server application which serves pages."""
47
        # Get the username of the student whose work we are browsing, and the
48
        # path on the local machine where the file is stored.
1294.2.57 by William Grant
Serve/Download done too.
49
        (login, jail, path) = studpath.url_to_jailpaths(req.config,
1294.2.60 by William Grant
Move the already-ported filesystem views to use subpaths.
50
                                                        self.path)
1099.3.6 by William Grant
Move serve over to the new framework. It sort of works, except not.
51
52
        owner = User.get_by_login(req.store, login)
53
        if not owner:
54
            # There is no user.
55
            raise NotFound()
56
1099.3.11 by William Grant
Implement a DownloadView. It mostly works.
57
        self.serve(req, owner, jail, path)
58
1294.2.60 by William Grant
Move the already-ported filesystem views to use subpaths.
59
    @property
60
    def path(self):
61
        return os.path.join(*self.subpath) if self.subpath else ''
62
1099.3.11 by William Grant
Implement a DownloadView. It mostly works.
63
    def serve(self, req, owner, jail, path):
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
64
        self.serve_file(req, owner, jail, path)
65
1099.1.169 by William Grant
Don't shadow the dispatch-called authorize() in ServeView.
66
    def path_authorize(self, req):
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
67
        """Given a request, checks whether req.username is allowed to
68
        access req.path. Returns True on authz success, False on failure.
1099.1.169 by William Grant
Don't shadow the dispatch-called authorize() in ServeView.
69
70
        This can't be done in the usual authorize(), because we rely on the
71
        jail being mounted.
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
72
        """
73
        # Private mode authorization: standard (only logged in user can access
74
        # their own files, and can access all of them).
75
        return studpath.authorize(req, req.user)
76
77
    def serve_file(self, req, owner, jail, path, download=False, files=None):
78
        """Serves a file, using one of three possibilities: interpreting it,
79
        serving it directly, or denying it and returning a 403 Forbidden error.
80
        No return value. Writes to req (possibly throwing an HTTP error).
81
82
        req: An IVLE request object.
83
        owner: The user who owns the file being served.
84
        jail: The user's jail.
85
        path: Filename in the jail.
86
        download:  Should the file be viewed in browser or downloaded
87
        """
88
89
        # We need a no-op trampoline run to ensure that the jail is mounted.
90
        # Otherwise we won't be able to authorise for public mode!
91
        noop_object = interpret.interpreter_objects["noop"]
92
        interpret.interpret_file(req, owner, jail, '', noop_object)
93
94
        # Authorize access. If failure, this throws a HTTP_FORBIDDEN error.
1099.1.169 by William Grant
Don't shadow the dispatch-called authorize() in ServeView.
95
        if not self.path_authorize(req):
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
96
            raise Unauthorized()
97
98
        args = []
99
        if download:
100
            args.append('-d')
101
102
        if files and download:
103
            args += [os.path.join(path, f) for f in files]
104
        else:
105
            args.append(path)
106
1276 by William Grant
Drop ivle.conf usage from ivle.interpret.
107
        (out, err) = interpret.execute_raw(req.config, owner, jail, '/home',
1250 by William Grant
Unbreak serve - it was depending on the old names of a module.
108
                    os.path.join(req.config['paths']['share'],
1224 by William Grant
Remove ivle.conf dependency from ivle.webapp.filesystem.serve.
109
                                 'services/serveservice'),
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
110
                    args)
111
        assert not err
112
113
        # Remove the JSON from the front of the response, and decode it.
114
        json = out.split('\n', 1)[0]
115
        out = out[len(json) + 1:]
116
        response = cjson.decode(json)
117
118
        if 'error' in response:
119
            if response['error'] == 'not-found':
120
                raise NotFound()
121
            elif response['error'] in ('is-directory', 'forbidden'):
122
                raise Forbidden()
123
            elif response['error'] == 'is-executable':
124
                # We need to execute it. Just run it with Python in the jail.
125
                interp_object = interpret.interpreter_objects["cgi-python"]
126
                interpret.interpret_file(req, owner, jail, response['path'],
127
                                         interp_object, gentle=True)
128
                return
129
            else:
130
                raise AssertionError('Unknown error from serveservice: %s' %
131
                                     response['error'])
132
133
        if download:
134
            req.headers_out["Content-Disposition"] = \
135
                         "attachment; filename=%s" % response['name']
136
        req.content_type = response['type']
137
        req.write(out)
93 by mattgiuca
New directory hierarchy.
138
1099.3.11 by William Grant
Implement a DownloadView. It mostly works.
139
class DownloadView(ServeView):
1294.2.60 by William Grant
Move the already-ported filesystem views to use subpaths.
140
    def __init__(self, req, context, subpath=None):
141
        super(DownloadView, self).__init__(req, context, subpath)
1099.3.12 by William Grant
Support downloading of a selection of files as a zip.
142
        filelist = req.get_fieldstorage().getlist('path')
143
        if filelist:
144
            self.files = [f.value for f in filelist]
145
        else:
146
            self.files = None
147
1099.3.11 by William Grant
Implement a DownloadView. It mostly works.
148
    def serve(self, req, owner, jail, path):
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
149
        self.serve_file(req, owner, jail, path, download=True,files=self.files)
150
151
class PublicServeView(ServeView):
1294.2.139 by William Grant
Revive PublicServeView.
152
    def __init__(self, req, context, subpath=None):
153
        # XXX: Prepend the username to the path, since the authorization
154
        # code expects that, but req.path drops the first path segment
155
        # for historical reasons.
156
        req.path = os.path.join(context.login, req.path)
157
        super(PublicServeView, self).__init__(req, context, subpath)
158
159
    @property
160
    def path(self):
161
        # XXX: Prepend the username again. See above for explanation.
162
        return os.path.join(
163
            self.context.login, super(PublicServeView, self).path)
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
164
165
    def authorize(self, req):
1099.1.203 by William Grant
Fix PublicServeView authorisation.
166
        # Only accessible in public mode.
167
        return req.user is None
168
169
    def path_authorize(self, req):
262 by mattgiuca
studpath: Added "authorize" function which checks the logged in user against
170
        # Public mode authorization: any user can access any other user's
1099.1.147 by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny.
171
        # files, BUT the accessed file needs to have a file named '.published'
172
        # in its parent directory.
173
        return studpath.authorize_public(req)
174
175
class Plugin(ViewPlugin, PublicViewPlugin):
1294.2.60 by William Grant
Move the already-ported filesystem views to use subpaths.
176
    views = [(ApplicationRoot, 'serve', ServeView),
177
             (ApplicationRoot, 'download', DownloadView)
1294.2.57 by William Grant
Serve/Download done too.
178
             ]
179
1294.2.139 by William Grant
Revive PublicServeView.
180
    public_views = [(User, None, PublicServeView)]