47
46
self.message = message
48
47
self.args = (httpcode, message)
49
class IVLEJailError(Exception):
51
This exception indicates an error that occurred inside an IVLE CGI script
52
inside the jail. It should never be raised directly - only by the
55
Information will be retrieved from it, and then treated as a normal
58
def __init__(self, type_str, message, info):
59
self.type_str = type_str
60
self.message = message
63
class FakeObject(object):
64
""" A representation of an object that can't be Pickled """
65
def __init__(self, type, name, attrib={}):
71
return "<Fake %s %s>"%(self.type, self.name)
50
74
def make_path(path):
51
75
"""Given a path relative to the IVLE root, makes the path relative to the
52
76
site root using conf.root_dir. This path can be used in URLs sent to the
54
return os.path.join(root_dir, path)
78
return os.path.join(conf.root_dir, path)
56
80
def make_local_path(path):
57
81
"""Given a path relative to the IVLE root, on the local file system, makes
111
135
return tuple(splitpath)
137
def open_exercise_file(exercisename):
138
"""Given an exercise name, opens the corresponding XML file for reading.
139
Returns None if the exercise file was not found.
140
(For tutorials / worksheets).
142
# First normalise the path
143
exercisename = os.path.normpath(exercisename)
144
# Now if it begins with ".." or separator, then it's illegal
145
if exercisename.startswith("..") or exercisename.startswith(os.sep):
148
exercisefile = os.path.join(conf.exercises_base, exercisename)
151
return open(exercisefile)
152
except (TypeError, IOError): # TypeError if exercisefile == None
113
155
# Initialise mime types library
115
157
for (ext, mimetype) in conf.mimetypes.additional_mime_types.items():
134
176
return filename[filename.rindex('.')+1:].upper() + " file"
135
177
except ValueError:
180
def send_terms_of_service(req):
182
Sends the Terms of Service document to the req object.
183
This consults conf to find out where the TOS is located on disk, and sends
184
that. If it isn't found, it sends a generic message explaining to admins
185
how to create a real one.
188
req.sendfile(conf.tos_path)
191
"""<h1>Terms of Service</h1>
192
<p><b>*** SAMPLE ONLY ***</b></p>
193
<p>This is the text of the IVLE Terms of Service.</p>
194
<p>The administrator should create a license file with an appropriate
195
"Terms of Service" license for your organisation.</p>
196
<h2>Instructions for Administrators</h2>
197
<p>You are seeing this message because you have not configured a Terms of
198
Service document.</p>
199
<p>When you configured IVLE, you specified a path to the Terms of Service
200
document (this is found in <b><tt>lib/conf/conf.py</tt></b> under
201
"<tt>tos_path</tt>").</p>
202
<p>Create a file at this location; an HTML file with the appropriately-worded
204
<p>This should be a normal XHTML file, except it should not contain
205
<tt>html</tt>, <tt>head</tt> or <tt>body</tt> elements - it should
206
just be the contents of a body element (IVLE will wrap it accordingly).</p>
207
<p>This will automatically be used as the license text instead of this
208
placeholder text.</p>
211
def parse_iso8601(str):
212
"""Parses ISO8601 string into a datetime object."""
213
# FIXME: Terrific hack that means we only accept the format that is
214
# produced by json.js module when it encodes date objects.
215
return datetime.datetime.strptime(str, "%Y-%m-%dT%H:%M:%SZ")
217
def incomplete_utf8_sequence(byteseq):
220
Given a UTF-8-encoded byte sequence (str), returns the number of bytes at
221
the end of the string which comprise an incomplete UTF-8 character
224
If the string is empty or ends with a complete character OR INVALID
226
Otherwise, returns 1-3 indicating the number of bytes in the final
227
incomplete (but valid) character sequence.
229
Does not check any bytes before the final sequence for correctness.
231
>>> incomplete_utf8_sequence("")
233
>>> incomplete_utf8_sequence("xy")
235
>>> incomplete_utf8_sequence("xy\xc3\xbc")
237
>>> incomplete_utf8_sequence("\xc3")
239
>>> incomplete_utf8_sequence("\xbc\xc3")
241
>>> incomplete_utf8_sequence("xy\xbc\xc3")
243
>>> incomplete_utf8_sequence("xy\xe0\xa0")
245
>>> incomplete_utf8_sequence("xy\xf4")
247
>>> incomplete_utf8_sequence("xy\xf4\x8f")
249
>>> incomplete_utf8_sequence("xy\xf4\x8f\xa0")
254
for b in byteseq[::-1]:
258
# 0xxxxxxx (single-byte character)
261
elif b & 0xc0 == 0x80:
262
# 10xxxxxx (subsequent byte)
264
elif b & 0xe0 == 0xc0:
265
# 110xxxxx (start of 2-byte sequence)
268
elif b & 0xf0 == 0xe0:
269
# 1110xxxx (start of 3-byte sequence)
272
elif b & 0xf8 == 0xf0:
273
# 11110xxx (start of 4-byte sequence)
281
# Seen too many "subsequent bytes", invalid
285
# We never saw a "first byte", invalid
288
# We now know expect and count
290
# Complete, or we saw an invalid sequence