56
56
self.serve(req, owner, jail, path)
58
58
def serve(self, req, owner, jail, path):
59
serve_file(req, owner, jail, path)
59
self.serve_file(req, owner, jail, path)
61
def authorize(self, req):
62
"""Given a request, checks whether req.username is allowed to
63
access req.path. Returns True on authz success, False on failure.
65
# Private mode authorization: standard (only logged in user can access
66
# their own files, and can access all of them).
67
return studpath.authorize(req, req.user)
69
def serve_file(self, req, owner, jail, path, download=False, files=None):
70
"""Serves a file, using one of three possibilities: interpreting it,
71
serving it directly, or denying it and returning a 403 Forbidden error.
72
No return value. Writes to req (possibly throwing an HTTP error).
74
req: An IVLE request object.
75
owner: The user who owns the file being served.
76
jail: The user's jail.
77
path: Filename in the jail.
78
download: Should the file be viewed in browser or downloaded
81
# We need a no-op trampoline run to ensure that the jail is mounted.
82
# Otherwise we won't be able to authorise for public mode!
83
noop_object = interpret.interpreter_objects["noop"]
84
interpret.interpret_file(req, owner, jail, '', noop_object)
86
# Authorize access. If failure, this throws a HTTP_FORBIDDEN error.
87
if not self.authorize(req):
94
if files and download:
95
args += [os.path.join(path, f) for f in files]
99
(out, err) = ivle.interpret.execute_raw(owner, jail, '/home',
100
os.path.join(ivle.conf.share_path, 'services/serveservice'),
104
# Remove the JSON from the front of the response, and decode it.
105
json = out.split('\n', 1)[0]
106
out = out[len(json) + 1:]
107
response = cjson.decode(json)
109
if 'error' in response:
110
if response['error'] == 'not-found':
112
elif response['error'] in ('is-directory', 'forbidden'):
114
elif response['error'] == 'is-executable':
115
# We need to execute it. Just run it with Python in the jail.
116
interp_object = interpret.interpreter_objects["cgi-python"]
117
interpret.interpret_file(req, owner, jail, response['path'],
118
interp_object, gentle=True)
121
raise AssertionError('Unknown error from serveservice: %s' %
125
req.headers_out["Content-Disposition"] = \
126
"attachment; filename=%s" % response['name']
127
req.content_type = response['type']
61
130
class DownloadView(ServeView):
62
131
def __init__(self, req, path):
70
139
def serve(self, req, owner, jail, path):
71
serve_file(req, owner, jail, path, download=True, files=self.files)
74
"""Given a request, checks whether req.username is allowed to
75
access req.path. Returns True on authorization success, False on failure.
77
# TODO: Reactivate public mode.
140
self.serve_file(req, owner, jail, path, download=True,files=self.files)
142
class PublicServeView(ServeView):
143
def __init__(self, req, path):
145
super(PublicServeView, self).__init__(req, path)
147
def authorize(self, req):
79
148
# Public mode authorization: any user can access any other user's
80
# files, BUT the accessed file needs to have its "ivle:published" flag
81
# turned on in the SVN status.
82
# studpath.authorize_public(req)
84
# Private mode authorization: standard (only logged in user can access
85
# their own files, and can access all of them).
86
return studpath.authorize(req, req.user)
88
def serve_file(req, owner, jail, path, download=False, files=None):
89
"""Serves a file, using one of three possibilities: interpreting the file,
90
serving it directly, or denying it and returning a 403 Forbidden error.
91
No return value. Writes to req (possibly throwing a server error exception
92
using req.throw_error).
94
req: An IVLE request object.
95
owner: The user who owns the file being served.
96
jail: The user's jail.
97
path: Filename in the jail.
98
download: Should the file be viewed in browser or downloaded
101
# We need a no-op trampoline run to ensure that the jail is mounted.
102
# Otherwise we won't be able to authorise for public mode!
103
noop_object = interpret.interpreter_objects["noop"]
104
interpret.interpret_file(req, owner, jail, '', noop_object)
106
# Authorize access. If failure, this throws a HTTP_FORBIDDEN error.
107
if not authorize(req):
114
if files and download:
115
args += [os.path.join(path, f) for f in files]
119
(out, err) = ivle.interpret.execute_raw(req.user, jail, '/home',
120
os.path.join(ivle.conf.share_path, 'services/serveservice'),
124
# Remove the JSON from the front of the response, and decode it.
125
json = out.split('\n', 1)[0]
126
out = out[len(json) + 1:]
127
response = cjson.decode(json)
129
if 'error' in response:
130
if response['error'] == 'not-found':
132
elif response['error'] in ('is-directory', 'forbidden'):
134
elif response['error'] == 'is-executable':
135
# We need to execute it. Just run it with Python in the jail.
136
interp_object = interpret.interpreter_objects["cgi-python"]
137
interpret.interpret_file(req, owner, jail, response['path'],
138
interp_object, gentle=True)
141
raise AssertionError('Unknown error from serveservice: %s' %
145
req.headers_out["Content-Disposition"] = \
146
"attachment; filename=%s" % response['name']
147
req.content_type = response['type']
150
class Plugin(ViewPlugin):
149
# files, BUT the accessed file needs to have a file named '.published'
150
# in its parent directory.
151
return studpath.authorize_public(req)
153
class Plugin(ViewPlugin, PublicViewPlugin):
152
155
('serve/*path', ServeView),
153
156
('download/*path', DownloadView),
160
('~*path', PublicServeView),