We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Magic is incorrectly using image/svg as MIME type for SVG files, preventing uploads of SVG files
Magic or libmagic is incorrectly using `image/svg` as the MIME type for SVG uploads, rather than `image/svg+xml`, which is the only correct MIME type [1] (and the one we've always used in the past).

Normally, we keep SVG uploads disabled for security reasons since SVG can contain JavaScript code. However, we like to use it for diagrams and the like because they can be translated, and they are more efficient for that purpose in many cases. When we want to upload SVG, we go to the admin panel in Django and in the Constance panel, add "image/svg+xml" to the `WIKI_ATTACHMENT_ALLOWED_TYPES` string. Then we upload the file and restore the previous string to that preference.

This is no longer working; even with `image/svg+xml` listed in the preference, uploads fail with an error announcing that "Files of this type are not permitted." This should work, however.

This issue is blocking work on WebXR and potentially other documentation that requires the use of diagrams to explain things properly. Hopefully the fix is not complicated.

[1] https://www.iana.org/assignments/media-types/media-types.xhtml#image

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kuma/attachments/forms.py`
Content:
```
1 import magic
2 from constance import config
3 from django import forms
4 from django.core.validators import EMPTY_VALUES
5 from django.utils.translation import ugettext_lazy as _
6 
7 from .models import AttachmentRevision
8 
9 
10 MIME_TYPE_INVALID = _('Files of this type are not permitted.')
11 
12 
13 class AttachmentRevisionForm(forms.ModelForm):
14     """
15     Unlike the DocumentForm/RevisionForm split, we have only one
16     form for file attachments. The handling view will determine if
17     this is a new revision of an existing file, or the first version
18     of a new file.
19 
20     As a result of this, calling save(commit=True) is off-limits.
21     """
22     class Meta:
23         model = AttachmentRevision
24         fields = ('file', 'title', 'description', 'comment')
25 
26     def __init__(self, *args, **kwargs):
27         super(AttachmentRevisionForm, self).__init__(*args, **kwargs)
28         self.mime_type = None
29 
30     def clean(self):
31         """
32         Check the submitted file for its MIME type in case the provided
33         MIME type is missing or is the default MIME type as given in the
34         model field definition.
35 
36         That allows overriding the MIME type via the admin UI.
37         """
38         cleaned_data = super(AttachmentRevisionForm, self).clean()
39         nulls = EMPTY_VALUES + (AttachmentRevision.DEFAULT_MIME_TYPE,)
40         submitted_mime_type = cleaned_data.get('mime_type')
41 
42         if (submitted_mime_type in nulls) and ('file' in cleaned_data):
43             self.mime_type = self.mime_type_from_file(cleaned_data['file'])
44             allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()
45             if self.mime_type not in allowed_mime_types:
46                 raise forms.ValidationError(MIME_TYPE_INVALID, code='invalid')
47 
48         return cleaned_data
49 
50     def save(self, *args, **kwargs):
51         revision = super(AttachmentRevisionForm, self).save(*args, **kwargs)
52         if self.mime_type is not None:
53             revision.mime_type = self.mime_type
54         return revision
55 
56     def mime_type_from_file(self, file):
57         m_mime = magic.Magic(mime=True)
58         mime_type = m_mime.from_buffer(file.read(1024)).split(';')[0]
59         file.seek(0)
60         return mime_type
61 
62 
63 class AdminAttachmentRevisionForm(AttachmentRevisionForm):
64     class Meta(AttachmentRevisionForm.Meta):
65         fields = ['attachment', 'file', 'title', 'mime_type', 'description',
66                   'is_approved']
67
```

Path: `kuma/attachments/views.py`
Content:
```
1 import mimetypes
2 
3 from django.conf import settings
4 from django.core.exceptions import PermissionDenied
5 from django.http import Http404, StreamingHttpResponse
6 from django.shortcuts import get_object_or_404, redirect, render
7 from django.views.decorators.cache import cache_control, never_cache
8 from django.views.decorators.clickjacking import xframe_options_sameorigin
9 
10 from kuma.core.decorators import (ensure_wiki_domain, login_required,
11                                   shared_cache_control)
12 from kuma.core.utils import is_untrusted
13 from kuma.wiki.decorators import process_document_path
14 from kuma.wiki.models import Document
15 
16 from .forms import AttachmentRevisionForm
17 from .models import Attachment
18 from .utils import allow_add_attachment_by, convert_to_http_date
19 
20 
21 # Mime types used on MDN
22 OVERRIDE_MIMETYPES = {
23     'image/jpeg': '.jpeg, .jpg, .jpe',
24     'image/vnd.adobe.photoshop': '.psd',
25 }
26 
27 IMAGE_MIMETYPES = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']
28 
29 
30 def guess_extension(_type):
31     return OVERRIDE_MIMETYPES.get(_type, mimetypes.guess_extension(_type))
32 
33 
34 @cache_control(public=True, max_age=60 * 15)
35 def raw_file(request, attachment_id, filename):
36     """
37     Serve up an attachment's file.
38     """
39     qs = Attachment.objects.select_related('current_revision')
40     attachment = get_object_or_404(qs, pk=attachment_id)
41     if attachment.current_revision is None:
42         raise Http404
43 
44     if is_untrusted(request):
45         rev = attachment.current_revision
46         response = StreamingHttpResponse(rev.file, content_type=rev.mime_type)
47         response['Content-Length'] = rev.file.size
48         response['Last-Modified'] = convert_to_http_date(rev.created)
49         response['X-Frame-Options'] = 'ALLOW-FROM %s' % settings.DOMAIN
50         return response
51 
52     return redirect(attachment.get_file_url(), permanent=True)
53 
54 
55 @shared_cache_control(s_maxage=60 * 60 * 24 * 30)
56 def mindtouch_file_redirect(request, file_id, filename):
57     """Redirect an old MindTouch file URL to a new kuma file URL."""
58     attachment = get_object_or_404(Attachment, mindtouch_attachment_id=file_id)
59     return redirect(attachment.get_file_url(), permanent=True)
60 
61 
62 @ensure_wiki_domain
63 @never_cache
64 @xframe_options_sameorigin
65 @login_required
66 @process_document_path
67 def edit_attachment(request, document_slug, document_locale):
68     """
69     Create a new Attachment object and populate its initial
70     revision or show a separate form view that allows to fix form submission
71     errors.
72 
73     Redirects back to the document's editing URL on success.
74     """
75     document = get_object_or_404(
76         Document,
77         locale=document_locale,
78         slug=document_slug,
79     )
80     if request.method != 'POST':
81         return redirect(document.get_edit_url())
82 
83     # No access if no permissions to upload
84     if not allow_add_attachment_by(request.user):
85         raise PermissionDenied
86 
87     form = AttachmentRevisionForm(data=request.POST, files=request.FILES)
88     if form.is_valid():
89         revision = form.save(commit=False)
90         revision.creator = request.user
91         attachment = Attachment.objects.create(title=revision.title)
92         revision.attachment = attachment
93         revision.save()
94         # adding the attachment to the document's files (M2M)
95         attachment.attach(document, request.user, revision)
96         return redirect(document.get_edit_url())
97     else:
98         context = {
99             'form': form,
100             'document': document,
101         }
102         return render(request, 'attachments/edit_attachment.html', context)
103
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kuma/attachments/forms.py b/kuma/attachments/forms.py
--- a/kuma/attachments/forms.py
+++ b/kuma/attachments/forms.py
@@ -24,6 +24,7 @@
         fields = ('file', 'title', 'description', 'comment')
 
     def __init__(self, *args, **kwargs):
+        self.allow_svg_uploads = kwargs.pop('allow_svg_uploads', False)
         super(AttachmentRevisionForm, self).__init__(*args, **kwargs)
         self.mime_type = None
 
@@ -39,11 +40,21 @@
         nulls = EMPTY_VALUES + (AttachmentRevision.DEFAULT_MIME_TYPE,)
         submitted_mime_type = cleaned_data.get('mime_type')
 
-        if (submitted_mime_type in nulls) and ('file' in cleaned_data):
+        if submitted_mime_type in nulls and 'file' in cleaned_data:
             self.mime_type = self.mime_type_from_file(cleaned_data['file'])
-            allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()
-            if self.mime_type not in allowed_mime_types:
-                raise forms.ValidationError(MIME_TYPE_INVALID, code='invalid')
+            if self.mime_type.startswith('image/svg') and self.allow_svg_uploads:
+                # The `magic.Magic()` will, for unknown reasons, sometimes
+                # think an SVG image's mime type is `image/svg` which not
+                # a valid mime type actually.
+                # See https://www.iana.org/assignments/media-types/media-types.xhtml#image
+                # So correct that.
+                if self.mime_type == 'image/svg':
+                    self.mime_type = 'image/svg+xml'
+            else:
+                allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()
+                if self.mime_type not in allowed_mime_types:
+                    raise forms.ValidationError(
+                        MIME_TYPE_INVALID, code='invalid')
 
         return cleaned_data
 
diff --git a/kuma/attachments/views.py b/kuma/attachments/views.py
--- a/kuma/attachments/views.py
+++ b/kuma/attachments/views.py
@@ -84,7 +84,13 @@
     if not allow_add_attachment_by(request.user):
         raise PermissionDenied
 
-    form = AttachmentRevisionForm(data=request.POST, files=request.FILES)
+    form = AttachmentRevisionForm(
+        data=request.POST,
+        files=request.FILES,
+        # Only staff users are allowed to upload SVG files because SVG files
+        # can contain embedded inline scripts.
+        allow_svg_uploads=request.user.is_staff
+    )
     if form.is_valid():
         revision = form.save(commit=False)
         revision.creator = request.user

{"golden_diff": "diff --git a/kuma/attachments/forms.py b/kuma/attachments/forms.py\n--- a/kuma/attachments/forms.py\n+++ b/kuma/attachments/forms.py\n@@ -24,6 +24,7 @@\n         fields = ('file', 'title', 'description', 'comment')\n \n     def __init__(self, *args, **kwargs):\n+        self.allow_svg_uploads = kwargs.pop('allow_svg_uploads', False)\n         super(AttachmentRevisionForm, self).__init__(*args, **kwargs)\n         self.mime_type = None\n \n@@ -39,11 +40,21 @@\n         nulls = EMPTY_VALUES + (AttachmentRevision.DEFAULT_MIME_TYPE,)\n         submitted_mime_type = cleaned_data.get('mime_type')\n \n-        if (submitted_mime_type in nulls) and ('file' in cleaned_data):\n+        if submitted_mime_type in nulls and 'file' in cleaned_data:\n             self.mime_type = self.mime_type_from_file(cleaned_data['file'])\n-            allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()\n-            if self.mime_type not in allowed_mime_types:\n-                raise forms.ValidationError(MIME_TYPE_INVALID, code='invalid')\n+            if self.mime_type.startswith('image/svg') and self.allow_svg_uploads:\n+                # The `magic.Magic()` will, for unknown reasons, sometimes\n+                # think an SVG image's mime type is `image/svg` which not\n+                # a valid mime type actually.\n+                # See https://www.iana.org/assignments/media-types/media-types.xhtml#image\n+                # So correct that.\n+                if self.mime_type == 'image/svg':\n+                    self.mime_type = 'image/svg+xml'\n+            else:\n+                allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()\n+                if self.mime_type not in allowed_mime_types:\n+                    raise forms.ValidationError(\n+                        MIME_TYPE_INVALID, code='invalid')\n \n         return cleaned_data\n \ndiff --git a/kuma/attachments/views.py b/kuma/attachments/views.py\n--- a/kuma/attachments/views.py\n+++ b/kuma/attachments/views.py\n@@ -84,7 +84,13 @@\n     if not allow_add_attachment_by(request.user):\n         raise PermissionDenied\n \n-    form = AttachmentRevisionForm(data=request.POST, files=request.FILES)\n+    form = AttachmentRevisionForm(\n+        data=request.POST,\n+        files=request.FILES,\n+        # Only staff users are allowed to upload SVG files because SVG files\n+        # can contain embedded inline scripts.\n+        allow_svg_uploads=request.user.is_staff\n+    )\n     if form.is_valid():\n         revision = form.save(commit=False)\n         revision.creator = request.user\n", "issue": "Magic is incorrectly using image/svg as MIME type for SVG files, preventing uploads of SVG files\nMagic or libmagic is incorrectly using `image/svg` as the MIME type for SVG uploads, rather than `image/svg+xml`, which is the only correct MIME type [1] (and the one we've always used in the past).\r\n\r\nNormally, we keep SVG uploads disabled for security reasons since SVG can contain JavaScript code. However, we like to use it for diagrams and the like because they can be translated, and they are more efficient for that purpose in many cases. When we want to upload SVG, we go to the admin panel in Django and in the Constance panel, add \"image/svg+xml\" to the `WIKI_ATTACHMENT_ALLOWED_TYPES` string. Then we upload the file and restore the previous string to that preference.\r\n\r\nThis is no longer working; even with `image/svg+xml` listed in the preference, uploads fail with an error announcing that \"Files of this type are not permitted.\" This should work, however.\r\n\r\nThis issue is blocking work on WebXR and potentially other documentation that requires the use of diagrams to explain things properly. Hopefully the fix is not complicated.\r\n\r\n[1] https://www.iana.org/assignments/media-types/media-types.xhtml#image\n", "before_files": [{"content": "import magic\nfrom constance import config\nfrom django import forms\nfrom django.core.validators import EMPTY_VALUES\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom .models import AttachmentRevision\n\n\nMIME_TYPE_INVALID = _('Files of this type are not permitted.')\n\n\nclass AttachmentRevisionForm(forms.ModelForm):\n    \"\"\"\n    Unlike the DocumentForm/RevisionForm split, we have only one\n    form for file attachments. The handling view will determine if\n    this is a new revision of an existing file, or the first version\n    of a new file.\n\n    As a result of this, calling save(commit=True) is off-limits.\n    \"\"\"\n    class Meta:\n        model = AttachmentRevision\n        fields = ('file', 'title', 'description', 'comment')\n\n    def __init__(self, *args, **kwargs):\n        super(AttachmentRevisionForm, self).__init__(*args, **kwargs)\n        self.mime_type = None\n\n    def clean(self):\n        \"\"\"\n        Check the submitted file for its MIME type in case the provided\n        MIME type is missing or is the default MIME type as given in the\n        model field definition.\n\n        That allows overriding the MIME type via the admin UI.\n        \"\"\"\n        cleaned_data = super(AttachmentRevisionForm, self).clean()\n        nulls = EMPTY_VALUES + (AttachmentRevision.DEFAULT_MIME_TYPE,)\n        submitted_mime_type = cleaned_data.get('mime_type')\n\n        if (submitted_mime_type in nulls) and ('file' in cleaned_data):\n            self.mime_type = self.mime_type_from_file(cleaned_data['file'])\n            allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()\n            if self.mime_type not in allowed_mime_types:\n                raise forms.ValidationError(MIME_TYPE_INVALID, code='invalid')\n\n        return cleaned_data\n\n    def save(self, *args, **kwargs):\n        revision = super(AttachmentRevisionForm, self).save(*args, **kwargs)\n        if self.mime_type is not None:\n            revision.mime_type = self.mime_type\n        return revision\n\n    def mime_type_from_file(self, file):\n        m_mime = magic.Magic(mime=True)\n        mime_type = m_mime.from_buffer(file.read(1024)).split(';')[0]\n        file.seek(0)\n        return mime_type\n\n\nclass AdminAttachmentRevisionForm(AttachmentRevisionForm):\n    class Meta(AttachmentRevisionForm.Meta):\n        fields = ['attachment', 'file', 'title', 'mime_type', 'description',\n                  'is_approved']\n", "path": "kuma/attachments/forms.py"}, {"content": "import mimetypes\n\nfrom django.conf import settings\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404, StreamingHttpResponse\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.views.decorators.cache import cache_control, never_cache\nfrom django.views.decorators.clickjacking import xframe_options_sameorigin\n\nfrom kuma.core.decorators import (ensure_wiki_domain, login_required,\n                                  shared_cache_control)\nfrom kuma.core.utils import is_untrusted\nfrom kuma.wiki.decorators import process_document_path\nfrom kuma.wiki.models import Document\n\nfrom .forms import AttachmentRevisionForm\nfrom .models import Attachment\nfrom .utils import allow_add_attachment_by, convert_to_http_date\n\n\n# Mime types used on MDN\nOVERRIDE_MIMETYPES = {\n    'image/jpeg': '.jpeg, .jpg, .jpe',\n    'image/vnd.adobe.photoshop': '.psd',\n}\n\nIMAGE_MIMETYPES = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']\n\n\ndef guess_extension(_type):\n    return OVERRIDE_MIMETYPES.get(_type, mimetypes.guess_extension(_type))\n\n\n@cache_control(public=True, max_age=60 * 15)\ndef raw_file(request, attachment_id, filename):\n    \"\"\"\n    Serve up an attachment's file.\n    \"\"\"\n    qs = Attachment.objects.select_related('current_revision')\n    attachment = get_object_or_404(qs, pk=attachment_id)\n    if attachment.current_revision is None:\n        raise Http404\n\n    if is_untrusted(request):\n        rev = attachment.current_revision\n        response = StreamingHttpResponse(rev.file, content_type=rev.mime_type)\n        response['Content-Length'] = rev.file.size\n        response['Last-Modified'] = convert_to_http_date(rev.created)\n        response['X-Frame-Options'] = 'ALLOW-FROM %s' % settings.DOMAIN\n        return response\n\n    return redirect(attachment.get_file_url(), permanent=True)\n\n\n@shared_cache_control(s_maxage=60 * 60 * 24 * 30)\ndef mindtouch_file_redirect(request, file_id, filename):\n    \"\"\"Redirect an old MindTouch file URL to a new kuma file URL.\"\"\"\n    attachment = get_object_or_404(Attachment, mindtouch_attachment_id=file_id)\n    return redirect(attachment.get_file_url(), permanent=True)\n\n\n@ensure_wiki_domain\n@never_cache\n@xframe_options_sameorigin\n@login_required\n@process_document_path\ndef edit_attachment(request, document_slug, document_locale):\n    \"\"\"\n    Create a new Attachment object and populate its initial\n    revision or show a separate form view that allows to fix form submission\n    errors.\n\n    Redirects back to the document's editing URL on success.\n    \"\"\"\n    document = get_object_or_404(\n        Document,\n        locale=document_locale,\n        slug=document_slug,\n    )\n    if request.method != 'POST':\n        return redirect(document.get_edit_url())\n\n    # No access if no permissions to upload\n    if not allow_add_attachment_by(request.user):\n        raise PermissionDenied\n\n    form = AttachmentRevisionForm(data=request.POST, files=request.FILES)\n    if form.is_valid():\n        revision = form.save(commit=False)\n        revision.creator = request.user\n        attachment = Attachment.objects.create(title=revision.title)\n        revision.attachment = attachment\n        revision.save()\n        # adding the attachment to the document's files (M2M)\n        attachment.attach(document, request.user, revision)\n        return redirect(document.get_edit_url())\n    else:\n        context = {\n            'form': form,\n            'document': document,\n        }\n        return render(request, 'attachments/edit_attachment.html', context)\n", "path": "kuma/attachments/views.py"}], "after_files": [{"content": "import magic\nfrom constance import config\nfrom django import forms\nfrom django.core.validators import EMPTY_VALUES\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom .models import AttachmentRevision\n\n\nMIME_TYPE_INVALID = _('Files of this type are not permitted.')\n\n\nclass AttachmentRevisionForm(forms.ModelForm):\n    \"\"\"\n    Unlike the DocumentForm/RevisionForm split, we have only one\n    form for file attachments. The handling view will determine if\n    this is a new revision of an existing file, or the first version\n    of a new file.\n\n    As a result of this, calling save(commit=True) is off-limits.\n    \"\"\"\n    class Meta:\n        model = AttachmentRevision\n        fields = ('file', 'title', 'description', 'comment')\n\n    def __init__(self, *args, **kwargs):\n        self.allow_svg_uploads = kwargs.pop('allow_svg_uploads', False)\n        super(AttachmentRevisionForm, self).__init__(*args, **kwargs)\n        self.mime_type = None\n\n    def clean(self):\n        \"\"\"\n        Check the submitted file for its MIME type in case the provided\n        MIME type is missing or is the default MIME type as given in the\n        model field definition.\n\n        That allows overriding the MIME type via the admin UI.\n        \"\"\"\n        cleaned_data = super(AttachmentRevisionForm, self).clean()\n        nulls = EMPTY_VALUES + (AttachmentRevision.DEFAULT_MIME_TYPE,)\n        submitted_mime_type = cleaned_data.get('mime_type')\n\n        if submitted_mime_type in nulls and 'file' in cleaned_data:\n            self.mime_type = self.mime_type_from_file(cleaned_data['file'])\n            if self.mime_type.startswith('image/svg') and self.allow_svg_uploads:\n                # The `magic.Magic()` will, for unknown reasons, sometimes\n                # think an SVG image's mime type is `image/svg` which not\n                # a valid mime type actually.\n                # See https://www.iana.org/assignments/media-types/media-types.xhtml#image\n                # So correct that.\n                if self.mime_type == 'image/svg':\n                    self.mime_type = 'image/svg+xml'\n            else:\n                allowed_mime_types = config.WIKI_ATTACHMENT_ALLOWED_TYPES.split()\n                if self.mime_type not in allowed_mime_types:\n                    raise forms.ValidationError(\n                        MIME_TYPE_INVALID, code='invalid')\n\n        return cleaned_data\n\n    def save(self, *args, **kwargs):\n        revision = super(AttachmentRevisionForm, self).save(*args, **kwargs)\n        if self.mime_type is not None:\n            revision.mime_type = self.mime_type\n        return revision\n\n    def mime_type_from_file(self, file):\n        m_mime = magic.Magic(mime=True)\n        mime_type = m_mime.from_buffer(file.read(1024)).split(';')[0]\n        file.seek(0)\n        return mime_type\n\n\nclass AdminAttachmentRevisionForm(AttachmentRevisionForm):\n    class Meta(AttachmentRevisionForm.Meta):\n        fields = ['attachment', 'file', 'title', 'mime_type', 'description',\n                  'is_approved']\n", "path": "kuma/attachments/forms.py"}, {"content": "import mimetypes\n\nfrom django.conf import settings\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404, StreamingHttpResponse\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.views.decorators.cache import cache_control, never_cache\nfrom django.views.decorators.clickjacking import xframe_options_sameorigin\n\nfrom kuma.core.decorators import (ensure_wiki_domain, login_required,\n                                  shared_cache_control)\nfrom kuma.core.utils import is_untrusted\nfrom kuma.wiki.decorators import process_document_path\nfrom kuma.wiki.models import Document\n\nfrom .forms import AttachmentRevisionForm\nfrom .models import Attachment\nfrom .utils import allow_add_attachment_by, convert_to_http_date\n\n\n# Mime types used on MDN\nOVERRIDE_MIMETYPES = {\n    'image/jpeg': '.jpeg, .jpg, .jpe',\n    'image/vnd.adobe.photoshop': '.psd',\n}\n\nIMAGE_MIMETYPES = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']\n\n\ndef guess_extension(_type):\n    return OVERRIDE_MIMETYPES.get(_type, mimetypes.guess_extension(_type))\n\n\n@cache_control(public=True, max_age=60 * 15)\ndef raw_file(request, attachment_id, filename):\n    \"\"\"\n    Serve up an attachment's file.\n    \"\"\"\n    qs = Attachment.objects.select_related('current_revision')\n    attachment = get_object_or_404(qs, pk=attachment_id)\n    if attachment.current_revision is None:\n        raise Http404\n\n    if is_untrusted(request):\n        rev = attachment.current_revision\n        response = StreamingHttpResponse(rev.file, content_type=rev.mime_type)\n        response['Content-Length'] = rev.file.size\n        response['Last-Modified'] = convert_to_http_date(rev.created)\n        response['X-Frame-Options'] = 'ALLOW-FROM %s' % settings.DOMAIN\n        return response\n\n    return redirect(attachment.get_file_url(), permanent=True)\n\n\n@shared_cache_control(s_maxage=60 * 60 * 24 * 30)\ndef mindtouch_file_redirect(request, file_id, filename):\n    \"\"\"Redirect an old MindTouch file URL to a new kuma file URL.\"\"\"\n    attachment = get_object_or_404(Attachment, mindtouch_attachment_id=file_id)\n    return redirect(attachment.get_file_url(), permanent=True)\n\n\n@ensure_wiki_domain\n@never_cache\n@xframe_options_sameorigin\n@login_required\n@process_document_path\ndef edit_attachment(request, document_slug, document_locale):\n    \"\"\"\n    Create a new Attachment object and populate its initial\n    revision or show a separate form view that allows to fix form submission\n    errors.\n\n    Redirects back to the document's editing URL on success.\n    \"\"\"\n    document = get_object_or_404(\n        Document,\n        locale=document_locale,\n        slug=document_slug,\n    )\n    if request.method != 'POST':\n        return redirect(document.get_edit_url())\n\n    # No access if no permissions to upload\n    if not allow_add_attachment_by(request.user):\n        raise PermissionDenied\n\n    form = AttachmentRevisionForm(\n        data=request.POST,\n        files=request.FILES,\n        # Only staff users are allowed to upload SVG files because SVG files\n        # can contain embedded inline scripts.\n        allow_svg_uploads=request.user.is_staff\n    )\n    if form.is_valid():\n        revision = form.save(commit=False)\n        revision.creator = request.user\n        attachment = Attachment.objects.create(title=revision.title)\n        revision.attachment = attachment\n        revision.save()\n        # adding the attachment to the document's files (M2M)\n        attachment.attach(document, request.user, revision)\n        return redirect(document.get_edit_url())\n    else:\n        context = {\n            'form': form,\n            'document': document,\n        }\n        return render(request, 'attachments/edit_attachment.html', context)\n", "path": "kuma/attachments/views.py"}]}