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 |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
37 |
|
1099.3.6
by William Grant
Move serve over to the new framework. It sort of works, except not. |
38 |
class ServeView(BaseView): |
39 |
def __init__(self, req, path): |
|
40 |
self.path = path |
|
41 |
||
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.
|
|
1273
by William Grant
Remove ivle.conf usage from ivle.studpath. |
49 |
(login, jail, path) = studpath.url_to_jailpaths(req.config, self.path) |
1099.3.6
by William Grant
Move serve over to the new framework. It sort of works, except not. |
50 |
|
51 |
owner = User.get_by_login(req.store, login) |
|
52 |
if not owner: |
|
53 |
# There is no user.
|
|
54 |
raise NotFound() |
|
55 |
||
1099.3.11
by William Grant
Implement a DownloadView. It mostly works. |
56 |
self.serve(req, owner, jail, path) |
57 |
||
58 |
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. |
59 |
self.serve_file(req, owner, jail, path) |
60 |
||
1099.1.169
by William Grant
Don't shadow the dispatch-called authorize() in ServeView. |
61 |
def path_authorize(self, req): |
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
62 |
"""Given a request, checks whether req.username is allowed to
|
63 |
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. |
64 |
|
65 |
This can't be done in the usual authorize(), because we rely on the
|
|
66 |
jail being mounted.
|
|
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
67 |
"""
|
68 |
# Private mode authorization: standard (only logged in user can access
|
|
69 |
# their own files, and can access all of them).
|
|
70 |
return studpath.authorize(req, req.user) |
|
71 |
||
72 |
def serve_file(self, req, owner, jail, path, download=False, files=None): |
|
73 |
"""Serves a file, using one of three possibilities: interpreting it,
|
|
74 |
serving it directly, or denying it and returning a 403 Forbidden error.
|
|
75 |
No return value. Writes to req (possibly throwing an HTTP error).
|
|
76 |
||
77 |
req: An IVLE request object.
|
|
78 |
owner: The user who owns the file being served.
|
|
79 |
jail: The user's jail.
|
|
80 |
path: Filename in the jail.
|
|
81 |
download: Should the file be viewed in browser or downloaded
|
|
82 |
"""
|
|
83 |
||
84 |
# We need a no-op trampoline run to ensure that the jail is mounted.
|
|
85 |
# Otherwise we won't be able to authorise for public mode!
|
|
86 |
noop_object = interpret.interpreter_objects["noop"] |
|
87 |
interpret.interpret_file(req, owner, jail, '', noop_object) |
|
88 |
||
89 |
# 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. |
90 |
if not self.path_authorize(req): |
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
91 |
raise Unauthorized() |
92 |
||
93 |
args = [] |
|
94 |
if download: |
|
95 |
args.append('-d') |
|
96 |
||
97 |
if files and download: |
|
98 |
args += [os.path.join(path, f) for f in files] |
|
99 |
else: |
|
100 |
args.append(path) |
|
101 |
||
1276
by William Grant
Drop ivle.conf usage from ivle.interpret. |
102 |
(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. |
103 |
os.path.join(req.config['paths']['share'], |
1224
by William Grant
Remove ivle.conf dependency from ivle.webapp.filesystem.serve. |
104 |
'services/serveservice'), |
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
105 |
args) |
106 |
assert not err |
|
107 |
||
108 |
# Remove the JSON from the front of the response, and decode it.
|
|
109 |
json = out.split('\n', 1)[0] |
|
110 |
out = out[len(json) + 1:] |
|
111 |
response = cjson.decode(json) |
|
112 |
||
113 |
if 'error' in response: |
|
114 |
if response['error'] == 'not-found': |
|
115 |
raise NotFound() |
|
116 |
elif response['error'] in ('is-directory', 'forbidden'): |
|
117 |
raise Forbidden() |
|
118 |
elif response['error'] == 'is-executable': |
|
119 |
# We need to execute it. Just run it with Python in the jail.
|
|
120 |
interp_object = interpret.interpreter_objects["cgi-python"] |
|
121 |
interpret.interpret_file(req, owner, jail, response['path'], |
|
122 |
interp_object, gentle=True) |
|
123 |
return
|
|
124 |
else: |
|
125 |
raise AssertionError('Unknown error from serveservice: %s' % |
|
126 |
response['error']) |
|
127 |
||
128 |
if download: |
|
129 |
req.headers_out["Content-Disposition"] = \ |
|
130 |
"attachment; filename=%s" % response['name'] |
|
131 |
req.content_type = response['type'] |
|
132 |
req.write(out) |
|
93
by mattgiuca
New directory hierarchy. |
133 |
|
1099.3.11
by William Grant
Implement a DownloadView. It mostly works. |
134 |
class DownloadView(ServeView): |
1099.3.12
by William Grant
Support downloading of a selection of files as a zip. |
135 |
def __init__(self, req, path): |
136 |
super(DownloadView, self).__init__(req, path) |
|
137 |
filelist = req.get_fieldstorage().getlist('path') |
|
138 |
if filelist: |
|
139 |
self.files = [f.value for f in filelist] |
|
140 |
else: |
|
141 |
self.files = None |
|
142 |
||
1099.3.11
by William Grant
Implement a DownloadView. It mostly works. |
143 |
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. |
144 |
self.serve_file(req, owner, jail, path, download=True,files=self.files) |
145 |
||
146 |
class PublicServeView(ServeView): |
|
147 |
def __init__(self, req, path): |
|
1099.1.148
by William Grant
Fix public mode serve authorization to traverse to the deepest directory, |
148 |
req.path = path # XXX: Needed because we don't have an app prefix. |
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
149 |
super(PublicServeView, self).__init__(req, path) |
150 |
||
151 |
def authorize(self, req): |
|
1099.1.203
by William Grant
Fix PublicServeView authorisation. |
152 |
# Only accessible in public mode.
|
153 |
return req.user is None |
|
154 |
||
155 |
def path_authorize(self, req): |
|
262
by mattgiuca
studpath: Added "authorize" function which checks the logged in user against |
156 |
# 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. |
157 |
# files, BUT the accessed file needs to have a file named '.published'
|
158 |
# in its parent directory.
|
|
159 |
return studpath.authorize_public(req) |
|
160 |
||
1099.1.203
by William Grant
Fix PublicServeView authorisation. |
161 |
# We don't want to redirect to a login page on Unauthorized.
|
162 |
@classmethod
|
|
163 |
def get_error_view(cls, e): |
|
164 |
return XHTMLErrorView |
|
165 |
||
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
166 |
class Plugin(ViewPlugin, PublicViewPlugin): |
1099.3.6
by William Grant
Move serve over to the new framework. It sort of works, except not. |
167 |
urls = [ |
1099.3.11
by William Grant
Implement a DownloadView. It mostly works. |
168 |
('serve/*path', ServeView), |
169 |
('download/*path', DownloadView), |
|
1099.3.6
by William Grant
Move serve over to the new framework. It sort of works, except not. |
170 |
]
|
1099.1.147
by William Grant
Provide a public serve view. Under /~user/path/to/script. How shiny. |
171 |
|
172 |
public_urls = [ |
|
173 |
('~*path', PublicServeView), |
|
174 |
]
|