FEATURE: new 'max_image_megapixels' site setting

This commit is contained in:
Régis Hanol 2017-01-11 23:37:12 +01:00
parent fee5f082b8
commit 887e9af84f
5 changed files with 28 additions and 5 deletions

View File

@ -95,6 +95,8 @@ class Upload < ActiveRecord::Base
# - image_type ("avatar", "profile_background", "card_background")
# - is_attachment_for_group_message (boolean)
def self.create_for(user_id, file, filename, filesize, options = {})
upload = Upload.new
DistributedMutex.synchronize("upload_#{user_id}_#{filename}") do
# do some work on images
if FileHelper.is_image?(filename) && is_actual_image?(file)
@ -105,13 +107,19 @@ class Upload < ActiveRecord::Base
File.write(file.path, doc.to_s)
file.rewind
else
# ensure image isn't huge
w, h = FastImage.size(file) || [0, 0]
if w * h >= SiteSetting.max_image_megapixels * 1_000_000
upload.errors.add(:base, I18n.t("upload.images.larger_than_x_megapixels", max_image_megapixels: SiteSetting.max_image_megapixels))
return upload
end
# fix orientation first
fix_image_orientation(file.path) if should_optimize?(file.path)
end
# retrieve image info
image_info = FastImage.new(file)
w, h = *(image_info.try(:size) || [0, 0])
w, h = FastImage.size(file) || [0, 0]
# default size
width, height = ImageSizer.resize(w, h)
@ -214,8 +222,7 @@ class Upload < ActiveRecord::Base
# don't optimize GIFs or SVGs
return false if path =~ /\.(gif|svg)$/i
return true if path !~ /\.png$/i
image_info = FastImage.new(path) rescue nil
w, h = *(image_info.try(:size) || [0, 0])
w, h = FastImage.size(path) || [0, 0]
# don't optimize large PNGs
w > 0 && h > 0 && w * h < LARGE_PNG_SIZE
end

View File

@ -1213,6 +1213,8 @@ en:
authorized_extensions: "A list of file extensions allowed for upload (use '*' to enable all file types)"
max_similar_results: "How many similar topics to show above the editor when composing a new topic. Comparison is based on title and body."
max_image_megapixels: "Maximum number of megapixels allowed for an image."
title_prettify: "Prevent common title typos and errors, including all caps, lowercase first character, multiple ! and ?, extra . at end, etc."
topic_views_heat_low: "After this many views, the views field is slightly highlighted."
@ -2640,6 +2642,7 @@ en:
too_large: "Sorry, the file you are trying to upload is too big (maximum size is %{max_size_kb}KB)."
images:
too_large: "Sorry, the image you are trying to upload is too big (maximum size is %{max_size_kb}KB), please resize it and try again."
larger_than_x_megapixels: "Sorry, the image you are trying to upload is too large (maximum dimension is %{max_image_megapixels}-megapixels), please resize it and try again."
size_not_found: "Sorry, but we couldn't determine the size of the image. Maybe your image is corrupted?"
avatar:

View File

@ -699,6 +699,10 @@ files:
max_attachment_size_kb:
client: true
default: 3072
max_image_megapixels:
default: 40
min: 5
max: 100
authorized_extensions:
client: true
default: 'jpg|jpeg|png|gif'

BIN
spec/fixtures/images/huge.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 KiB

View File

@ -17,6 +17,10 @@ describe Upload do
let(:image_svg) { file_from_fixtures(image_svg_filename) }
let(:image_svg_filesize) { File.size(image_svg) }
let(:huge_image_filename) { "huge.jpg" }
let(:huge_image) { file_from_fixtures(huge_image_filename) }
let(:huge_image_filesize) { File.size(huge_image) }
let(:attachment_path) { __FILE__ }
let(:attachment) { File.new(attachment_path) }
let(:attachment_filename) { File.basename(attachment_path) }
@ -55,6 +59,12 @@ describe Upload do
expect(Upload.create_for(user_id, image, image_filename, image_filesize)).to eq(upload)
end
it "ensures images isn't huge before processing it" do
Upload.expects(:fix_image_orientation).never
upload = Upload.create_for(user_id, huge_image, huge_image_filename, huge_image_filesize)
expect(upload.errors.size).to be > 0
end
it "fix image orientation" do
Upload.expects(:fix_image_orientation).with(image.path)
Upload.create_for(user_id, image, image_filename, image_filesize)
@ -62,7 +72,6 @@ describe Upload do
it "computes width & height for images" do
ImageSizer.expects(:resize)
image.expects(:rewind).times(3)
Upload.create_for(user_id, image, image_filename, image_filesize)
end