diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index 8689a956e9..7474b5653f 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -57,7 +57,7 @@ class MediaAttachment < ApplicationRecord
).freeze
IMAGE_MIME_TYPES = %w(image/jpeg image/png image/gif image/heic image/heif image/webp image/avif).freeze
- IMAGE_CONVERTIBLE_MIME_TYPES = %w(image/heic image/heif).freeze
+ IMAGE_CONVERTIBLE_MIME_TYPES = %w(image/heic image/heif image/avif).freeze
VIDEO_MIME_TYPES = %w(video/webm video/mp4 video/quicktime video/ogg).freeze
VIDEO_CONVERTIBLE_MIME_TYPES = %w(video/webm video/quicktime).freeze
AUDIO_MIME_TYPES = %w(audio/wave audio/wav audio/x-wav audio/x-pn-wave audio/vnd.wave audio/ogg audio/vorbis audio/mpeg audio/mp3 audio/webm audio/flac audio/aac audio/m4a audio/x-m4a audio/mp4 audio/3gpp video/x-ms-asf).freeze
diff --git a/config/imagemagick/policy.xml b/config/imagemagick/policy.xml
index 1052476b31..e2aa202f27 100644
--- a/config/imagemagick/policy.xml
+++ b/config/imagemagick/policy.xml
@@ -22,6 +22,6 @@
-
+
diff --git a/lib/paperclip/media_type_spoof_detector_extensions.rb b/lib/paperclip/media_type_spoof_detector_extensions.rb
index a406ef312f..c8868d5e95 100644
--- a/lib/paperclip/media_type_spoof_detector_extensions.rb
+++ b/lib/paperclip/media_type_spoof_detector_extensions.rb
@@ -2,13 +2,15 @@
module Paperclip
module MediaTypeSpoofDetectorExtensions
+ MARCEL_MIME_TYPES = %w(audio/mpeg image/avif).freeze
+
def calculated_content_type
return @calculated_content_type if defined?(@calculated_content_type)
@calculated_content_type = type_from_file_command.chomp
# The `file` command fails to recognize some MP3 files as such
- @calculated_content_type = type_from_marcel if @calculated_content_type == 'application/octet-stream' && type_from_marcel == 'audio/mpeg'
+ @calculated_content_type = type_from_marcel if @calculated_content_type == 'application/octet-stream' && type_from_marcel.in?(MARCEL_MIME_TYPES)
@calculated_content_type
end
diff --git a/spec/fixtures/files/600x400.avif b/spec/fixtures/files/600x400.avif
new file mode 100644
index 0000000000..f306942dbe
Binary files /dev/null and b/spec/fixtures/files/600x400.avif differ
diff --git a/spec/fixtures/files/600x400.heic b/spec/fixtures/files/600x400.heic
new file mode 100644
index 0000000000..1add5832a8
Binary files /dev/null and b/spec/fixtures/files/600x400.heic differ
diff --git a/spec/fixtures/files/600x400.jpeg b/spec/fixtures/files/600x400.jpeg
new file mode 100644
index 0000000000..1c20bea515
Binary files /dev/null and b/spec/fixtures/files/600x400.jpeg differ
diff --git a/spec/fixtures/files/600x400.png b/spec/fixtures/files/600x400.png
new file mode 100644
index 0000000000..3b8a2dee35
Binary files /dev/null and b/spec/fixtures/files/600x400.png differ
diff --git a/spec/fixtures/files/600x400.webp b/spec/fixtures/files/600x400.webp
new file mode 100644
index 0000000000..56fa5151c2
Binary files /dev/null and b/spec/fixtures/files/600x400.webp differ
diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb
index 90e4f2f47b..d142875aa9 100644
--- a/spec/models/media_attachment_spec.rb
+++ b/spec/models/media_attachment_spec.rb
@@ -84,7 +84,87 @@ RSpec.describe MediaAttachment, paperclip_processing: true do
end
end
- describe 'animated gif conversion' do
+ shared_examples 'static 600x400 image' do |content_type, extension|
+ after do
+ media.destroy
+ end
+
+ it 'saves media attachment' do
+ expect(media.persisted?).to be true
+ expect(media.file).to_not be_nil
+ end
+
+ it 'completes processing' do
+ expect(media.processing_complete?).to be true
+ end
+
+ it 'sets type' do
+ expect(media.type).to eq 'image'
+ end
+
+ it 'sets content type' do
+ expect(media.file_content_type).to eq content_type
+ end
+
+ it 'sets file extension' do
+ expect(media.file_file_name).to end_with extension
+ end
+
+ it 'strips original file name' do
+ expect(media.file_file_name).to_not start_with '600x400'
+ end
+
+ it 'sets meta for original' do
+ expect(media.file.meta['original']['width']).to eq 600
+ expect(media.file.meta['original']['height']).to eq 400
+ expect(media.file.meta['original']['aspect']).to eq 1.5
+ end
+
+ it 'sets meta for thumbnail' do
+ expect(media.file.meta['small']['width']).to eq 588
+ expect(media.file.meta['small']['height']).to eq 392
+ expect(media.file.meta['small']['aspect']).to eq 1.5
+ end
+ end
+
+ describe 'jpeg' do
+ let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('600x400.jpeg')) }
+
+ it_behaves_like 'static 600x400 image', 'image/jpeg', '.jpeg'
+ end
+
+ describe 'png' do
+ let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('600x400.png')) }
+
+ it_behaves_like 'static 600x400 image', 'image/png', '.png'
+ end
+
+ describe 'webp' do
+ let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('600x400.webp')) }
+
+ it_behaves_like 'static 600x400 image', 'image/webp', '.webp'
+ end
+
+ describe 'avif' do
+ let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('600x400.avif')) }
+
+ it_behaves_like 'static 600x400 image', 'image/jpeg', '.jpeg'
+ end
+
+ describe 'heic' do
+ let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('600x400.heic')) }
+
+ it_behaves_like 'static 600x400 image', 'image/jpeg', '.jpeg'
+ end
+
+ describe 'base64-encoded image' do
+ let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('600x400.jpeg').read)}" }
+ let(:media) { described_class.create(account: Fabricate(:account), file: base64_attachment) }
+
+ it_behaves_like 'static 600x400 image', 'image/jpeg', '.jpeg'
+ end
+
+ describe 'animated gif' do
let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('avatar.gif')) }
it 'sets type to gifv' do
@@ -101,7 +181,7 @@ RSpec.describe MediaAttachment, paperclip_processing: true do
end
end
- describe 'non-animated gif non-conversion' do
+ describe 'static gif' do
fixtures = [
{ filename: 'attachment.gif', width: 600, height: 400, aspect: 1.5 },
{ filename: 'mini-static.gif', width: 32, height: 32, aspect: 1.0 },
@@ -172,37 +252,6 @@ RSpec.describe MediaAttachment, paperclip_processing: true do
end
end
- describe 'jpeg' do
- let(:media) { described_class.create(account: Fabricate(:account), file: attachment_fixture('attachment.jpg')) }
-
- it 'sets meta for different style' do
- expect(media.file.meta['original']['width']).to eq 600
- expect(media.file.meta['original']['height']).to eq 400
- expect(media.file.meta['original']['aspect']).to eq 1.5
- expect(media.file.meta['small']['width']).to eq 588
- expect(media.file.meta['small']['height']).to eq 392
- expect(media.file.meta['small']['aspect']).to eq 1.5
- end
-
- it 'gives the file a random name' do
- expect(media.file_file_name).to_not eq 'attachment.jpg'
- end
- end
-
- describe 'base64-encoded jpeg' do
- let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" }
- let(:media) { described_class.create(account: Fabricate(:account), file: base64_attachment) }
-
- it 'saves media attachment' do
- expect(media.persisted?).to be true
- expect(media.file).to_not be_nil
- end
-
- it 'gives the file a file name' do
- expect(media.file_file_name).to_not be_blank
- end
- end
-
it 'is invalid without file' do
media = described_class.new(account: Fabricate(:account))
expect(media.valid?).to be false