www/secretary/workbench/models/attachment.rb (88 lines of code) (raw):

require 'open3' class Attachment IMAGE_TYPES = %w(.gif .jpg .jpeg .png) attr_reader :headers def initialize(message, headers, part) @message = message @headers = headers @part = part end def name headers[:name] || @part.filename end def content_type type = headers[:mime] || @part.content_type if type == 'application/octet-stream' or type == 'text/plain' type = 'text/plain' if name.end_with? '.sig' type = 'text/plain' if name.end_with? '.asc' type = 'application/pdf' if name.end_with? '.pdf' type = 'image/gif' if name.end_with? '.gif' type = 'image/jpeg' if name.end_with? '.jpg' type = 'image/jpeg' if name.end_with? '.jpeg' type = 'image/png' if name.end_with? '.png' end type = "image/#{$1}" if type =~ /^application\/(jpeg|gif|png)$/ type end def body headers[:content] || @part.body end def safe_name name = self.name.dup name.gsub! %r{[^\w.]}, '_' name end # writes the attachment to the specified pathname, which must not exist def write_path(path) File.open(path, File::WRONLY|File::CREAT|File::EXCL, encoding: Encoding::BINARY) do |file| file.write body end end # Returns the attachment as an open temporary file # Warning: if the reference count goes to 0, the file may be deleted # so calling code must retain the reference until done. def as_file file = Tempfile.new([safe_name, '.pdf'], encoding: Encoding::BINARY) file.write(body) file.rewind file end def as_pdf ext = File.extname(name).downcase ext = '.pdf' if content_type.end_with? '/pdf' file = Tempfile.new([safe_name, ext], encoding: Encoding::BINARY) file.write(body) file.rewind return file if ext == '.pdf' if IMAGE_TYPES.include? ext or content_type.start_with? 'image/' pdf = Tempfile.new([safe_name, '.pdf'], encoding: Encoding::BINARY) img2pdf = File.expand_path('../img2pdf', __dir__) _stdout, stderr, status = Open3.capture3 img2pdf, '--output', pdf.path, file.path # img2pdf will refuse if there is an alpha channel. If that happens # use imagemagick to remove the alpha channel and try again. unless status.exitstatus == 0 if stderr.include? 'remove the alpha channel' tmppng = Tempfile.new([safe_name, '.png'], encoding: Encoding::BINARY) system 'convert', file.path, '-background', 'white', '-alpha', 'remove', '-alpha', 'off', tmppng.path if File.size? tmppng.path _stdout, stderr, _status = Open3.capture3 img2pdf, '--output', pdf.path, tmppng.path end tmppng.unlink end end file.unlink unless File.size? pdf.path STDERR.print stderr unless stderr.empty? raise "Failed to convert #{self.name} to PDF" end return pdf end return file end # write a file out to svn # If there is already a directory with the target path, then add the file to the directory instead # returns the pathname of the file that was written def write_svn(repos, file, path=nil) filename = File.join(repos, file) filename = File.join(filename, path || safe_name) if Dir.exist? filename raise Errno::EEXIST.new(file) if File.exist? filename File.write filename, body, encoding: Encoding::BINARY system 'svn', 'add', filename system 'svn', 'propset', 'svn:mime-type', content_type, filename filename end end