diff --git a/app/test_files/image_with_exif_data.gif b/app/test_files/image_with_exif_data.gif new file mode 100644 index 0000000000000000000000000000000000000000..55609f4bf5f26b7569b7cab811489641cef6a882 Binary files /dev/null and b/app/test_files/image_with_exif_data.gif differ diff --git a/app/tests.py b/app/tests.py index 196b2104bdca9b781b3238a4df5cc4d5f13fefb5..de4dd9e0b836a028194d6cb4e7d4e3c4bb142f43 100644 --- a/app/tests.py +++ b/app/tests.py @@ -1,6 +1,7 @@ -import json +import json, tempfile, os from io import StringIO +from django.conf import settings from django.contrib.auth import get_user_model from django.core.exceptions import PermissionDenied, ValidationError from django.core.files.uploadedfile import SimpleUploadedFile @@ -19,6 +20,7 @@ from .views import (DaftarKatalog, DashboardKontributorView, DetailMateri, SuksesLoginKontributorView, SuntingProfilView, ProfilAdminView, PostsView, SuntingProfilAdminView, RevisiMateriView) from app.forms import SuntingProfilForm +from app.utils.fileManagementUtil import get_random_filename, remove_image_exifdata class DaftarKatalogTest(TestCase): @@ -1128,3 +1130,31 @@ class RatingMateriTest(TestCase): def test_score_in_rating_should_not_be_null(self): with self.assertRaises(TypeError): Rating(materi=self.materi1, user=self.user_one).save() + + +class fileManagementUtilTest(TestCase): + def setUp(self): + self.filename = "image_with_exif_data.gif" + self.file_content = open(settings.BASE_DIR + "/app/test_files/" + + self.filename, "rb").read() + + def test_get_random_filename_isCorrect(self): + generated_name = get_random_filename(self.filename) + + self.assertTrue(generated_name != self.filename) + # 40 from 36 expected name length + 4 from extension + self.assertEqual(len(generated_name), 40) + self.assertTrue(generated_name[-4:] == ".gif") + + def test_remove_image_exifdata_isCorrect(self): + with tempfile.TemporaryDirectory() as d: + image_with_exif_data_path = os.path.join(d, self.filename) + img = open(image_with_exif_data_path, "wb") + img.write(self.file_content) + img.close() + + remove_image_exifdata(image_with_exif_data_path) + sanitized_img = open(image_with_exif_data_path, "rb").read() + + self.assertTrue(len(sanitized_img) < len(self.file_content)) + self.assertTrue(b'<exif:' not in sanitized_img) diff --git a/app/utils/fileManagementUtil.py b/app/utils/fileManagementUtil.py new file mode 100644 index 0000000000000000000000000000000000000000..d693b01fea0cbd035f0fa6e7ef347cdac1d0373b --- /dev/null +++ b/app/utils/fileManagementUtil.py @@ -0,0 +1,17 @@ +import tempfile, random, datetime, string, hashlib,os +import PIL.Image as Image + +def get_random_filename(f_name): + ext = f_name.split(".")[-1] + name = ''.join(random.choices(string.ascii_lowercase , k=4)) + name += hashlib.md5((datetime.datetime.now().isoformat() + f_name).encode()).hexdigest() + + name = name + "." + ext + return name + +def remove_image_exifdata(f_path): + img = Image.open(f_path) + img.save(f_path) + return + + diff --git a/app/views.py b/app/views.py index 167f7c1c9f8fac5a7464ae085ab10853a48727e4..532239f9b6056087256b4f8c1d48937f69a1375a 100644 --- a/app/views.py +++ b/app/views.py @@ -19,6 +19,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from administration.models import VerificationReport from app.forms import SuntingProfilForm, UploadMateriForm from app.models import Category, Comment, Materi, Like, ViewStatistics, DownloadStatistics, ReqMaterial +from app.utils.fileManagementUtil import get_random_filename, remove_image_exifdata from authentication.models import User import django @@ -340,11 +341,26 @@ class SuntingProfilView(TemplateView): raise PermissionDenied(request) current_user = self.request.user + form = SuntingProfilForm( request.POST, request.FILES, instance=current_user) if form.is_valid(): current_user.default_profile_picture = True - form.save() + + # Removing exifdata from profile picture on upload + if request.FILES: + f_name = request.FILES['profile_picture'].name + f_name = get_random_filename(f_name) + f_path = settings.MEDIA_ROOT + "/" + f_name + request.FILES['profile_picture'].name = f_name + + form = SuntingProfilForm( + request.POST, request.FILES, instance=current_user) + form.save() + + remove_image_exifdata(f_path) + else: + form.save() return HttpResponseRedirect("/profil/") else: context = self.get_context_data(**kwargs) @@ -379,11 +395,26 @@ class SuntingProfilAdminView(TemplateView): raise PermissionDenied(request) current_user = self.request.user + form = SuntingProfilForm( request.POST, request.FILES, instance=current_user) if form.is_valid(): current_user.default_profile_picture = True - form.save() + + # Removing exifdata from profile picture on upload + if request.FILES: + f_name = request.FILES['profile_picture'].name + f_name = get_random_filename(f_name) + f_path = settings.MEDIA_ROOT + "/" + f_name + request.FILES['profile_picture'].name = f_name + + form = SuntingProfilForm( + request.POST, request.FILES, instance=current_user) + form.save() + + remove_image_exifdata(f_path) + else: + form.save() return HttpResponseRedirect("/profil-admin/") else: context = self.get_context_data(**kwargs)