173
180
text = text.replace('"', '"')
174
181
text = text.replace(''', '\'')
185
def validate_file(attachment):
187
tmp_file_path = attachment.temporary_file_path()
190
def _split_mime(mime_type):
191
main, sub = mime_type.split('/', maxsplit=1)
192
return {'maintype': main, 'subtype': sub}
195
# Use PIL to determine if it is a valid image file
196
# works not for corrupted jpg
198
with Image.open(tmp_file_path) as im:
206
zip_obj = zipfile.ZipFile(tmp_file_path)
207
except zipfile.BadZipfile:
211
def _zip_contains(zip_parts):
212
# Check if each entry in zip_parts is inside the attachment
216
for obj in zip_parts:
223
# Main part of file checks
225
if attachment.size > pybb_settings.ATTACHMENT_SIZE_LIMIT:
226
raise ValidationError(
227
'Attachment is too big. We allow max %(size)s MiB',
229
'size': pybb_settings.ATTACHMENT_SIZE_LIMIT/1024/1024,
233
# Checks by file extension
234
splitted_fn = attachment.name.rsplit('.', maxsplit=2)
235
if len(splitted_fn) == 1:
236
raise ValidationError(
237
'We do not allow uploading files without an extension.'
240
ext = splitted_fn[-1]
241
if not ext in settings.ALLOWED_EXTENSIONS:
242
raise ValidationError(
243
'This type of file is not allowed.'
248
raise ValidationError(
249
'This seems to be a widelands map file. Please upload \
250
it at our maps section.'
253
# Widelands savegame (*.wgf) and widelands replay (*.wrpl.wgf)
255
if ext == 'wgf' and not splitted_fn[-2] == 'wrpl':
256
if not _zip_contains(settings.WGF_CONTENT_CHECK):
257
raise ValidationError(
258
'This is not a valid widelands savegame.'
263
raise ValidationError(
264
'This file is part of a replay. Please zip it together with \
265
the corresponding .wrpl.wgf file and upload again.'
269
if _is_zip() == None:
270
raise ValidationError(
271
'This is not a valid zip file.'
274
# Widelands AI configuration
276
wai = configparser.ConfigParser()
278
wai.read(tmp_file_path)
279
wai_sections = wai.sections()
280
if len(settings.ALLOWED_WAI_SECTIONS) == len(wai_sections):
281
for section in settings.ALLOWED_WAI_SECTIONS:
282
if section not in wai_sections:
287
raise ValidationError(
288
'This not a valid wai file.'
292
# Get MIME-Type from python-magic
293
magic_mime = magic.from_file(tmp_file_path, mime=True)
294
magic_mime = _split_mime(magic_mime)
295
send_mime = _split_mime(attachment.content_type)
297
# Check for valid image file. Use te mime-type provided by python-magic,
298
# because for a renamed image the wrong mime-type is send by the browser.
299
if magic_mime['maintype'] == 'image':
301
raise ValidationError(
302
'This is not a valid image: %(file)s',
303
params={'file': attachment.name}
306
# Compare Mime type send by browser and Mime type from python-magic.
307
# We only compare the main type (the first part) because the second
308
# part may not be recoginzed correctly. E.g. for .lua the submitted
309
# type is 'text/x-lua' but 'x-lua' is not official at all. See:
310
# https://www.iana.org/assignments/media-types/media-types.xhtml
311
# Unrecoginzed extension are always send with mime type
312
# 'application/octet-stream'. Skip if we know them.
313
if not ext in settings.SKIP_MIME_EXTENSIONS:
314
if not magic_mime['maintype'] == send_mime['maintype']:
315
raise ValidationError(
316
'The file %(file)s looks like %(send_mime)s, \
317
but we think it is %(magic_mime)s',
319
'file': attachment.name,
320
'send_mime': send_mime['maintype'],
321
'magic_mime': magic_mime['maintype'],