Skip to content

Commit 6453739

Browse files
authored
Use bytes to determine file types as a default (#14)
Fixe issue #13
1 parent d47bbed commit 6453739

File tree

6 files changed

+48
-6
lines changed

6 files changed

+48
-6
lines changed

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pytz = "*"
1414
flask = "*"
1515
pillow = ">=7.1.0"
1616
werkzeug = "*"
17+
filetype = "*"
1718

1819
[requires]
1920
python_version = "*"

Pipfile.lock

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flask_sieve/rules_processor.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pytz
88
import operator
99
import requests
10+
import filetype
1011

1112
from PIL import Image
1213
from dateutil.parser import parse as dateparse
@@ -231,7 +232,11 @@ def validate_extension(self, value, params, **kwargs):
231232
if not self.validate_file(value):
232233
return False
233234
self._assert_params_size(size=1, params=params, rule='extension')
234-
return value.filename.split('.')[-1].lower() == params[0]
235+
kind = filetype.guess(value.stream.read(512))
236+
value.seek(0)
237+
if kind is None:
238+
return value.filename.split('.')[-1].lower() == params[0]
239+
return kind.extension in params
235240

236241
@staticmethod
237242
def validate_file(value, **kwargs):
@@ -375,7 +380,11 @@ def validate_mime_types(self, value, params, **kwargs):
375380
if not self.validate_file(value):
376381
return False
377382
self._assert_params_size(size=1, params=params, rule='mime_types')
378-
return value.mimetype in params
383+
kind = filetype.guess(value.stream.read(512))
384+
value.seek(0)
385+
if kind is None:
386+
return value.mimetype in params
387+
return kind.mime in params
379388

380389
def validate_min(self, value, params, **kwargs):
381390
self._assert_params_size(size=1, params=params, rule='min')

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ click==7.1.2
44
coverage==5.2.1
55
coveralls==2.1.2
66
docopt==0.6.2
7+
filetype==1.0.7
78
Flask==1.1.2
89
idna==2.10
910
itsdangerous==1.1.0

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
name='flask-sieve',
66
description='A Laravel inspired requests validator for Flask',
77
long_description='Find the documentation at https://flask-sieve.readthedocs.io/en/latest/',
8-
version='1.1.2',
8+
version='1.1.3',
99
url='https://github.com/codingedward/flask-sieve',
1010
license='BSD-2',
1111
author='Edward Njoroge',
@@ -18,6 +18,7 @@
1818
'python-dateutil',
1919
'pytz',
2020
'requests',
21+
'filetype',
2122
],
2223
classifiers=[
2324
'Development Status :: 5 - Production/Stable',

tests/test_rules_processor.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
from flask_sieve.parser import Parser
77
from flask_sieve.rules_processor import RulesProcessor
88

9+
class FakeFileStream:
10+
def __init__(self, buf):
11+
self.buf = buf
12+
13+
def read(self, buf_size):
14+
return self.buf[:buf_size]
15+
16+
def seek(self, value):
17+
pass
18+
919

1020
class TestRulesProcessor(unittest.TestCase):
1121
def setUp(self):
@@ -19,7 +29,7 @@ def setUp(self):
1929
name='image'
2030
)
2131
self.invalid_file = FileStorage(
22-
stream=self.stream,
32+
stream=FakeFileStream(bytearray([0xFE, 0x58, 0x8F, 0x00, 0x08])),
2333
filename='invalid.png'
2434
)
2535

@@ -285,6 +295,10 @@ def test_validates_dimensions(self):
285295
rules={'field': ['dimensions:2x1']},
286296
request={'field': 'not a file'}
287297
)
298+
self.assert_fails(
299+
rules={'field': ['dimensions:1x1']},
300+
request={'field': self.invalid_file}
301+
)
288302

289303
def test_validates_distinct(self):
290304
self.assert_passes(
@@ -327,6 +341,10 @@ def test_validates_extension(self):
327341
rules={'field': ['extension:png']},
328342
request={'field': 1}
329343
)
344+
self.assert_fails(
345+
rules={'field': ['extension:tnp']},
346+
request={'field': self.invalid_file}
347+
)
330348

331349
def test_validates_email(self):
332350
self.assert_passes(
@@ -565,6 +583,10 @@ def test_validates_mime_types(self):
565583
rules={'field': ['mime_types:image/png']},
566584
request={'field': 1}
567585
)
586+
self.assert_fails(
587+
rules={'field': ['mime_types:image/xpng']},
588+
request={'field': self.invalid_file}
589+
)
568590

569591
def test_validates_min(self):
570592
self.assert_passes(

0 commit comments

Comments
 (0)