Project

General

Profile

Feature #22995 ยป 0001-Replace-ImageMagick-shellouts-with-fastimage_resize.patch

Gregor Schmidt, 2016-06-06 12:57

View differences:

Gemfile
14 14
gem "actionpack-action_caching"
15 15
gem "actionpack-xml_parser"
16 16
gem "roadie-rails"
17
gem "mimemagic"
17

  
18
# Optional gems to create attachment thumbnails
19
platforms :mri do
20
  group :thumbnails do
21
    gem "local-fastimage_resize", "~> 3.1", require: "fastimage/resize"
22
  end
23
end
18 24

  
19 25
# Request at least nokogiri 1.6.7.2 because of security advisories
20 26
gem "nokogiri", ">= 1.6.7.2"
21 27

  
22
# Request at least rails-html-sanitizer 1.0.3 because of security advisories 
28
# Request at least rails-html-sanitizer 1.0.3 because of security advisories
23 29
gem "rails-html-sanitizer", ">= 1.0.3"
24 30

  
25 31
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
app/models/attachment.rb
194 194
  end
195 195

  
196 196
  def image?
197
    !!(self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i)
197
    !!(self.filename =~ /\.(gif|jpg|jpe|jpeg|png)$/i)
198 198
  end
199 199

  
200 200
  def thumbnailable?
lib/redmine/thumbnail.rb
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18 18
require 'fileutils'
19
require 'mimemagic'
19

  
20
begin
21
  require 'fastimage/resize' unless defined? FastImage
22
rescue LoadError
23
  # :thumbnails group not available
24
end
20 25

  
21 26
module Redmine
22 27
  module Thumbnail
23
    extend Redmine::Utils::Shell
24

  
25
    CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze
26

  
27 28
    # Generates a thumbnail for the source image to target
28 29
    def self.generate(source, target, size)
30

  
31
      # Nothing we can do without the libraries
29 32
      return nil unless convert_available?
30
      unless File.exists?(target)
31
        # Make sure we only invoke Imagemagick if this is actually an image
32
        unless File.open(source) {|f| MimeMagic.by_magic(f).try(:image?)}
33
          return nil
34
        end
35
        directory = File.dirname(target)
36
        unless File.exists?(directory)
37
          FileUtils.mkdir_p directory
38
        end
39
        size_option = "#{size}x#{size}>"
40
        cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}"
41
        unless system(cmd)
42
          logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
43
          return nil
44
        end
33

  
34
      # Nothing to do, thumb was already created
35
      return target if File.exists?(target)
36

  
37
      fastimage = FastImage.new(source)
38

  
39
      # Cannot read dimensions for source - it's probably not an image
40
      return nil if fastimage.size.nil?
41

  
42
      directory = File.dirname(target)
43
      FileUtils.mkdir_p(directory) unless File.exists?(directory)
44

  
45
      if fastimage.size.max <= size
46
        FileUtils.cp(source, target)
47
      elsif fastimage.size.first > fastimage.size.last
48
        fastimage.resize(size, 0, :outfile => target, :jpeg_quality => 90)
49
      else
50
        fastimage.resize(0, size, :outfile => target, :jpeg_quality => 90)
45 51
      end
52

  
46 53
      target
54

  
55
    rescue FastImage::FastImageException
56
      logger.error("Creating thumbnail failed - #{$!.class.name}: #{$!.message}")
57
      nil
47 58
    end
48 59

  
49 60
    def self.convert_available?
50
      return @convert_available if defined?(@convert_available)
51
      @convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false
52
      logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
53
      @convert_available
61
      !!defined?(FastImage)
54 62
    end
55 63

  
56 64
    def self.logger
    (1-1/1)