diff --git a/lib/mimemagic.rb b/lib/mimemagic.rb index 3be35a1..9b28d1b 100644 --- a/lib/mimemagic.rb +++ b/lib/mimemagic.rb @@ -109,28 +109,27 @@ def self.child?(child, parent) end def self.magic_match(io, method) - if io.respond_to?(:seek) && io.respond_to?(:read) - io.binmode - io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding) - buffer = "".force_encoding(Encoding::BINARY) - MAGIC.send(method) { |type, matches| magic_match_io(io, matches, buffer) } - else - str = io.respond_to?(:read) ? io.read : io.to_s - magic_match(StringIO.new(str), method) - end + return magic_match(StringIO.new(io.to_s), method) unless io.respond_to?(:read) + + io.binmode if io.respond_to?(:binmode) + io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding) + buffer = "".force_encoding(Encoding::BINARY) + + MAGIC.send(method) { |type, matches| magic_match_io(io, matches, buffer) } end def self.magic_match_io(io, matches, buffer) matches.any? do |offset, value, children| match = if Range === offset - io.seek(offset.begin) + io.read(offset.begin, buffer) x = io.read(offset.end - offset.begin + value.bytesize, buffer) x && x.include?(value) else - io.seek(offset) + io.read(offset, buffer) io.read(value.bytesize, buffer) == value end + io.rewind match && (!children || magic_match_io(io, children, buffer)) end end diff --git a/test/mimemagic_test.rb b/test/mimemagic_test.rb index 6cdb386..7ac11b0 100644 --- a/test/mimemagic_test.rb +++ b/test/mimemagic_test.rb @@ -1,6 +1,7 @@ require 'bacon' require 'mimemagic' require 'stringio' +require 'forwardable' describe 'MimeMagic' do it 'should have type, mediatype and subtype' do @@ -116,12 +117,15 @@ it 'should handle different file objects' do MimeMagic.add('application/mimemagic-test', magic: [[0, 'MAGICTEST']]) - class ReadableObj - def read - 'MAGICTEST' + class IOObject + def initialize + @io = StringIO.new('MAGICTEST') end + + extend Forwardable + delegate [:read, :size, :rewind, :eof?, :close] => :@io end - MimeMagic.by_magic(ReadableObj.new).should.equal 'application/mimemagic-test' + MimeMagic.by_magic(IOObject.new).should.equal 'application/mimemagic-test' class StringableObject def to_s 'MAGICTEST'