Skip to content

Commit cce13d2

Browse files
authored
fix: Allow Image.MAX_IMAGE_PIXELS to be None (#1475)
* Fix #1377 * fix: `Image.MAX_IMAGE_SIZE = None` allowed. * Improve warning message * Add test.
1 parent 4d8de83 commit cce13d2

File tree

2 files changed

+48
-5
lines changed

2 files changed

+48
-5
lines changed

filer/models/abstract.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import logging
22

33
from django.conf import settings
4+
from django.core.checks import Warning, register as register_check
45
from django.core.exceptions import ValidationError
56
from django.db import models
67
from django.utils.functional import cached_property
78
from django.utils.translation import gettext_lazy as _
89

10+
911
import easy_thumbnails.utils
1012
from easy_thumbnails.VIL import Image as VILImage
1113
from PIL.Image import MAX_IMAGE_PIXELS
@@ -24,10 +26,24 @@
2426
# as if we allow it, it will fail while thumbnailing (first in the admin thumbnails
2527
# and then in the page itself.
2628
# Refer this https://github.com/python-pillow/Pillow/blob/b723e9e62e4706a85f7e44cb42b3d838dae5e546/src/PIL/Image.py#L3148
27-
FILER_MAX_IMAGE_PIXELS = min(
28-
getattr(settings, "FILER_MAX_IMAGE_PIXELS", MAX_IMAGE_PIXELS),
29-
MAX_IMAGE_PIXELS,
30-
)
29+
FILER_MAX_IMAGE_PIXELS = getattr(settings, "FILER_MAX_IMAGE_PIXELS", MAX_IMAGE_PIXELS)
30+
if MAX_IMAGE_PIXELS is not None:
31+
FILER_MAX_IMAGE_PIXELS = min(FILER_MAX_IMAGE_PIXELS, MAX_IMAGE_PIXELS)
32+
33+
34+
@register_check()
35+
def max_pixel_setting_check(app_configs, **kwargs):
36+
if not FILER_MAX_IMAGE_PIXELS:
37+
return [
38+
Warning(
39+
"Both settings.FILER_MAX_IMAGE_PIXELS and PIL.Image.MAX_IMAGE_PIXELS are not set.",
40+
hint="Set FILER_MAX_IMAGE_PIXELS to a positive integer value in your settings.py. "
41+
"This setting is used to limit the maximum number of pixels an image can have "
42+
"to protect your site from memory bombs.",
43+
obj=settings,
44+
)
45+
]
46+
return []
3147

3248

3349
class BaseImage(File):
@@ -130,7 +146,7 @@ def clean(self):
130146
# the image gets attached to a folder and saved. We also
131147
# send the error msg in the JSON and also post the message
132148
# so that they know what is wrong with the image they uploaded
133-
if not self.file:
149+
if not self.file or not FILER_MAX_IMAGE_PIXELS:
134150
return
135151

136152
if self._width is None or self._height is None:

tests/test_admin.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,33 @@ def test_filer_ajax_decompression_bomb(self):
565565

566566
abstract.FILER_MAX_IMAGE_PIXELS = DEFAULT_MAX_IMAGE_PIXELS
567567

568+
def test_filer_max_pixel_deactivation(self):
569+
from django.core.checks import Warning
570+
571+
DEFAULT_MAX_IMAGE_PIXELS = abstract.FILER_MAX_IMAGE_PIXELS
572+
abstract.FILER_MAX_IMAGE_PIXELS = None # Deactivate
573+
574+
self.assertEqual(Image.objects.count(), 0)
575+
folder = Folder.objects.create(name='foo')
576+
with open(self.filename, 'rb') as fh:
577+
file_obj = django.core.files.File(fh)
578+
url = reverse(
579+
'admin:filer-ajax_upload',
580+
kwargs={'folder_id': folder.pk}
581+
) + '?filename=%s' % self.image_name
582+
self.client.post(
583+
url,
584+
data=file_obj.read(),
585+
content_type='image/jpeg',
586+
**{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
587+
)
588+
self.assertEqual(Image.objects.count(), 1) # Success
589+
check_result = abstract.max_pixel_setting_check(None)
590+
self.assertEqual(len(check_result), 1)
591+
self.assertIsInstance(check_result[0], Warning)
592+
593+
abstract.FILER_MAX_IMAGE_PIXELS = DEFAULT_MAX_IMAGE_PIXELS
594+
568595
def test_filer_ajax_upload_file_using_content_type(self):
569596
self.assertEqual(Image.objects.count(), 0)
570597
folder = Folder.objects.create(name='foo')

0 commit comments

Comments
 (0)