class FileValidators::MimeTypeAnalyzer

Constants

MAGIC_NUMBER
SUPPORTED_TOOLS

Public Class Methods

new(tool) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 9
def initialize(tool)
  raise Error, "unknown mime type analyzer #{tool.inspect}, supported analyzers are: #{SUPPORTED_TOOLS.join(',')}" unless SUPPORTED_TOOLS.include?(tool)

  @tool = tool
end

Public Instance Methods

call(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 15
def call(io)
  mime_type = send(:"extract_with_#{@tool}", io)
  io.rewind

  mime_type
end

Private Instance Methods

extract_filename(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 98
def extract_filename(io)
  if io.respond_to?(:original_filename)
    io.original_filename
  elsif io.respond_to?(:path)
    File.basename(io.path)
  end
end
extract_with_fastimage(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 48
def extract_with_fastimage(io)
  require 'fastimage'

  type = FastImage.type(io)
  "image/#{type}" if type
end
extract_with_file(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 24
def extract_with_file(io)
  require 'open3'

  return nil if io.eof? # file command returns "application/x-empty" for empty files

  Open3.popen3(*%W[file --mime-type --brief -]) do |stdin, stdout, stderr, thread|
    begin
      IO.copy_stream(io, stdin.binmode)
    rescue Errno::EPIPE
    end
    stdin.close

    status = thread.value

    raise Error, "file command failed to spawn: #{stderr.read}" if status.nil?
    raise Error, "file command failed: #{stderr.read}" unless status.success?
    $stderr.print(stderr.read)

    stdout.read.strip
  end
rescue Errno::ENOENT
  raise Error, 'file command-line tool is not installed'
end
extract_with_filemagic(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 55
def extract_with_filemagic(io)
  require 'filemagic'

  return nil if io.eof? # FileMagic returns "application/x-empty" for empty files

  FileMagic.open(FileMagic::MAGIC_MIME_TYPE) do |filemagic|
    filemagic.buffer(io.read(MAGIC_NUMBER))
  end
end
extract_with_marcel(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 72
def extract_with_marcel(io)
  require 'marcel'

  return nil if io.eof? # marcel returns "application/octet-stream" for empty files

  Marcel::MimeType.for(io)
end
extract_with_mime_types(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 80
def extract_with_mime_types(io)
  require 'mime/types'

  if filename = extract_filename(io)
    mime_type = MIME::Types.of(filename).first
    mime_type.content_type if mime_type
  end
end
extract_with_mimemagic(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 65
def extract_with_mimemagic(io)
  require 'mimemagic'

  mime = MimeMagic.by_magic(io)
  mime.type if mime
end
extract_with_mini_mime(io) click to toggle source
# File lib/file_validators/mime_type_analyzer.rb, line 89
def extract_with_mini_mime(io)
  require 'mini_mime'

  if filename = extract_filename(io)
    info = MiniMime.lookup_by_filename(filename)
    info.content_type if info
  end
end