diff --git a/app/controllers/user_avatars_controller.rb b/app/controllers/user_avatars_controller.rb index 39050be70bd..a7f32b11710 100644 --- a/app/controllers/user_avatars_controller.rb +++ b/app/controllers/user_avatars_controller.rb @@ -184,6 +184,7 @@ class UserAvatarsController < ApplicationController def get_optimized_image(upload, size) return if !upload + return upload if upload.extension == "svg" upload.get_optimized_image(size, size, allow_animation: SiteSetting.allow_animated_avatars) # TODO decide if we want to detach here diff --git a/app/models/optimized_image.rb b/app/models/optimized_image.rb index fbf8b60bec7..c9cdbd94ef5 100644 --- a/app/models/optimized_image.rb +++ b/app/models/optimized_image.rb @@ -21,6 +21,7 @@ class OptimizedImage < ActiveRecord::Base end def self.create_for(upload, width, height, opts = {}) + return unless width > 0 && height > 0 return if upload.try(:sha1).blank? @@ -29,7 +30,7 @@ class OptimizedImage < ActiveRecord::Base upload.fix_image_extension end - if !upload.extension.match?(IM_DECODERS) + if !upload.extension.match?(IM_DECODERS) && upload.extension != "svg" if !opts[:raise_on_error] # nothing to do ... bad extension, not an image return @@ -76,7 +77,7 @@ class OptimizedImage < ActiveRecord::Base temp_file = Tempfile.new(["discourse-thumbnail", extension]) temp_path = temp_file.path - if extension =~ /\.svg$/i + if upload.extension == "svg" FileUtils.cp(original_path, temp_path) resized = true elsif opts[:crop] @@ -86,7 +87,6 @@ class OptimizedImage < ActiveRecord::Base end if resized - thumbnail = OptimizedImage.create!( upload_id: upload.id, sha1: Upload.generate_digest(temp_path), diff --git a/lib/upload_creator.rb b/lib/upload_creator.rb index 04c3e670ec4..431f4f6b94a 100644 --- a/lib/upload_creator.rb +++ b/lib/upload_creator.rb @@ -44,7 +44,7 @@ class UploadCreator extract_image_info! return @upload if @upload.errors.present? - if @filename[/\.svg$/i] + if @image_info.type.to_s == "svg" whitelist_svg! elsif !Rails.env.test? || @opts[:force_optimize] convert_to_jpeg! if should_convert_to_jpeg? @@ -131,7 +131,7 @@ class UploadCreator end end - if @upload.errors.empty? && is_image && @opts[:type] == "avatar" + if @upload.errors.empty? && is_image && @opts[:type] == "avatar" && @upload.extension != "svg" Jobs.enqueue(:create_avatar_thumbnails, upload_id: @upload.id, user_id: user_id) end diff --git a/spec/models/optimized_image_spec.rb b/spec/models/optimized_image_spec.rb index caef6150f11..1eefbb01c35 100644 --- a/spec/models/optimized_image_spec.rb +++ b/spec/models/optimized_image_spec.rb @@ -185,6 +185,21 @@ describe OptimizedImage do describe ".create_for" do + it "is able to 'optimize' an svg" do + + # we don't really optimize anything, we simply copy + # but at least this confirms this actually works + + SiteSetting.authorized_extensions = 'svg' + svg = file_from_fixtures('image.svg') + upload = UploadCreator.new(svg, 'image.svg').create_for(Discourse.system_user.id) + resized = upload.get_optimized_image(50, 50, {}) + + # we perform some basic svg mangling but expect the string Discourse to be there + expect(File.read(Discourse.store.path_for(resized))).to include("Discourse") + expect(File.read(Discourse.store.path_for(resized))).to eq(File.read(Discourse.store.path_for(upload))) + end + context "when using an internal store" do let(:store) { FakeInternalStore.new }