2010-06-26 17:01:22 +00:00
|
|
|
import os
|
|
|
|
|
|
2008-08-12 08:12:38 +00:00
|
|
|
from django import forms
|
|
|
|
|
from django.forms import widgets
|
2022-08-09 19:17:24 +00:00
|
|
|
from django.template.defaultfilters import filesizeformat
|
2008-08-12 08:12:38 +00:00
|
|
|
from django.utils.safestring import mark_safe
|
2022-01-27 20:22:00 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2023-02-22 18:39:28 +00:00
|
|
|
from PIL import Image, ImageOps
|
2008-08-12 08:12:38 +00:00
|
|
|
|
2013-09-13 15:59:52 +00:00
|
|
|
from avatar.conf import settings
|
2010-01-22 11:48:42 +00:00
|
|
|
from avatar.models import Avatar
|
2010-01-22 10:59:58 +00:00
|
|
|
|
2010-02-01 18:32:15 +00:00
|
|
|
|
2022-08-15 08:08:35 +00:00
|
|
|
def avatar_img(avatar, width, height):
|
|
|
|
|
if not avatar.thumbnail_exists(width, height):
|
|
|
|
|
avatar.create_thumbnail(width, height)
|
2022-07-16 20:50:05 +00:00
|
|
|
return mark_safe(
|
|
|
|
|
'<img src="%s" alt="%s" width="%s" height="%s" />'
|
2022-08-15 08:08:35 +00:00
|
|
|
% (avatar.avatar_url(width, height), str(avatar), width, height)
|
2022-07-16 20:50:05 +00:00
|
|
|
)
|
2013-08-01 11:12:49 +00:00
|
|
|
|
2008-08-12 08:12:38 +00:00
|
|
|
|
2010-01-22 10:59:58 +00:00
|
|
|
class UploadAvatarForm(forms.Form):
|
2013-08-01 11:19:56 +00:00
|
|
|
avatar = forms.ImageField(label=_("avatar"))
|
2013-08-01 11:12:49 +00:00
|
|
|
|
2010-01-22 10:59:58 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
2022-07-16 20:50:05 +00:00
|
|
|
self.user = kwargs.pop("user")
|
2022-08-15 08:08:35 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2013-08-01 11:12:49 +00:00
|
|
|
|
2010-01-22 10:59:58 +00:00
|
|
|
def clean_avatar(self):
|
2022-07-16 20:50:05 +00:00
|
|
|
data = self.cleaned_data["avatar"]
|
2013-09-13 15:59:52 +00:00
|
|
|
|
2022-08-15 10:00:59 +00:00
|
|
|
if settings.AVATAR_ALLOWED_MIMETYPES:
|
2013-07-18 22:34:57 +00:00
|
|
|
try:
|
|
|
|
|
import magic
|
|
|
|
|
except ImportError:
|
2022-08-15 10:00:59 +00:00
|
|
|
raise ImportError(
|
|
|
|
|
"python-magic library must be installed in order to use uploaded file content limitation"
|
|
|
|
|
)
|
2013-07-18 22:34:57 +00:00
|
|
|
|
|
|
|
|
# Construct 256 bytes needed for mime validation
|
2022-08-15 10:00:59 +00:00
|
|
|
magic_buffer = bytes()
|
2013-07-18 22:34:57 +00:00
|
|
|
for chunk in data.chunks():
|
|
|
|
|
magic_buffer += chunk
|
|
|
|
|
if len(magic_buffer) >= 256:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# https://github.com/ahupp/python-magic#usage
|
|
|
|
|
mime = magic.from_buffer(magic_buffer, mime=True)
|
2022-08-15 10:00:59 +00:00
|
|
|
if mime not in settings.AVATAR_ALLOWED_MIMETYPES:
|
|
|
|
|
raise forms.ValidationError(
|
|
|
|
|
_(
|
|
|
|
|
"File content is invalid. Detected: %(mimetype)s Allowed content types are: %(valid_mime_list)s"
|
|
|
|
|
)
|
|
|
|
|
% {
|
|
|
|
|
"valid_mime_list": ", ".join(settings.AVATAR_ALLOWED_MIMETYPES),
|
|
|
|
|
"mimetype": mime,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2013-09-13 15:59:52 +00:00
|
|
|
if settings.AVATAR_ALLOWED_FILE_EXTS:
|
|
|
|
|
root, ext = os.path.splitext(data.name.lower())
|
|
|
|
|
if ext not in settings.AVATAR_ALLOWED_FILE_EXTS:
|
|
|
|
|
valid_exts = ", ".join(settings.AVATAR_ALLOWED_FILE_EXTS)
|
2022-07-16 20:50:05 +00:00
|
|
|
error = _(
|
|
|
|
|
"%(ext)s is an invalid file extension. "
|
|
|
|
|
"Authorized extensions are : %(valid_exts_list)s"
|
|
|
|
|
)
|
|
|
|
|
raise forms.ValidationError(
|
|
|
|
|
error % {"ext": ext, "valid_exts_list": valid_exts}
|
|
|
|
|
)
|
2013-09-13 15:59:52 +00:00
|
|
|
|
|
|
|
|
if data.size > settings.AVATAR_MAX_SIZE:
|
2022-07-16 20:50:05 +00:00
|
|
|
error = _(
|
|
|
|
|
"Your file is too big (%(size)s), "
|
|
|
|
|
"the maximum allowed size is %(max_valid_size)s"
|
|
|
|
|
)
|
|
|
|
|
raise forms.ValidationError(
|
|
|
|
|
error
|
|
|
|
|
% {
|
|
|
|
|
"size": filesizeformat(data.size),
|
|
|
|
|
"max_valid_size": filesizeformat(settings.AVATAR_MAX_SIZE),
|
|
|
|
|
}
|
|
|
|
|
)
|
2013-08-01 11:12:49 +00:00
|
|
|
|
2023-02-22 18:39:28 +00:00
|
|
|
try:
|
|
|
|
|
image = Image.open(data)
|
|
|
|
|
ImageOps.exif_transpose(image)
|
|
|
|
|
except TypeError:
|
|
|
|
|
raise forms.ValidationError(_("Corrupted image"))
|
|
|
|
|
|
2010-01-22 11:48:42 +00:00
|
|
|
count = Avatar.objects.filter(user=self.user).count()
|
2019-12-03 14:43:31 +00:00
|
|
|
if 1 < settings.AVATAR_MAX_AVATARS_PER_USER <= count:
|
2022-07-16 20:50:05 +00:00
|
|
|
error = _(
|
|
|
|
|
"You already have %(nb_avatars)d avatars, "
|
|
|
|
|
"and the maximum allowed is %(nb_max_avatars)d."
|
|
|
|
|
)
|
|
|
|
|
raise forms.ValidationError(
|
|
|
|
|
error
|
|
|
|
|
% {
|
|
|
|
|
"nb_avatars": count,
|
|
|
|
|
"nb_max_avatars": settings.AVATAR_MAX_AVATARS_PER_USER,
|
|
|
|
|
}
|
|
|
|
|
)
|
2013-08-01 11:12:49 +00:00
|
|
|
return
|
|
|
|
|
|
2010-01-22 10:59:58 +00:00
|
|
|
|
2008-08-12 08:12:38 +00:00
|
|
|
class PrimaryAvatarForm(forms.Form):
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2022-07-16 20:50:05 +00:00
|
|
|
kwargs.pop("user")
|
2022-08-15 08:08:35 +00:00
|
|
|
width = kwargs.pop("width", settings.AVATAR_DEFAULT_SIZE)
|
|
|
|
|
height = kwargs.pop("height", settings.AVATAR_DEFAULT_SIZE)
|
2022-07-16 20:50:05 +00:00
|
|
|
avatars = kwargs.pop("avatars")
|
2022-08-15 08:08:35 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2022-07-16 20:50:05 +00:00
|
|
|
self.fields["choice"] = forms.ChoiceField(
|
2022-08-15 08:08:35 +00:00
|
|
|
choices=[(c.id, avatar_img(c, width, height)) for c in avatars],
|
|
|
|
|
widget=widgets.RadioSelect,
|
2022-07-16 20:50:05 +00:00
|
|
|
)
|
2008-08-12 08:12:38 +00:00
|
|
|
|
2013-08-01 11:12:49 +00:00
|
|
|
|
2008-08-12 08:12:38 +00:00
|
|
|
class DeleteAvatarForm(forms.Form):
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2022-07-16 20:50:05 +00:00
|
|
|
kwargs.pop("user")
|
2022-08-15 08:08:35 +00:00
|
|
|
width = kwargs.pop("width", settings.AVATAR_DEFAULT_SIZE)
|
|
|
|
|
height = kwargs.pop("height", settings.AVATAR_DEFAULT_SIZE)
|
2022-07-16 20:50:05 +00:00
|
|
|
avatars = kwargs.pop("avatars")
|
2022-08-15 08:08:35 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2022-07-16 20:50:05 +00:00
|
|
|
self.fields["choices"] = forms.MultipleChoiceField(
|
2022-08-15 08:08:35 +00:00
|
|
|
label=_("Choices"),
|
|
|
|
|
choices=[(c.id, avatar_img(c, width, height)) for c in avatars],
|
|
|
|
|
widget=widgets.CheckboxSelectMultiple,
|
2022-07-16 20:50:05 +00:00
|
|
|
)
|