[extensions-web/wip/ne0sight] extensions: restrict accepted images types
- From: Yuri Konotopov <ykonotopov src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [extensions-web/wip/ne0sight] extensions: restrict accepted images types
- Date: Fri, 29 May 2020 16:16:52 +0000 (UTC)
commit 99f792643f927e78658d671d5fd8645af2d09fd8
Author: Yuri Konotopov <ykonotopov gnome org>
Date: Fri May 29 20:16:38 2020 +0400
extensions: restrict accepted images types
sweettooth/extensions/form_fields.py | 33 +++++++++++++++++++++++++++++++++
sweettooth/extensions/forms.py | 21 ++++++++++++++++++++-
sweettooth/extensions/models.py | 25 +++++++++++++++++++------
sweettooth/extensions/views.py | 19 ++++++++++++++++---
4 files changed, 88 insertions(+), 10 deletions(-)
---
diff --git a/sweettooth/extensions/form_fields.py b/sweettooth/extensions/form_fields.py
new file mode 100644
index 0000000..3d21edc
--- /dev/null
+++ b/sweettooth/extensions/form_fields.py
@@ -0,0 +1,33 @@
+"""
+ GNOME Shell Extensions Repository
+ Copyright (C) 2020 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+
+from django.core.exceptions import ValidationError
+from django.forms.fields import ImageField
+
+class RestrictedImageField(ImageField):
+ def __init__(self, *, allowed_types=["gif", "jpeg", "png", "webp"], **kwargs):
+ self.allowed_types = allowed_types
+ super().__init__(**kwargs)
+
+ def to_python(self, data):
+ f = super().to_python(data)
+ if f is None or f.image is None:
+ return None
+
+ if f.image.format is None or not f.image.format.lower() in self.allowed_types:
+ raise ValidationError(
+ self.error_messages['invalid_image'],
+ code='invalid_image_type',
+ )
+
+ if hasattr(f, 'seek') and callable(f.seek):
+ f.seek(0)
+
+ return f
diff --git a/sweettooth/extensions/forms.py b/sweettooth/extensions/forms.py
index 67be262..fec95b0 100644
--- a/sweettooth/extensions/forms.py
+++ b/sweettooth/extensions/forms.py
@@ -1,5 +1,18 @@
+"""
+ GNOME Shell Extensions Repository
+ Copyright (C) 2011 Jasper St. Pierre <jstpierre mecheye net>
+ Copyright (C) 2020 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
from django import forms
+from django.core.validators import FileExtensionValidator
+
+from .form_fields import RestrictedImageField
class UploadForm(forms.Form):
source = forms.FileField(required=True)
@@ -23,5 +36,11 @@ I agree that GNOME Shell Extensions can remove, modify or reassign maintainershi
raise forms.ValidationError("You must agree to the GNOME Shell Extensions terms of service.")
return tos_compliant
+
class ImageUploadForm(forms.Form):
- file = forms.ImageField(required=True)
+ allowed_types = ["gif", "jpg", "jpeg", "png", "webp"]
+ file = RestrictedImageField(
+ required=True,
+ allowed_types=allowed_types,
+ validators=[FileExtensionValidator(allowed_types)]
+ )
diff --git a/sweettooth/extensions/models.py b/sweettooth/extensions/models.py
index ca09fb9..432350b 100644
--- a/sweettooth/extensions/models.py
+++ b/sweettooth/extensions/models.py
@@ -1,5 +1,20 @@
+"""
+ GNOME Shell Extensions Repository
+ Copyright (C) 2011-2013 Jasper St. Pierre <jstpierre mecheye net>
+ Copyright (C) 2019 Claude Paroz <claude 2xlibre net>
+ Copyright (C) 2016-2020 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+import autoslug
import json
+import os
+import re
+import zlib
from zipfile import ZipFile, BadZipfile
@@ -8,10 +23,6 @@ from django.db import models
from django.dispatch import Signal
from django.urls import reverse
-import autoslug
-import re
-import zlib
-
(STATUS_UNREVIEWED,
STATUS_REJECTED,
STATUS_INACTIVE,
@@ -82,11 +93,13 @@ def build_shell_version_array(versions):
def make_screenshot_filename(obj, filename=None):
- return "screenshots/screenshot_%d.png" % (obj.pk,)
+ ext = os.path.splitext(filename)[1].lower()
+ return "screenshots/screenshot_%d%s" % (obj.pk, ext)
def make_icon_filename(obj, filename=None):
- return "icons/icon_%d.png" % (obj.pk,)
+ ext = os.path.splitext(filename)[1].lower()
+ return "icons/icon_%d%s" % (obj.pk, ext)
class Extension(models.Model):
diff --git a/sweettooth/extensions/views.py b/sweettooth/extensions/views.py
index 0cc9eb6..da165e5 100644
--- a/sweettooth/extensions/views.py
+++ b/sweettooth/extensions/views.py
@@ -1,3 +1,13 @@
+"""
+ GNOME Shell Extensions Repository
+ Copyright (C) 2011-2016 Jasper St. Pierre <jstpierre mecheye net>
+ Copyright (C) 2016-2020 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
import json
from math import ceil
@@ -7,7 +17,7 @@ from django.core.paginator import Paginator, InvalidPage
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import transaction
-from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden,
HttpResponseServerError, Http404
+from django.http import JsonResponse, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden,
HttpResponseServerError, Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.views.decorators.http import require_POST
@@ -348,8 +358,11 @@ def validate_uploaded_image(request, extension):
form = ImageUploadForm(request.POST, request.FILES)
- if not form.is_valid() or form.cleaned_data['file'].size > 2*1024*1024:
- return HttpResponseForbidden()
+ if not form.is_valid():
+ return JsonResponse(form.errors.get_json_data(), status=403)
+
+ if form.cleaned_data['file'].size > 2*1024*1024:
+ return HttpResponseForbidden(content="Too big image")
return form.cleaned_data['file']
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]