| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2024-02-26 22:55:54 +00:00
										 |  |  | # Copyright (C) 2006-  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' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2021-05-25 02:36:21 +00:00
										 |  |  |     GS_BIN = ( | 
					
						
							|  |  |  |       Redmine::Configuration['gs_command'] || | 
					
						
							|  |  |  |       ('gswin64c' if Redmine::Platform.mswin?) || | 
					
						
							|  |  |  |       'gs' | 
					
						
							|  |  |  |     ).freeze | 
					
						
							| 
									
										
										
										
											2023-01-16 01:23:36 +00:00
										 |  |  |     ALLOWED_TYPES = %w(image/bmp image/gif image/jpeg image/png image/webp 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? | 
					
						
							| 
									
										
										
										
											2020-11-05 13:42:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 03:20:31 +00:00
										 |  |  |       unless File.exist?(target) | 
					
						
							| 
									
										
										
										
											2021-03-27 10:16:34 +00:00
										 |  |  |         # Make sure we only invoke Imagemagick if the file type is allowed | 
					
						
							| 
									
										
										
										
											2021-03-27 10:23:47 +00:00
										 |  |  |         mime_type = File.open(source) {|f| Marcel::MimeType.for(f)} | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |         return nil if !ALLOWED_TYPES.include? mime_type | 
					
						
							|  |  |  |         return nil if is_pdf && mime_type != "application/pdf" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |         directory = File.dirname(target) | 
					
						
							| 
									
										
										
										
											2022-06-30 07:35:23 +00:00
										 |  |  |         FileUtils.mkdir_p directory | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:42:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 02:36:21 +00:00
										 |  |  |       begin | 
					
						
							|  |  |  |         `#{shell_quote GS_BIN} -version` | 
					
						
							|  |  |  |         @gs_available = $?.success? | 
					
						
							|  |  |  |       rescue | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |         @gs_available = false | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-04-20 14:15:18 +00:00
										 |  |  |       logger.warn("gs binary (#{GS_BIN}) not available") unless @gs_available | 
					
						
							| 
									
										
										
										
											2019-05-12 03:55:56 +00:00
										 |  |  |       @gs_available | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:48:07 +00:00
										 |  |  |     def self.logger | 
					
						
							|  |  |  |       Rails.logger | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |