datatracker/ietf/utils/validators.py
2019-07-15 15:37:48 +00:00

101 lines
3.8 KiB
Python

# Copyright The IETF Trust 2016-2019, All Rights Reserved
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
import os
import re
import magic
from pyquery import PyQuery
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.template.defaultfilters import filesizeformat
from django.utils.deconstruct import deconstructible
import debug # pyflakes:ignore
# Note that this is an instantiation of the regex validator, _not_ the
# regex-string validator defined right below
validate_no_control_chars = RegexValidator(
regex="^[^\x00-\x1f]*$",
message="Please enter a string without control characters." )
@deconstructible
class RegexStringValidator(object):
"Validates that a given regular expression can be compiled."
def __init__(self):
pass
def __call__(self, value):
"""
Validates that the given regular expression can be compiled.
"""
try:
re.compile(value)
except Exception as e:
raise ValidationError('Please enter a valid regular expression. '
'Got an error when trying to compile this: "%s" : "%s"'
% (value, e))
if '-*' in value:
raise ValidationError('Did you really mean that? The regular expression '
'contains "-*" which will match zero or more dashes. '
'Maybe you meant to write "-.*"? If you actually meant "-*", '
'you can use "[-]*" instead to get past this error.')
def __eq__(self, other):
return isinstance(other, RegexStringValidator)
def __ne__(self, other):
return not (self == other)
validate_regular_expression_string = RegexStringValidator()
def get_mime_type(content):
# try to fixup encoding
if hasattr(magic, "open"):
m = magic.open(magic.MAGIC_MIME)
m.load()
filetype = m.buffer(content)
else:
m = magic.Magic()
m.cookie = magic.magic_open(magic.MAGIC_NONE | magic.MAGIC_MIME | magic.MAGIC_MIME_ENCODING)
magic.magic_load(m.cookie, None)
filetype = m.from_buffer(content)
return filetype.split('; ', 1)
def validate_file_size(file):
if file._size > settings.SECR_MAX_UPLOAD_SIZE:
raise ValidationError('Please keep filesize under %s. Requested upload size was %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE), filesizeformat(file._size)))
def validate_mime_type(file, valid):
file.open()
raw = file.read()
mime_type, encoding = get_mime_type(raw)
# work around mis-identification of text where a line has 'virtual' as
# the first word:
if mime_type == 'text/x-c++' and re.search(br'(?m)^virtual\s', raw):
mod = raw.replace(b'virtual', b' virtual')
mime_type, encoding = get_mime_type(mod)
if valid and not mime_type in valid:
raise ValidationError('Found content with unexpected mime type: %s. Expected one of %s.' %
(mime_type, ', '.join(valid) ))
return mime_type, encoding
def validate_file_extension(file, valid):
name, ext = os.path.splitext(file.name)
if ext.lower() not in valid:
raise ValidationError('Found an unexpected extension: %s. Expected one of %s' % (ext, ','.join(valid)))
return ext
def validate_no_html_frame(file):
file.open()
q = PyQuery(file.read())
if q("frameset") or q("frame") or q("iframe"):
raise ValidationError('Found content with html frames. Please upload a file that does not use frames')