| 
									
										
										
										
											2019-03-16 09:37:35 +00:00
										 |  |  | # frozen_string_literal: true | 
					
						
							| 
									
										
										
										
											2019-03-15 01:32:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  | # Redmine - project management software | 
					
						
							| 
									
										
										
										
											2019-05-25 07:36:06 +00:00
										 |  |  | # Copyright (C) 2006-2019  Jean-Philippe Lang | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | # modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | # as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | # of the License, or (at your option) any later version. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | # GNU General Public License for more details. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | # along with this program; if not, write to the Free Software | 
					
						
							|  |  |  | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require 'fileutils' | 
					
						
							| 
									
										
										
										
											2016-05-04 18:05:54 +00:00
										 |  |  | require 'mimemagic' | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | module Redmine | 
					
						
							|  |  |  |   module Thumbnail | 
					
						
							|  |  |  |     extend Redmine::Utils::Shell | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-16 17:37:24 +00:00
										 |  |  |     CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |     ALLOWED_TYPES = %w(image/bmp image/gif image/jpeg image/png application/pdf) | 
					
						
							| 
									
										
										
										
											2012-07-16 17:37:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |     # Generates a thumbnail for the source image to target | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |     def self.generate(source, target, size, is_pdf = false) | 
					
						
							| 
									
										
										
										
											2012-07-16 17:37:24 +00:00
										 |  |  |       return nil unless convert_available? | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |       return nil if is_pdf && !gs_available? | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |       unless File.exists?(target) | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |         mime_type = File.open(source) {|f| MimeMagic.by_magic(f).try(:type) } | 
					
						
							|  |  |  |         return nil if mime_type.nil? | 
					
						
							|  |  |  |         return nil if !ALLOWED_TYPES.include? mime_type | 
					
						
							|  |  |  |         return nil if is_pdf && mime_type != "application/pdf" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-20 08:52:26 +00:00
										 |  |  |         # Make sure we only invoke Imagemagick if the file type is allowed | 
					
						
							|  |  |  |         unless File.open(source) {|f| ALLOWED_TYPES.include? MimeMagic.by_magic(f).try(:type) } | 
					
						
							| 
									
										
										
										
											2016-05-04 18:05:54 +00:00
										 |  |  |           return nil | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |         directory = File.dirname(target) | 
					
						
							|  |  |  |         unless File.exists?(directory) | 
					
						
							|  |  |  |           FileUtils.mkdir_p directory | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         size_option = "#{size}x#{size}>" | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if is_pdf | 
					
						
							|  |  |  |           cmd = "#{shell_quote CONVERT_BIN} #{shell_quote "#{source}[0]"} -thumbnail #{shell_quote size_option} #{shell_quote "png:#{target}"}" | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -auto-orient -thumbnail #{shell_quote size_option} #{shell_quote target}" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |         unless system(cmd) | 
					
						
							|  |  |  |           logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}") | 
					
						
							|  |  |  |           return nil | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       target | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-16 17:37:24 +00:00
										 |  |  |     def self.convert_available? | 
					
						
							|  |  |  |       return @convert_available if defined?(@convert_available) | 
					
						
							| 
									
										
										
										
											2019-05-05 00:44:32 +00:00
										 |  |  |       begin | 
					
						
							|  |  |  |         `#{shell_quote CONVERT_BIN} -version` | 
					
						
							|  |  |  |         @convert_available = $?.success? | 
					
						
							|  |  |  |       rescue | 
					
						
							|  |  |  |         @convert_available = false | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2012-07-16 17:37:24 +00:00
										 |  |  |       logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available | 
					
						
							|  |  |  |       @convert_available | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |     def self.gs_available? | 
					
						
							|  |  |  |       return @gs_available if defined?(@gs_available) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if Redmine::Platform.mswin? | 
					
						
							|  |  |  |         @gs_available = false | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         begin | 
					
						
							|  |  |  |           `gs -version` | 
					
						
							|  |  |  |           @gs_available = $?.success? | 
					
						
							|  |  |  |         rescue | 
					
						
							|  |  |  |           @gs_available = false | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       @gs_available | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |     def self.logger | 
					
						
							|  |  |  |       Rails.logger | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |