afp_mimemagic 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,164 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class String
|
6
|
+
alias inspect_old inspect
|
7
|
+
|
8
|
+
def inspect
|
9
|
+
x = b.inspect_old.gsub(/\\x([0-9a-f]{2})/i) do
|
10
|
+
'\\%03o' % Regexp.last_match(1).to_i(16)
|
11
|
+
end
|
12
|
+
x =~ /[\\']/ ? x : x.gsub('"', '\'')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def str2int(s)
|
17
|
+
return s.to_i(16) if s[0..1].downcase == '0x'
|
18
|
+
return s.to_i(8) if s[0..0].downcase == '0'
|
19
|
+
|
20
|
+
s.to_i(10)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_matches(parent)
|
24
|
+
parent.elements.map do |match|
|
25
|
+
if match['mask']
|
26
|
+
nil
|
27
|
+
else
|
28
|
+
type = match['type']
|
29
|
+
value = match['value']
|
30
|
+
offset = match['offset'].split(':').map { |x| x.to_i }
|
31
|
+
offset = offset.size == 2 ? offset[0]..offset[1] : offset[0]
|
32
|
+
case type
|
33
|
+
when 'string'
|
34
|
+
value.gsub!(/\\(x[\dA-Fa-f]{1,2}|0\d{1,3}|\d{1,3}|.)/) { eval("\"\\#{Regexp.last_match(1)}\"") }
|
35
|
+
when 'big16'
|
36
|
+
value = str2int(value)
|
37
|
+
value = ((value >> 8).chr + (value & 0xFF).chr)
|
38
|
+
when 'big32'
|
39
|
+
value = str2int(value)
|
40
|
+
value = (((value >> 24) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 8) & 0xFF).chr + (value & 0xFF).chr)
|
41
|
+
when 'little16'
|
42
|
+
value = str2int(value)
|
43
|
+
value = ((value & 0xFF).chr + (value >> 8).chr)
|
44
|
+
when 'little32'
|
45
|
+
value = str2int(value)
|
46
|
+
value = ((value & 0xFF).chr + ((value >> 8) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 24) & 0xFF).chr)
|
47
|
+
when 'host16' # use little endian
|
48
|
+
value = str2int(value)
|
49
|
+
value = ((value & 0xFF).chr + (value >> 8).chr)
|
50
|
+
when 'host32' # use little endian
|
51
|
+
value = str2int(value)
|
52
|
+
value = ((value & 0xFF).chr + ((value >> 8) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 24) & 0xFF).chr)
|
53
|
+
when 'byte'
|
54
|
+
value = str2int(value)
|
55
|
+
value = value.chr
|
56
|
+
end
|
57
|
+
children = get_matches(match)
|
58
|
+
children.empty? ? [offset, value] : [offset, value, children]
|
59
|
+
end
|
60
|
+
end.compact
|
61
|
+
end
|
62
|
+
|
63
|
+
if ARGV.size != 1
|
64
|
+
puts "Usage: #{$0} <freedesktop.org.xml>"
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
FILE = ARGV[0]
|
69
|
+
file = File.new(FILE)
|
70
|
+
doc = Nokogiri::XML(file)
|
71
|
+
extensions = {}
|
72
|
+
types = {}
|
73
|
+
magics = []
|
74
|
+
(doc / 'mime-info/mime-type').each do |mime|
|
75
|
+
comments = Hash[*(mime / 'comment').map { |comment| [comment['xml:lang'], comment.inner_text] }.flatten]
|
76
|
+
type = mime['type']
|
77
|
+
subclass = (mime / 'sub-class-of').map { |x| x['type'] }
|
78
|
+
exts = (mime / 'glob').map { |x| x['pattern'] =~ /^\*\.([^\[\]]+)$/ ? Regexp.last_match(1).downcase : nil }.compact
|
79
|
+
(mime / 'magic').each do |magic|
|
80
|
+
priority = magic['priority'].to_i
|
81
|
+
matches = get_matches(magic)
|
82
|
+
magics << [priority, type, matches]
|
83
|
+
end
|
84
|
+
next if exts.empty?
|
85
|
+
|
86
|
+
exts.each do |x|
|
87
|
+
extensions[x] = type unless extensions.include?(x)
|
88
|
+
end
|
89
|
+
types[type] = [exts, subclass, comments[nil]]
|
90
|
+
end
|
91
|
+
|
92
|
+
magics = magics.sort { |a, b| [-a[0], a[1]] <=> [-b[0], b[1]] }
|
93
|
+
|
94
|
+
common_types = [
|
95
|
+
'image/jpeg', # .jpg
|
96
|
+
'image/png', # .png
|
97
|
+
'image/gif', # .gif
|
98
|
+
'image/tiff', # .tiff
|
99
|
+
'image/bmp', # .bmp
|
100
|
+
'image/vnd.adobe.photoshop', # .psd
|
101
|
+
'image/webp', # .webp
|
102
|
+
'image/svg+xml', # .svg
|
103
|
+
|
104
|
+
'video/x-msvideo', # .avi
|
105
|
+
'video/x-ms-wmv', # .wmv
|
106
|
+
'video/mp4', # .mp4, .m4v
|
107
|
+
'video/quicktime', # .mov
|
108
|
+
'video/mpeg', # .mpeg
|
109
|
+
'video/ogg', # .ogv
|
110
|
+
'video/webm', # .webm
|
111
|
+
'video/x-matroska', # .mkv
|
112
|
+
'video/x-flv', # .flv
|
113
|
+
|
114
|
+
'audio/mpeg', # .mp3
|
115
|
+
'audio/x-wav', # .wav
|
116
|
+
'audio/aac', # .aac
|
117
|
+
'audio/flac', # .flac
|
118
|
+
'audio/mp4', # .m4a
|
119
|
+
'audio/ogg', # .ogg
|
120
|
+
|
121
|
+
'application/pdf', # .pdf
|
122
|
+
'application/msword', # .doc
|
123
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document', # .docx
|
124
|
+
'application/vnd.ms-powerpoint', # .pps
|
125
|
+
'application/vnd.openxmlformats-officedocument.presentationml.slideshow', # .ppsx
|
126
|
+
'application/vnd.ms-excel', # .pps
|
127
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' # .ppsx
|
128
|
+
]
|
129
|
+
|
130
|
+
common_magics = common_types.map do |common_type|
|
131
|
+
magics.find { |_, type, _| type == common_type }
|
132
|
+
end
|
133
|
+
|
134
|
+
magics = (common_magics.compact + magics).uniq
|
135
|
+
|
136
|
+
puts '# -*- coding: binary -*-'
|
137
|
+
puts '# frozen_string_literal: true'
|
138
|
+
puts "# Generated from #{FILE}"
|
139
|
+
puts 'class MimeMagic'
|
140
|
+
puts ' # @private'
|
141
|
+
puts ' # :nodoc:'
|
142
|
+
puts ' EXTENSIONS = {'
|
143
|
+
extensions.keys.sort.each do |key|
|
144
|
+
puts " '#{key}' => '#{extensions[key]}',"
|
145
|
+
end
|
146
|
+
puts ' }'
|
147
|
+
puts ' # @private'
|
148
|
+
puts ' # :nodoc:'
|
149
|
+
puts ' TYPES = {'
|
150
|
+
types.keys.sort.each do |key|
|
151
|
+
exts = types[key][0].join(' ')
|
152
|
+
parents = types[key][1].sort.join(' ')
|
153
|
+
comment = types[key][2].inspect
|
154
|
+
puts " '#{key}' => [%w(#{exts}), %w(#{parents}), #{comment}],"
|
155
|
+
end
|
156
|
+
puts ' }'
|
157
|
+
puts ' # @private'
|
158
|
+
puts ' # :nodoc:'
|
159
|
+
puts ' MAGIC = ['
|
160
|
+
magics.each do |_priority, type, matches|
|
161
|
+
puts " ['#{type}', #{matches.inspect}],"
|
162
|
+
end
|
163
|
+
puts ' ]'
|
164
|
+
puts 'end'
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'mimemagic'
|
3
|
+
require 'stringio'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
class TestMimeMagic < Minitest::Test
|
7
|
+
# Do deep copy for constants of initial state.
|
8
|
+
INIT_EXTENSIONS = Marshal.load(Marshal.dump(MimeMagic::EXTENSIONS))
|
9
|
+
INIT_TYPES = Marshal.load(Marshal.dump(MimeMagic::TYPES))
|
10
|
+
INIT_MAGIC = Marshal.load(Marshal.dump(MimeMagic::MAGIC))
|
11
|
+
|
12
|
+
def setup
|
13
|
+
extentions = Marshal.load(Marshal.dump(INIT_EXTENSIONS))
|
14
|
+
types = Marshal.load(Marshal.dump(INIT_TYPES))
|
15
|
+
magic = Marshal.load(Marshal.dump(INIT_MAGIC))
|
16
|
+
MimeMagic.send(:remove_const, :EXTENSIONS) if MimeMagic.const_defined?(:EXTENSIONS)
|
17
|
+
MimeMagic.send(:remove_const, :TYPES) if MimeMagic.const_defined?(:TYPES)
|
18
|
+
MimeMagic.send(:remove_const, :MAGIC) if MimeMagic.const_defined?(:MAGIC)
|
19
|
+
MimeMagic.const_set('EXTENSIONS', extentions)
|
20
|
+
MimeMagic.const_set('TYPES', types)
|
21
|
+
MimeMagic.const_set('MAGIC', magic)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_have_type_mediatype_and_subtype
|
25
|
+
assert_equal 'text/html', MimeMagic.new('text/html').type
|
26
|
+
assert_equal 'text', MimeMagic.new('text/html').mediatype
|
27
|
+
assert_equal 'html', MimeMagic.new('text/html').subtype
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_have_mediatype_helpers
|
31
|
+
assert MimeMagic.new('text/plain').text?
|
32
|
+
assert MimeMagic.new('text/html').text?
|
33
|
+
assert MimeMagic.new('application/xhtml+xml').text?
|
34
|
+
refute MimeMagic.new('application/octet-stream').text?
|
35
|
+
refute MimeMagic.new('image/png').text?
|
36
|
+
assert MimeMagic.new('image/png').image?
|
37
|
+
assert MimeMagic.new('video/ogg').video?
|
38
|
+
assert MimeMagic.new('audio/mpeg').audio?
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_have_hierarchy
|
42
|
+
assert MimeMagic.new('text/html').child_of?('text/plain')
|
43
|
+
assert MimeMagic.new('text/x-java').child_of?('text/plain')
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_have_extensions
|
47
|
+
assert_equal %w[htm html], MimeMagic.new('text/html').extensions
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_have_comment
|
51
|
+
assert_equal 'HTML document', MimeMagic.new('text/html').comment
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_recognize_extensions
|
55
|
+
assert_equal 'text/html', MimeMagic.by_extension('.html').to_s
|
56
|
+
assert_equal 'text/html', MimeMagic.by_extension('html').to_s
|
57
|
+
assert_equal 'text/html', MimeMagic.by_extension(:html).to_s
|
58
|
+
assert_equal 'application/x-ruby', MimeMagic.by_extension('rb').to_s
|
59
|
+
assert_nil MimeMagic.by_extension('crazy')
|
60
|
+
assert_nil MimeMagic.by_extension('')
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_recognize_by_a_path
|
64
|
+
assert_equal 'text/html', MimeMagic.by_path('/adsjkfa/kajsdfkadsf/kajsdfjasdf.html').to_s
|
65
|
+
assert_equal 'text/html', MimeMagic.by_path('something.html').to_s
|
66
|
+
assert_equal 'application/x-ruby', MimeMagic.by_path('wtf.rb').to_s
|
67
|
+
assert_nil MimeMagic.by_path('where/am.html/crazy')
|
68
|
+
assert_nil MimeMagic.by_path('')
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_recognize_xlsx_as_zip_without_magic
|
72
|
+
file = 'test/files/application.vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
73
|
+
%w[msoffice rubyxl gdocs].each do |variant|
|
74
|
+
file = "test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{#{variant}}.sheet"
|
75
|
+
assert_equal 'application/zip', MimeMagic.by_magic(File.read(file)).to_s
|
76
|
+
assert_equal 'application/zip', MimeMagic.by_magic(File.open(file, 'rb')).to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_recognize_by_magic
|
81
|
+
load 'mimemagic/overlay.rb'
|
82
|
+
Dir['test/files/*'].each do |file|
|
83
|
+
mime = file[11..-1].sub('.', '/').sub(/\{\w+\}/, '')
|
84
|
+
assert_equal mime, MimeMagic.by_magic(File.read(file)).to_s
|
85
|
+
assert_equal mime, MimeMagic.by_magic(File.open(file, 'rb')).to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_recognize_all_by_magic
|
90
|
+
load 'mimemagic/overlay.rb'
|
91
|
+
%w[msoffice rubyxl gdocs].each do |variant|
|
92
|
+
file = "test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{#{variant}}.sheet"
|
93
|
+
mimes = %w[application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/zip]
|
94
|
+
assert_equal mimes, MimeMagic.all_by_magic(File.read(file)).map(&:type)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_have_add
|
99
|
+
MimeMagic.add('application/mimemagic-test',
|
100
|
+
extensions: %w[ext1 ext2],
|
101
|
+
parents: 'application/xml',
|
102
|
+
comment: 'Comment')
|
103
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_extension('ext1').to_s
|
104
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_extension('ext2').to_s
|
105
|
+
assert_equal 'Comment', MimeMagic.by_extension('ext2').comment
|
106
|
+
assert_equal %w[ext1 ext2], MimeMagic.new('application/mimemagic-test').extensions
|
107
|
+
assert MimeMagic.new('application/mimemagic-test').child_of?('text/plain')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_process_magic
|
111
|
+
MimeMagic.add('application/mimemagic-test',
|
112
|
+
magic: [[0, 'MAGICTEST'], # MAGICTEST at position 0
|
113
|
+
[1, 'MAGICTEST'], # MAGICTEST at position 1
|
114
|
+
[9..12, 'MAGICTEST'], # MAGICTEST starting at position 9 to 12
|
115
|
+
[2, 'MAGICTEST', [[0, 'X'], [0, 'Y']]]]) # MAGICTEST at position 2 and (X at 0 or Y at 0)
|
116
|
+
|
117
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('MAGICTEST').to_s
|
118
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('XMAGICTEST').to_s
|
119
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(' MAGICTEST').to_s
|
120
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789MAGICTEST').to_s
|
121
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789ABMAGICTEST').to_s
|
122
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789ABCMAGICTEST').to_s
|
123
|
+
assert_nil MimeMagic.by_magic('123456789ABCDMAGICTEST')
|
124
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('X MAGICTEST').to_s
|
125
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic('Y MAGICTEST').to_s
|
126
|
+
assert_nil MimeMagic.by_magic('Z MAGICTEST')
|
127
|
+
|
128
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('MAGICTEST')).to_s
|
129
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('XMAGICTEST')).to_s
|
130
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new(' MAGICTEST')).to_s
|
131
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('123456789MAGICTEST')).to_s
|
132
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('123456789ABMAGICTEST')).to_s
|
133
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('123456789ABCMAGICTEST')).to_s
|
134
|
+
assert_nil MimeMagic.by_magic(StringIO.new('123456789ABCDMAGICTEST'))
|
135
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('X MAGICTEST')).to_s
|
136
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new('Y MAGICTEST')).to_s
|
137
|
+
assert_nil MimeMagic.by_magic(StringIO.new('Z MAGICTEST'))
|
138
|
+
end
|
139
|
+
|
140
|
+
class IOObject
|
141
|
+
def initialize
|
142
|
+
@io = StringIO.new('MAGICTEST')
|
143
|
+
end
|
144
|
+
|
145
|
+
extend Forwardable
|
146
|
+
delegate %i[read size rewind eof? close] => :@io
|
147
|
+
end
|
148
|
+
|
149
|
+
class StringableObject
|
150
|
+
def to_s
|
151
|
+
'MAGICTEST'
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_handle_different_file_objects
|
156
|
+
MimeMagic.add('application/mimemagic-test', magic: [[0, 'MAGICTEST']])
|
157
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(IOObject.new).to_s
|
158
|
+
assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringableObject.new).to_s
|
159
|
+
end
|
160
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: afp_mimemagic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Mendler
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Fast mime detection by extension or content in pure ruby (Uses freedesktop.org.xml
|
42
|
+
shared-mime-info database)
|
43
|
+
email:
|
44
|
+
- mail@daniel-mendler.de
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- ".travis.yml"
|
51
|
+
- ".yardopts"
|
52
|
+
- CHANGELOG.md
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- lib/mimemagic.rb
|
58
|
+
- lib/mimemagic/overlay.rb
|
59
|
+
- lib/mimemagic/tables.rb
|
60
|
+
- lib/mimemagic/version.rb
|
61
|
+
- mimemagic.gemspec
|
62
|
+
- script/freedesktop.org.xml
|
63
|
+
- script/generate-mime.rb
|
64
|
+
- test/files/application.gzip
|
65
|
+
- test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{gdocs}.sheet
|
66
|
+
- test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{msoffice}.sheet
|
67
|
+
- test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{rubyxl}.sheet
|
68
|
+
- test/files/application.x-bzip
|
69
|
+
- test/files/application.x-ruby
|
70
|
+
- test/files/application.x-tar
|
71
|
+
- test/files/application.zip
|
72
|
+
- test/files/image.jpeg
|
73
|
+
- test/files/image.png
|
74
|
+
- test/mimemagic_test.rb
|
75
|
+
homepage: https://github.com/minad/mimemagic
|
76
|
+
licenses:
|
77
|
+
- GPL-2.0
|
78
|
+
metadata:
|
79
|
+
changelog_uri: https://github.com/minad/mimemagic/blob/master/CHANGELOG.md
|
80
|
+
source_code_uri: https://github.com/minad/mimemagic
|
81
|
+
bug_tracker_uri: https://github.com/minad/mimemagic/issues
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubygems_version: 3.0.8
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Fast mime detection by extension or content
|
101
|
+
test_files: []
|