43
44
CGI_BLOCK_SIZE = 65535
45
def interpret_file(req, owner, filename, interpreter):
49
"""Get the unix uid corresponding to the given login name.
50
If it is not in the dictionary of uids, then consult the
51
database and retrieve an update of the user table."""
57
res = conn.get_all('login', ['login', 'unixid'])
59
return (flds['login'], flds['unixid'])
60
uids = dict(map(repack,res))
64
def interpret_file(req, owner, jail_dir, filename, interpreter):
46
65
"""Serves a file by interpreting it using one of IVLE's builtin
47
66
interpreters. All interpreters are intended to run in the user's jail. The
48
67
jail location is provided as an argument to the interpreter but it is up
51
70
req: An IVLE request object.
52
71
owner: Username of the user who owns the file being served.
53
filename: Filename in the local file system.
72
jail_dir: Absolute path to the user's jail.
73
filename: Absolute filename within the user's jail.
54
74
interpreter: A function object to call.
56
# Make sure the file exists (otherwise some interpreters may not actually
58
# Don't test for execute permission, that will only be required for
59
# certain interpreters.
60
if not os.access(filename, os.R_OK):
61
req.throw_error(req.HTTP_NOT_FOUND)
76
# We can't test here whether or not the target file actually exists,
77
# because the apache user may not have permission. Instead we have to
78
# rely on the interpreter generating an error.
79
if filename.startswith(os.sep):
80
filename_abs = filename
81
filename_rel = filename[1:]
83
filename_abs = os.path.join(os.sep, filename)
84
filename_rel = filename
63
86
# Get the UID of the owner of the file
64
87
# (Note: files are executed by their owners, not the logged in user.
65
88
# This ensures users are responsible for their own programs and also
66
89
# allows them to be executed by the public).
68
(_,_,uid,_,_,_,_) = pwd.getpwnam(owner)
70
# The user does not exist. This should have already failed the
72
req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR)
74
92
# Split up req.path again, this time with respect to the jail
75
(_, jail_dir, path) = studpath.url_to_jailpaths(req.path)
76
path = os.path.join('/', path)
77
(working_dir, _) = os.path.split(path)
93
(working_dir, _) = os.path.split(filename_abs)
78
94
# jail_dir is the absolute jail directory.
79
95
# path is the filename relative to the user's jail.
80
96
# working_dir is the directory containing the file relative to the user's
82
98
# (Note that paths "relative" to the jail actually begin with a '/' as
83
99
# they are absolute in the jailspace)
85
return interpreter(uid, jail_dir, working_dir, path, req)
101
return interpreter(uid, jail_dir, working_dir, filename_abs, req)
88
104
"""Stores flags regarding the state of reading CGI output."""
181
197
# Break data into lines of CGI header data.
182
198
linebuf = cgiflags.linebuf + data
183
199
# First see if we can split all header data
184
split = linebuf.split('\r\n\r\n', 1)
186
# Allow UNIX newlines instead
187
split = linebuf.split('\n\n', 1)
200
# We need to get the double CRLF- or LF-terminated headers, whichever
201
# is smaller, as either sequence may appear somewhere in the body.
202
usplit = linebuf.split('\n\n', 1)
203
wsplit = linebuf.split('\r\n\r\n', 1)
204
split = len(usplit[0]) > len(wsplit[0]) and wsplit or usplit
188
205
if len(split) == 1:
189
206
# Haven't seen all headers yet. Buffer and come back later.
190
207
cgiflags.linebuf = linebuf