51
45
# TODO: Nicer 404 message?
52
46
req.throw_error(req.HTTP_NOT_FOUND)
54
# If this type has a special interpreter, call that instead of just
55
# serving the content.
56
if type in executable_types:
57
return executable_types[type](path, req)
48
serve_file(req, user, path)
50
def serve_file(req, owner, filename):
51
"""Serves a file, using one of three possibilities: interpreting the file,
52
serving it directly, or denying it and returning a 403 Forbidden error.
53
No return value. Writes to req (possibly throwing a server error exception
54
using req.throw_error).
56
req: An IVLE request object.
57
owner: Username of the user who owns the file being served.
58
filename: Filename in the local file system.
61
# First get the mime type of this file
62
# (Note that importing common.util has already initialised mime types)
63
(type, _) = mimetypes.guess_type(filename)
65
type = conf.app.server.default_mimetype
67
# If this type is to be interpreted
68
if type in conf.app.server.interpreters:
69
interp_name = conf.app.server.interpreters[type]
71
# Get the interpreter function object
72
interp_object = interpreter_objects[interp_name]
74
# TODO: Nicer 500 message (this is due to bad configuration in
76
req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR)
77
interpret_file(req, owner, filename, interp_object)
59
req.content_type = type
80
# Otherwise, use the blacklist/whitelist to see if this file should be
81
# served or disallowed
82
if conf.app.server.blacklist_served_filetypes:
83
toserve = type not in conf.app.server.served_filetypes_blacklist
85
toserve = type in conf.app.server.served_filetypes_whitelist
87
# toserve or not toserve
89
# TODO: Nicer 403 message
90
req.throw_error(req.HTTP_FORBIDDEN)
92
serve_file_direct(req, filename, type)
94
def interpret_file(req, owner, filename, interpreter):
95
"""Serves a file by interpreting it using one of IVLE's builtin
98
req: An IVLE request object.
99
owner: Username of the user who owns the file being served.
100
filename: Filename in the local file system.
101
interpreter: A function object to call.
103
# Make sure the file exists (otherwise some interpreters may not actually
105
# Don't test for execute permission, that will only be required for
106
# certain interpreters.
107
if not os.access(filename, os.R_OK):
108
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)
62
123
# Used to store mutable data