summaryrefslogtreecommitdiffstats
path: root/venv/Lib/site-packages/flask_wtf/file.py
blob: b21669661c86927d279fc8de45fa8a053afa1312 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from collections import abc

from werkzeug.datastructures import FileStorage
from wtforms import FileField as _FileField
from wtforms.validators import DataRequired
from wtforms.validators import StopValidation
from wtforms.validators import ValidationError


class FileField(_FileField):
    """Werkzeug-aware subclass of :class:`wtforms.fields.FileField`."""

    def process_formdata(self, valuelist):
        valuelist = (x for x in valuelist if isinstance(x, FileStorage) and x)
        data = next(valuelist, None)

        if data is not None:
            self.data = data
        else:
            self.raw_data = ()


class FileRequired(DataRequired):
    """Validates that the data is a Werkzeug
    :class:`~werkzeug.datastructures.FileStorage` object.

    :param message: error message

    You can also use the synonym ``file_required``.
    """

    def __call__(self, form, field):
        if not (isinstance(field.data, FileStorage) and field.data):
            raise StopValidation(
                self.message or field.gettext("This field is required.")
            )


file_required = FileRequired


class FileAllowed:
    """Validates that the uploaded file is allowed by a given list of
    extensions or a Flask-Uploads :class:`~flaskext.uploads.UploadSet`.

    :param upload_set: A list of extensions or an
        :class:`~flaskext.uploads.UploadSet`
    :param message: error message

    You can also use the synonym ``file_allowed``.
    """

    def __init__(self, upload_set, message=None):
        self.upload_set = upload_set
        self.message = message

    def __call__(self, form, field):
        if not (isinstance(field.data, FileStorage) and field.data):
            return

        filename = field.data.filename.lower()

        if isinstance(self.upload_set, abc.Iterable):
            if any(filename.endswith("." + x) for x in self.upload_set):
                return

            raise StopValidation(
                self.message
                or field.gettext(
                    "File does not have an approved extension: {extensions}"
                ).format(extensions=", ".join(self.upload_set))
            )

        if not self.upload_set.file_allowed(field.data, filename):
            raise StopValidation(
                self.message
                or field.gettext("File does not have an approved extension.")
            )


file_allowed = FileAllowed


class FileSize:
    """Validates that the uploaded file is within a minimum and maximum
    file size (set in bytes).

    :param min_size: minimum allowed file size (in bytes). Defaults to 0 bytes.
    :param max_size: maximum allowed file size (in bytes).
    :param message: error message

    You can also use the synonym ``file_size``.
    """

    def __init__(self, max_size, min_size=0, message=None):
        self.min_size = min_size
        self.max_size = max_size
        self.message = message

    def __call__(self, form, field):
        if not (isinstance(field.data, FileStorage) and field.data):
            return

        file_size = len(field.data.read())
        field.data.seek(0)  # reset cursor position to beginning of file

        if (file_size < self.min_size) or (file_size > self.max_size):
            # the file is too small or too big => validation failure
            raise ValidationError(
                self.message
                or field.gettext(
                    "File must be between {min_size} and {max_size} bytes.".format(
                        min_size=self.min_size, max_size=self.max_size
                    )
                )
            )


file_size = FileSize