afp_mimemagic 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.travis.yml +20 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +2 -0
- data/LICENSE +339 -0
- data/README.md +51 -0
- data/Rakefile +15 -0
- data/lib/mimemagic/overlay.rb +11 -0
- data/lib/mimemagic/tables.rb +2208 -0
- data/lib/mimemagic/version.rb +5 -0
- data/lib/mimemagic.rb +148 -0
- data/mimemagic.gemspec +28 -0
- data/script/freedesktop.org.xml +41233 -0
- data/script/generate-mime.rb +164 -0
- data/test/files/application.gzip +0 -0
- data/test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{gdocs}.sheet +0 -0
- data/test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{msoffice}.sheet +0 -0
- data/test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{rubyxl}.sheet +0 -0
- data/test/files/application.x-bzip +0 -0
- data/test/files/application.x-ruby +2 -0
- data/test/files/application.x-tar +0 -0
- data/test/files/application.zip +0 -0
- data/test/files/image.jpeg +0 -0
- data/test/files/image.png +0 -0
- data/test/mimemagic_test.rb +160 -0
- metadata +101 -0
data/lib/mimemagic.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'mimemagic/tables'
|
2
|
+
require 'mimemagic/version'
|
3
|
+
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
# Mime type detection
|
7
|
+
class MimeMagic
|
8
|
+
attr_reader :type, :mediatype, :subtype
|
9
|
+
|
10
|
+
# Mime type by type string
|
11
|
+
def initialize(type)
|
12
|
+
@type = type
|
13
|
+
@mediatype, @subtype = type.split('/', 2)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Add custom mime type. Arguments:
|
17
|
+
# * <i>type</i>: Mime type
|
18
|
+
# * <i>options</i>: Options hash
|
19
|
+
#
|
20
|
+
# Option keys:
|
21
|
+
# * <i>:extensions</i>: String list or single string of file extensions
|
22
|
+
# * <i>:parents</i>: String list or single string of parent mime types
|
23
|
+
# * <i>:magic</i>: Mime magic specification
|
24
|
+
# * <i>:comment</i>: Comment string
|
25
|
+
def self.add(type, options)
|
26
|
+
extensions = [options[:extensions]].flatten.compact
|
27
|
+
TYPES[type] = [extensions,
|
28
|
+
[options[:parents]].flatten.compact,
|
29
|
+
options[:comment]]
|
30
|
+
extensions.each { |ext| EXTENSIONS[ext] = type }
|
31
|
+
MAGIC.unshift [type, options[:magic]] if options[:magic]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Removes a mime type from the dictionary. You might want to do this if
|
35
|
+
# you're seeing impossible conflicts (for instance, application/x-gmc-link).
|
36
|
+
# * <i>type</i>: The mime type to remove. All associated extensions and magic are removed too.
|
37
|
+
def self.remove(type)
|
38
|
+
EXTENSIONS.delete_if { |_ext, t| t == type }
|
39
|
+
MAGIC.delete_if { |t, _m| t == type }
|
40
|
+
TYPES.delete(type)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if type is a text format
|
44
|
+
def text?
|
45
|
+
mediatype == 'text' || child_of?('text/plain')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Mediatype shortcuts
|
49
|
+
def image?
|
50
|
+
mediatype == 'image'
|
51
|
+
end
|
52
|
+
|
53
|
+
def audio?
|
54
|
+
mediatype == 'audio'
|
55
|
+
end
|
56
|
+
|
57
|
+
def video?
|
58
|
+
mediatype == 'video'
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns true if type is child of parent type
|
62
|
+
def child_of?(parent)
|
63
|
+
MimeMagic.child?(type, parent)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get string list of file extensions
|
67
|
+
def extensions
|
68
|
+
TYPES.key?(type) ? TYPES[type][0] : []
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get mime comment
|
72
|
+
def comment
|
73
|
+
(TYPES.key?(type) ? TYPES[type][2] : nil).to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
# Lookup mime type by file extension
|
77
|
+
def self.by_extension(ext)
|
78
|
+
ext = ext.to_s.downcase
|
79
|
+
mime = ext[0..0] == '.' ? EXTENSIONS[ext[1..-1]] : EXTENSIONS[ext]
|
80
|
+
mime && new(mime)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Lookup mime type by filename
|
84
|
+
def self.by_path(path)
|
85
|
+
by_extension(File.extname(path))
|
86
|
+
end
|
87
|
+
|
88
|
+
# Lookup mime type by magic content analysis.
|
89
|
+
# This is a slow operation.
|
90
|
+
def self.by_magic(io)
|
91
|
+
mime = magic_match(io, :find)
|
92
|
+
mime && new(mime[0])
|
93
|
+
end
|
94
|
+
|
95
|
+
# Lookup all mime types by magic content analysis.
|
96
|
+
# This is a slower operation.
|
97
|
+
def self.all_by_magic(io)
|
98
|
+
magic_match(io, :select).map { |mime| new(mime[0]) }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return type as string
|
102
|
+
def to_s
|
103
|
+
type
|
104
|
+
end
|
105
|
+
|
106
|
+
# Allow comparison with string
|
107
|
+
def eql?(other)
|
108
|
+
type == other.to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
def hash
|
112
|
+
type.hash
|
113
|
+
end
|
114
|
+
|
115
|
+
alias == eql?
|
116
|
+
|
117
|
+
def self.child?(child, parent)
|
118
|
+
child == parent || TYPES.key?(child) && TYPES[child][1].any? { |p| child?(p, parent) }
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.magic_match(io, method)
|
122
|
+
return magic_match(StringIO.new(io.to_s), method) unless io.respond_to?(:read)
|
123
|
+
|
124
|
+
io.binmode if io.respond_to?(:binmode)
|
125
|
+
io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding)
|
126
|
+
buffer = ''.force_encoding(Encoding::BINARY)
|
127
|
+
|
128
|
+
MAGIC.send(method) { |_type, matches| magic_match_io(io, matches, buffer) }
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.magic_match_io(io, matches, buffer)
|
132
|
+
matches.any? do |offset, value, children|
|
133
|
+
match =
|
134
|
+
if offset.is_a?(Range)
|
135
|
+
io.read(offset.begin, buffer)
|
136
|
+
x = io.read(offset.end - offset.begin + value.bytesize, buffer)
|
137
|
+
x && x.include?(value)
|
138
|
+
else
|
139
|
+
io.read(offset, buffer)
|
140
|
+
io.read(value.bytesize, buffer) == value
|
141
|
+
end
|
142
|
+
io.rewind
|
143
|
+
match && (!children || magic_match_io(io, children, buffer))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private_class_method :magic_match, :magic_match_io
|
148
|
+
end
|
data/mimemagic.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/mimemagic/version'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'afp_mimemagic'
|
6
|
+
s.version = MimeMagic::VERSION
|
7
|
+
|
8
|
+
s.authors = ['Daniel Mendler']
|
9
|
+
s.date = Date.today.to_s
|
10
|
+
s.email = ['mail@daniel-mendler.de']
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_paths = %w[lib]
|
14
|
+
|
15
|
+
s.summary = 'Fast mime detection by extension or content'
|
16
|
+
s.description = 'Fast mime detection by extension or content in pure ruby (Uses freedesktop.org.xml shared-mime-info database)'
|
17
|
+
s.homepage = 'https://github.com/minad/mimemagic'
|
18
|
+
s.license = 'GPL-2.0'
|
19
|
+
|
20
|
+
s.add_development_dependency('minitest', '~> 5.11')
|
21
|
+
s.add_development_dependency('rake')
|
22
|
+
|
23
|
+
if s.respond_to?(:metadata)
|
24
|
+
s.metadata['changelog_uri'] = 'https://github.com/minad/mimemagic/blob/master/CHANGELOG.md'
|
25
|
+
s.metadata['source_code_uri'] = 'https://github.com/minad/mimemagic'
|
26
|
+
s.metadata['bug_tracker_uri'] = 'https://github.com/minad/mimemagic/issues'
|
27
|
+
end
|
28
|
+
end
|