diff --git a/TODO b/TODO index 7176283c..80d42734 100644 --- a/TODO +++ b/TODO @@ -36,4 +36,5 @@ Template Readme -* add note about translations and fuzziness \ No newline at end of file +* add note about translations and fuzziness +* update: rebuild_index (search) command \ No newline at end of file diff --git a/spirit/forms/comment.py b/spirit/forms/comment.py index bd7062b1..c868c8e3 100644 --- a/spirit/forms/comment.py +++ b/spirit/forms/comment.py @@ -67,12 +67,16 @@ class CommentImageForm(forms.Form): image = forms.ImageField() + def __init__(self, user=None, *args, **kwargs): + super(CommentImageForm, self).__init__(*args, **kwargs) + self.user = user + def clean_image(self): image = self.cleaned_data["image"] - if Image.open(image).format.lower() not in settings.ST_ALLOWED_UPLOAD_IMAGES: + if Image.open(image).format.lower() not in settings.ST_ALLOWED_UPLOAD_IMAGE_FORMAT: raise forms.ValidationError(_("Unsupported file format. Supported formats are %s." - % ", ".join(settings.ST_ALLOWED_UPLOAD_IMAGES))) + % ", ".join(settings.ST_ALLOWED_UPLOAD_IMAGE_FORMAT))) image.seek(0) return image @@ -81,9 +85,14 @@ class CommentImageForm(forms.Form): image = self.cleaned_data["image"] hash = hashlib.md5(image.read()).hexdigest() name, ext = os.path.splitext(image.name) - image.name = u"".join((hash, ext)) - upload_to = os.path.join('spirit', 'images') - image.url = os.path.join(settings.MEDIA_URL, upload_to, image.name) + + # Remove the extension if not allowed + if ext and ext[1:].lower() not in settings.ST_ALLOWED_UPLOAD_IMAGE_EXT: + ext = "" + + image.name = u"".join((hash, ext.lower())) + upload_to = os.path.join('spirit', 'images', str(self.user.pk)) + image.url = os.path.join(settings.MEDIA_URL, upload_to, image.name).replace("\\", "/") media_path = os.path.join(settings.MEDIA_ROOT, upload_to) utils.mkdir_p(media_path) diff --git a/spirit/tests/tests_comment.py b/spirit/tests/tests_comment.py index 26c3aa50..34a7292d 100644 --- a/spirit/tests/tests_comment.py +++ b/spirit/tests/tests_comment.py @@ -331,13 +331,14 @@ class CommentViewTest(TestCase): img = StringIO('GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00' '\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;') files = {'image': SimpleUploadedFile('image.gif', img.read(), content_type='image/gif'), } - response = self.client.post(reverse('spirit:comment-image-upload'), + response = self.client.post(reverse('spirit:comment-image-upload-ajax'), HTTP_X_REQUESTED_WITH='XMLHttpRequest', data=files) res = json.loads(response.content) - self.assertEqual(res['url'], os.path.join(settings.MEDIA_URL, 'spirit', 'images', - "bf21c3043d749d5598366c26e7e4ab44.gif")) - os.remove(os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', "bf21c3043d749d5598366c26e7e4ab44.gif")) + self.assertEqual(res['url'], os.path.join(settings.MEDIA_URL, 'spirit', 'images', str(self.user.pk), + "bf21c3043d749d5598366c26e7e4ab44.gif").replace("\\", "/")) + os.remove(os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', str(self.user.pk), + "bf21c3043d749d5598366c26e7e4ab44.gif")) def test_comment_image_upload_invalid(self): """ @@ -348,7 +349,7 @@ class CommentViewTest(TestCase): image.name = 'image.gif' image.content_type = 'image/gif' files = {'image': SimpleUploadedFile(image.name, image.read()), } - response = self.client.post(reverse('spirit:comment-image-upload'), + response = self.client.post(reverse('spirit:comment-image-upload-ajax'), HTTP_X_REQUESTED_WITH='XMLHttpRequest', data=files) self.assertEqual(response.status_code, 404) @@ -495,12 +496,14 @@ class CommentFormTest(TestCase): img = StringIO(content) files = {'image': SimpleUploadedFile('image.gif', img.read(), content_type='image/gif'), } - form = CommentImageForm(data={}, files=files) + form = CommentImageForm(user=self.user, data={}, files=files) self.assertTrue(form.is_valid()) image = form.save() self.assertEqual(image.name, "bf21c3043d749d5598366c26e7e4ab44.gif") - self.assertEqual(image.url, os.path.join(settings.MEDIA_URL, 'spirit', 'images', image.name)) - image_path = os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', image.name) + image_url = os.path.join(settings.MEDIA_URL, 'spirit', 'images', str(self.user.pk), + image.name).replace("\\", "/") + self.assertEqual(image.url, image_url) + image_path = os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', str(self.user.pk), image.name) self.assertTrue(os.path.isfile(image_path)) image.open() self.assertEqual(image.read(), content) @@ -517,13 +520,27 @@ class CommentFormTest(TestCase): img = StringIO('GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00' '\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;') files = {'image': SimpleUploadedFile('image', img.read(), content_type='image/gif'), } - form = CommentImageForm(data={}, files=files) + form = CommentImageForm(user=self.user, data={}, files=files) self.assertTrue(form.is_valid()) image = form.save() self.assertEqual(image.name, "bf21c3043d749d5598366c26e7e4ab44") - os.remove(os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', image.name)) + os.remove(os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', str(self.user.pk), image.name)) - @override_settings(ST_ALLOWED_UPLOAD_IMAGES=['png', ]) + @override_settings(ST_ALLOWED_UPLOAD_IMAGE_EXT=[]) + def test_comment_image_upload_bad_extension(self): + """ + Image upload bad extensions are removed + """ + img = StringIO('GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00' + '\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;') + files = {'image': SimpleUploadedFile('image.gif', img.read(), content_type='image/gif'), } + form = CommentImageForm(user=self.user, data={}, files=files) + self.assertTrue(form.is_valid()) + image = form.save() + self.assertEqual(image.name, "bf21c3043d749d5598366c26e7e4ab44") + os.remove(os.path.join(settings.MEDIA_ROOT, 'spirit', 'images', str(self.user.pk), image.name)) + + @override_settings(ST_ALLOWED_UPLOAD_IMAGE_FORMAT=['png', ]) def test_comment_image_upload_not_allowed_format(self): """ Image upload, invalid format diff --git a/spirit/urls/__init__.py b/spirit/urls/__init__.py index e7677d03..75f0b899 100644 --- a/spirit/urls/__init__.py +++ b/spirit/urls/__init__.py @@ -3,6 +3,7 @@ from django.conf.urls import patterns, include, url import djconfig + from spirit.forms.admin import BasicConfigForm # TODO: use app loader in django 1.7 diff --git a/spirit/urls/comment.py b/spirit/urls/comment.py index 5c8c2c27..1915fe43 100644 --- a/spirit/urls/comment.py +++ b/spirit/urls/comment.py @@ -14,5 +14,5 @@ urlpatterns = patterns("spirit.views.comment", url(r'^(?P\d+)/delete/$', 'comment_delete', name='comment-delete'), url(r'^(?P\d+)/undelete/$', 'comment_delete', kwargs={'remove': False, }, name='comment-undelete'), - url(r'^upload/$', 'comment_image_upload', name='comment-image-upload'), + url(r'^upload/$', 'comment_image_upload_ajax', name='comment-image-upload-ajax'), ) \ No newline at end of file diff --git a/spirit/views/comment.py b/spirit/views/comment.py index 390df246..e10789be 100644 --- a/spirit/views/comment.py +++ b/spirit/views/comment.py @@ -106,11 +106,11 @@ def comment_find(request, pk): @require_POST @login_required -def comment_image_upload(request): +def comment_image_upload_ajax(request): if not request.is_ajax(): return Http404() - form = CommentImageForm(data=request.POST, files=request.FILES) + form = CommentImageForm(user=request.user, data=request.POST, files=request.FILES) if form.is_valid(): image = form.save()