blob: 9daf05065fd253de4d2fa62b3032281178b417ba [file] [log] [blame]
require 'open3'
require_relative 'safetemp'
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! /^\W/, ''
name.gsub! /[^\w.]/, '_'
name.untaint
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 = SafeTempFile.new([safe_name, '.pdf'])
file.write(body)
file.rewind
file
end
def as_pdf
ext = File.extname(name).downcase
ext = '.pdf' if content_type.end_with? '/pdf'
ext.untaint if ext =~ /^\.\w+$/
file = SafeTempFile.new([safe_name, ext])
file.write(body)
file.rewind
return file if ext == '.pdf'
if IMAGE_TYPES.include? ext or content_type.start_with? 'image/'
pdf = SafeTempFile.new([safe_name, '.pdf'])
img2pdf = File.expand_path('../img2pdf', __dir__.untaint).untaint
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 = SafeTempFile.new([safe_name, '.png'])
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
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.untaint, filename
filename
end
end