92
93
serve_file_direct(req, filename, type)
95
def serve_file_direct(req, filename, type):
96
"""Serves a file by directly writing it out to the response.
98
req: An IVLE request object.
99
filename: Filename in the local file system.
100
type: String. Mime type to serve the file with.
102
if not os.access(filename, os.R_OK):
103
req.throw_error(req.HTTP_NOT_FOUND)
104
req.content_type = type
105
req.sendfile(filename)
94
107
def interpret_file(req, owner, filename, interpreter):
95
108
"""Serves a file by interpreting it using one of IVLE's builtin
109
interpreters. All interpreters are intended to run in the user's jail. The
110
jail location is provided as an argument to the interpreter but it is up
111
to the individual interpreters to create the jail.
98
113
req: An IVLE request object.
99
114
owner: Username of the user who owns the file being served.
106
121
# certain interpreters.
107
122
if not os.access(filename, os.R_OK):
108
123
req.throw_error(req.HTTP_NOT_FOUND)
109
return interpreter(filename, req)
111
def serve_file_direct(req, filename, type):
112
"""Serves a file by directly writing it out to the response.
114
req: An IVLE request object.
115
filename: Filename in the local file system.
116
type: String. Mime type to serve the file with.
118
if not os.access(filename, os.R_OK):
119
req.throw_error(req.HTTP_NOT_FOUND)
120
req.content_type = type
121
req.sendfile(filename)
125
# Get the UID of the owner of the file
126
# (Note: files are executed by their owners, not the logged in user.
127
# This ensures users are responsible for their own programs and also
128
# allows them to be executed by the public).
130
(_,_,uid,_,_,_,_) = pwd.getpwnam(owner)
132
# The user does not exist. This should have already failed the
134
req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR)
136
# Split up req.path again, this time with respect to the jail
137
(_, jail_dir, path) = studpath.url_to_jailpaths(req.path)
138
(working_dir, _) = os.path.split(path)
139
# Now jail_dir is the jail directory relative to the jails root.
140
# Note that the trampoline has jails root hard-coded for security.
141
# path is the filename relative to the user's jail.
142
# working_dir is the directory containing the file relative to the user's
145
return interpreter(uid, jail_dir, working_dir, path, req)
123
147
# Used to store mutable data
127
def execute_cgi(filename, studentprog, req):
151
def execute_cgi(trampoline, uid, jail_dir, working_dir, script_path, req):
129
filename: Full path on the local system to the CGI wrapper program
153
trampoline: Full path on the local system to the CGI wrapper program
131
studentprog: Full path on the local system to the CGI student program
132
which will eventually be executed.
155
uid: User ID of the owner of the file.
156
jail_dir: Owner's jail directory relative to the jails root.
157
working_dir: Directory containing the script file relative to owner's
159
script_path: CGI script relative to the owner's jail.
133
160
req: IVLE request object.
135
162
The called CGI wrapper application shall be called using popen and receive
155
178
f.seek(0) # Rewind, for reading
157
pid = subprocess.Popen([filename, studentprog],
158
stdin=f, stdout=subprocess.PIPE, cwd=progdir)
180
# usage: tramp uid jail_dir working_dir script_path
181
pid = subprocess.Popen(
182
[trampoline, str(uid), jail_dir, working_dir, script_path],
183
stdin=f, stdout=subprocess.PIPE, cwd=tramp_dir)
160
185
# process_cgi_line: Reads a single line of CGI output and processes it.
161
186
# Prints to req, and also does fancy HTML warnings if Content-Type
254
# TODO: Replace mytest with cgi trampoline handler script
255
location_cgi_python = os.path.join(conf.ivlepath, "bin/mytest")
229
257
# Mapping of interpreter names (as given in conf/app/server.py) to
230
258
# interpreter functions.
232
260
interpreter_objects = {
234
: functools.partial(execute_cgi, '/usr/bin/python'),
262
: functools.partial(execute_cgi, location_cgi_python),
235
263
# Should also have:
237
265
# python-server-page