Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Mendler committed May 9, 2009
0 parents commit 749a7e5
Show file tree
Hide file tree
Showing 9 changed files with 6,583 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
lib/mimemagic.rb
lib/mimemagic_tables.rb
test/test_mimemagic.rb
script/freedesktop.org.xml
script/generate-mime.rb
Rakefile
README
15 changes: 15 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
MimeMagic is a library to detect the mime type of a file by extension or by content.

Usage
=====

require 'mimemagic'
MimeMagic.by_extension('html').text?
MimeMagic.by_extension('.html').child_of? 'text/plain'
MimeMagic.by_magic(File.open('test.html'))
etc...

Authors
=======

Daniel Mendler
10 changes: 10 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'hoe'

$:.unshift 'lib'
require 'mimemagic'

Hoe.new 'mimemagic', MimeMagic::VERSION do |mimemagic|
mimemagic.developer 'Daniel Mendler', 'mail@daniel-mendler.de'
mimemagic.summary = 'Mime detection by extension or content'
end

90 changes: 90 additions & 0 deletions lib/mimemagic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
require 'mimemagic_tables'
require 'stringio'

# Mime type detection
class MimeMagic
VERSION = '0.1'

attr_reader :type, :mediatype, :subtype

# Mime type by type string
def initialize(type)
@type = type
@mediatype = @type.split('/')[0]
@subtype = @type.split('/')[1]
end

# Add custom mime type. You have to
# specify the type, a string list of file extensions,
# a string list of parent mime types and an optional
# detector block for magic detection.
def self.add(type, extensions, parents, *magics)
TYPES[type] = [extensions, parents, block_given? ? proc(&block) : nil]
extensions.each do |ext|
EXTENSIONS[ext] = type
end
MAGIC.unshift [type, magics] if magics
end

# Returns true if type is a text format
def text?
child_of? 'text/plain'
end

# Returns true if type is child of parent type
def child_of?(parent)
child?(type, parent)
end

# Get string list of file extensions
def extensions
TYPES.key?(type) ? TYPES[type][0] : []
end

# Lookup mime type by file extension
def self.by_extension(ext)
ext = ext.downcase
mime = EXTENSIONS[ext] || (ext[0..0] == '.' && EXTENSIONS[ext[1..-1]])
mime ? new(mime) : nil
end

# Lookup mime type by magic content analysis
# That could be slow
def self.by_magic(content)
io = content.respond_to?(:seek) ? content : StringIO.new(content.to_s, 'rb')
mime = MAGIC.find {|type, matches| magic_match(io, matches) }
mime ? new(mime[0]) : nil
end

# Return type as string
def to_s
type
end

# Allow comparison with string
def ==(x)
type == x.to_s
end

private

def child?(child, parent)
return true if child == parent
TYPES.key?(child) ? TYPES[child][1].any? {|p| child?(p, parent) } : false
end

def self.magic_match(io, matches)
matches.any? do |offset, value, children|
if Range === offset
io.seek(offset.begin)
match = io.read(offset.end - offset.begin + value.length).include?(value)
else
io.seek(offset)
match = value == io.read(value.length)
end
match && (!children || magic_match(io, children))
end
rescue
false
end
end

0 comments on commit 749a7e5

Please sign in to comment.