shared-mime-info 0.1 → 0.2.5
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/LICENSE +13 -0
- data/README.rdoc +25 -0
- data/Rakefile +43 -0
- data/lib/magics.rb +364 -0
- data/lib/shared-mime-info.rb +145 -377
- data/lib/shared-mime-info/magic.rb +79 -0
- data/lib/shared-mime-info/type.rb +96 -0
- data/lib/shared-mime-info/version.rb +3 -0
- metadata +48 -42
- data/copying.txt +0 -20
- data/rakefile +0 -30
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d7bc9f651e0b3ff517d8c2ec1dfad3912d246449
|
4
|
+
data.tar.gz: 84771f2ad03cb8a8c176297d3f5ddbc9055cddf5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c91043438e9e4d8da897b2bc944ac0953817cea3d1e28e3fe1e4256f431fb7efe3cf01eeb8ce33fdb2b7477218b4683e745265ac8dde5b0abdbcd29f25701f55
|
7
|
+
data.tar.gz: bbcb438545358fd618c5425a4acf045b6d0ce6f7aeb6cecd29a44c4323481b0172882b4fca3ae3a3cc9eb4713b94afa2967586efcbb1ccc7c9264520039b3825
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2006 Mael Clerambault <mael@clerambault.fr>
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= shared-mime-info
|
2
|
+
|
3
|
+
shared-mime-info is a pure Ruby library for accessing the MIME info database provided by Freedesktop[http://freedesktop.org/] on {Standards/shared-mime-info-spec}[http://freedesktop.org/wiki/Specifications/shared-mime-info-spec].
|
4
|
+
|
5
|
+
= Project
|
6
|
+
|
7
|
+
The rubyforge project : http://rubyforge.org/projects/shared-mime
|
8
|
+
|
9
|
+
The github repository: http://github.com/hanklords/shared-mime-info/tree/master
|
10
|
+
|
11
|
+
|
12
|
+
= Usage
|
13
|
+
|
14
|
+
require 'shared-mime-info'
|
15
|
+
|
16
|
+
MIME.check 'sample.jpg' # => #<MIME::Type ..., @type="image/jpeg">
|
17
|
+
|
18
|
+
MIME['image/jpeg'].match_filename? 'sample.jpg' # => true
|
19
|
+
|
20
|
+
= Notes
|
21
|
+
* Ensure that shared-mime-info is installed on the system:
|
22
|
+
> brew install shared-mime-info
|
23
|
+
* You may need to update the mime database first:
|
24
|
+
> update-mime-database
|
25
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rdoc/task'
|
2
|
+
require 'rake/packagetask'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
|
5
|
+
require_relative 'lib/shared-mime-info/version'
|
6
|
+
|
7
|
+
PKG_FILES = FileList["lib/*.rb", "lib/shared-mime-info/*", "Rakefile", "LICENSE", "README.rdoc"]
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.summary = "Library to guess the MIME type of a file with both filename lookup and magic file detection"
|
11
|
+
s.name = "shared-mime-info"
|
12
|
+
s.description = 'shared-mime-info is a pure Ruby library for accessing the MIME info database provided by Freedesktop'
|
13
|
+
s.author = "Mael Clerambault"
|
14
|
+
s.email = "mael@clerambault.fr"
|
15
|
+
s.license = 'Public Domain'
|
16
|
+
s.homepage = 'http://shared-mime.rubyforge.org/'
|
17
|
+
s.version = SharedMimeInfo::VERSION
|
18
|
+
s.files = PKG_FILES.to_a
|
19
|
+
end
|
20
|
+
|
21
|
+
RDoc::Task.new do |rd|
|
22
|
+
rd.rdoc_files.include "README.rdoc", "lib/*.rb"
|
23
|
+
rd.options << "--inline-source"
|
24
|
+
end
|
25
|
+
|
26
|
+
Gem::PackageTask.new(spec).define
|
27
|
+
|
28
|
+
desc 'Generate the magics parser'
|
29
|
+
file "lib/magics.rb" => "magics.rl" do |t|
|
30
|
+
sh "ragel -R -o #{t.name} #{t.prerequisites.join(' ')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Generate the gemspec'
|
34
|
+
task :spec do
|
35
|
+
open("#{spec.name}.gemspec", "w") {|g| g.puts spec.to_ruby }
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Open an pry session preloaded with this library"
|
39
|
+
task :console do
|
40
|
+
require 'pry' rescue nil
|
41
|
+
console = defined?(Pry) ? :pry : :irb
|
42
|
+
sh "#{console} -rubygems -I lib -r shared-mime-info.rb"
|
43
|
+
end
|
data/lib/magics.rb
ADDED
@@ -0,0 +1,364 @@
|
|
1
|
+
|
2
|
+
# line 1 "magics.rl"
|
3
|
+
module MIME
|
4
|
+
module Magic
|
5
|
+
|
6
|
+
# line 7 "lib/magics.rb"
|
7
|
+
class << self
|
8
|
+
attr_accessor :_magic_actions
|
9
|
+
private :_magic_actions, :_magic_actions=
|
10
|
+
end
|
11
|
+
self._magic_actions = [
|
12
|
+
0, 1, 0, 1, 1, 1, 3, 1,
|
13
|
+
5, 1, 12, 1, 13, 2, 0, 1,
|
14
|
+
2, 2, 6, 2, 2, 7, 2, 2,
|
15
|
+
9, 2, 11, 12, 3, 2, 8, 4,
|
16
|
+
3, 2, 9, 13, 3, 2, 10, 13,
|
17
|
+
3, 12, 0, 1, 4, 11, 12, 0,
|
18
|
+
1
|
19
|
+
]
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :_magic_key_offsets
|
23
|
+
private :_magic_key_offsets, :_magic_key_offsets=
|
24
|
+
end
|
25
|
+
self._magic_key_offsets = [
|
26
|
+
0, 0, 1, 2, 3, 4, 5, 6,
|
27
|
+
7, 8, 9, 10, 11, 12, 14, 17,
|
28
|
+
27, 36, 46, 57, 58, 61, 64, 66,
|
29
|
+
69, 73, 76, 78, 81, 83, 87, 88
|
30
|
+
]
|
31
|
+
|
32
|
+
class << self
|
33
|
+
attr_accessor :_magic_trans_keys
|
34
|
+
private :_magic_trans_keys, :_magic_trans_keys=
|
35
|
+
end
|
36
|
+
self._magic_trans_keys = [
|
37
|
+
77, 73, 77, 69, 45, 77, 97, 103,
|
38
|
+
105, 99, 0, 10, 48, 57, 58, 48,
|
39
|
+
57, 43, 95, 45, 46, 48, 57, 65,
|
40
|
+
90, 97, 122, 43, 47, 95, 45, 57,
|
41
|
+
65, 90, 97, 122, 43, 95, 45, 46,
|
42
|
+
48, 57, 65, 90, 97, 122, 43, 93,
|
43
|
+
95, 45, 46, 48, 57, 65, 90, 97,
|
44
|
+
122, 10, 62, 48, 57, 62, 48, 57,
|
45
|
+
48, 57, 61, 48, 57, 10, 38, 43,
|
46
|
+
126, 10, 43, 126, 48, 57, 10, 48,
|
47
|
+
57, 48, 57, 10, 43, 48, 57, 91,
|
48
|
+
62, 91, 48, 57, 0
|
49
|
+
]
|
50
|
+
|
51
|
+
class << self
|
52
|
+
attr_accessor :_magic_single_lengths
|
53
|
+
private :_magic_single_lengths, :_magic_single_lengths=
|
54
|
+
end
|
55
|
+
self._magic_single_lengths = [
|
56
|
+
0, 1, 1, 1, 1, 1, 1, 1,
|
57
|
+
1, 1, 1, 1, 1, 0, 1, 2,
|
58
|
+
3, 2, 3, 1, 1, 1, 0, 1,
|
59
|
+
4, 3, 0, 1, 0, 2, 1, 2
|
60
|
+
]
|
61
|
+
|
62
|
+
class << self
|
63
|
+
attr_accessor :_magic_range_lengths
|
64
|
+
private :_magic_range_lengths, :_magic_range_lengths=
|
65
|
+
end
|
66
|
+
self._magic_range_lengths = [
|
67
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
68
|
+
0, 0, 0, 0, 0, 1, 1, 4,
|
69
|
+
3, 4, 4, 0, 1, 1, 1, 1,
|
70
|
+
0, 0, 1, 1, 1, 1, 0, 1
|
71
|
+
]
|
72
|
+
|
73
|
+
class << self
|
74
|
+
attr_accessor :_magic_index_offsets
|
75
|
+
private :_magic_index_offsets, :_magic_index_offsets=
|
76
|
+
end
|
77
|
+
self._magic_index_offsets = [
|
78
|
+
0, 0, 2, 4, 6, 8, 10, 12,
|
79
|
+
14, 16, 18, 20, 22, 24, 26, 29,
|
80
|
+
36, 43, 50, 58, 60, 63, 66, 68,
|
81
|
+
71, 76, 80, 82, 85, 87, 91, 93
|
82
|
+
]
|
83
|
+
|
84
|
+
class << self
|
85
|
+
attr_accessor :_magic_indicies
|
86
|
+
private :_magic_indicies, :_magic_indicies=
|
87
|
+
end
|
88
|
+
self._magic_indicies = [
|
89
|
+
0, 1, 2, 1, 3, 1, 4, 1,
|
90
|
+
5, 1, 6, 1, 7, 1, 8, 1,
|
91
|
+
9, 1, 10, 1, 11, 1, 12, 1,
|
92
|
+
13, 1, 15, 14, 1, 16, 16, 16,
|
93
|
+
16, 16, 16, 1, 17, 18, 17, 17,
|
94
|
+
17, 17, 1, 19, 19, 19, 19, 19,
|
95
|
+
19, 1, 19, 20, 19, 19, 19, 19,
|
96
|
+
19, 1, 21, 1, 23, 22, 1, 25,
|
97
|
+
24, 1, 26, 1, 28, 27, 1, 29,
|
98
|
+
30, 31, 32, 1, 29, 31, 32, 1,
|
99
|
+
33, 1, 34, 35, 1, 36, 1, 37,
|
100
|
+
38, 39, 1, 40, 1, 42, 40, 41,
|
101
|
+
1, 0
|
102
|
+
]
|
103
|
+
|
104
|
+
class << self
|
105
|
+
attr_accessor :_magic_trans_targs
|
106
|
+
private :_magic_trans_targs, :_magic_trans_targs=
|
107
|
+
end
|
108
|
+
self._magic_trans_targs = [
|
109
|
+
2, 0, 3, 4, 5, 6, 7, 8,
|
110
|
+
9, 10, 11, 12, 30, 14, 14, 15,
|
111
|
+
16, 16, 17, 18, 19, 20, 21, 22,
|
112
|
+
21, 22, 23, 23, 24, 31, 25, 26,
|
113
|
+
28, 27, 31, 27, 29, 31, 26, 29,
|
114
|
+
13, 21, 22
|
115
|
+
]
|
116
|
+
|
117
|
+
class << self
|
118
|
+
attr_accessor :_magic_trans_actions
|
119
|
+
private :_magic_trans_actions, :_magic_trans_actions=
|
120
|
+
end
|
121
|
+
self._magic_trans_actions = [
|
122
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
123
|
+
0, 0, 0, 0, 0, 13, 3, 16,
|
124
|
+
1, 0, 0, 3, 5, 0, 44, 25,
|
125
|
+
3, 19, 13, 3, 28, 11, 7, 0,
|
126
|
+
0, 13, 36, 3, 13, 32, 22, 3,
|
127
|
+
0, 40, 9
|
128
|
+
]
|
129
|
+
|
130
|
+
class << self
|
131
|
+
attr_accessor :magic_start
|
132
|
+
end
|
133
|
+
self.magic_start = 1;
|
134
|
+
class << self
|
135
|
+
attr_accessor :magic_first_final
|
136
|
+
end
|
137
|
+
self.magic_first_final = 30;
|
138
|
+
class << self
|
139
|
+
attr_accessor :magic_error
|
140
|
+
end
|
141
|
+
self.magic_error = 0;
|
142
|
+
|
143
|
+
class << self
|
144
|
+
attr_accessor :magic_en_main
|
145
|
+
end
|
146
|
+
self.magic_en_main = 1;
|
147
|
+
|
148
|
+
|
149
|
+
# line 53 "magics.rl"
|
150
|
+
|
151
|
+
|
152
|
+
def self.parse_magic( data )
|
153
|
+
magics = []
|
154
|
+
data = data.unpack("c*")
|
155
|
+
|
156
|
+
|
157
|
+
# line 158 "lib/magics.rb"
|
158
|
+
begin
|
159
|
+
p ||= 0
|
160
|
+
pe ||= data.length
|
161
|
+
cs = magic_start
|
162
|
+
end
|
163
|
+
|
164
|
+
# line 60 "magics.rl"
|
165
|
+
eof = pe
|
166
|
+
|
167
|
+
# line 168 "lib/magics.rb"
|
168
|
+
begin
|
169
|
+
_klen, _trans, _keys, _acts, _nacts = nil
|
170
|
+
_goto_level = 0
|
171
|
+
_resume = 10
|
172
|
+
_eof_trans = 15
|
173
|
+
_again = 20
|
174
|
+
_test_eof = 30
|
175
|
+
_out = 40
|
176
|
+
while true
|
177
|
+
_trigger_goto = false
|
178
|
+
if _goto_level <= 0
|
179
|
+
if p == pe
|
180
|
+
_goto_level = _test_eof
|
181
|
+
next
|
182
|
+
end
|
183
|
+
if cs == 0
|
184
|
+
_goto_level = _out
|
185
|
+
next
|
186
|
+
end
|
187
|
+
end
|
188
|
+
if _goto_level <= _resume
|
189
|
+
_keys = _magic_key_offsets[cs]
|
190
|
+
_trans = _magic_index_offsets[cs]
|
191
|
+
_klen = _magic_single_lengths[cs]
|
192
|
+
_break_match = false
|
193
|
+
|
194
|
+
begin
|
195
|
+
if _klen > 0
|
196
|
+
_lower = _keys
|
197
|
+
_upper = _keys + _klen - 1
|
198
|
+
|
199
|
+
loop do
|
200
|
+
break if _upper < _lower
|
201
|
+
_mid = _lower + ( (_upper - _lower) >> 1 )
|
202
|
+
|
203
|
+
if data[p] < _magic_trans_keys[_mid]
|
204
|
+
_upper = _mid - 1
|
205
|
+
elsif data[p] > _magic_trans_keys[_mid]
|
206
|
+
_lower = _mid + 1
|
207
|
+
else
|
208
|
+
_trans += (_mid - _keys)
|
209
|
+
_break_match = true
|
210
|
+
break
|
211
|
+
end
|
212
|
+
end # loop
|
213
|
+
break if _break_match
|
214
|
+
_keys += _klen
|
215
|
+
_trans += _klen
|
216
|
+
end
|
217
|
+
_klen = _magic_range_lengths[cs]
|
218
|
+
if _klen > 0
|
219
|
+
_lower = _keys
|
220
|
+
_upper = _keys + (_klen << 1) - 2
|
221
|
+
loop do
|
222
|
+
break if _upper < _lower
|
223
|
+
_mid = _lower + (((_upper-_lower) >> 1) & ~1)
|
224
|
+
if data[p] < _magic_trans_keys[_mid]
|
225
|
+
_upper = _mid - 2
|
226
|
+
elsif data[p] > _magic_trans_keys[_mid+1]
|
227
|
+
_lower = _mid + 2
|
228
|
+
else
|
229
|
+
_trans += ((_mid - _keys) >> 1)
|
230
|
+
_break_match = true
|
231
|
+
break
|
232
|
+
end
|
233
|
+
end # loop
|
234
|
+
break if _break_match
|
235
|
+
_trans += _klen
|
236
|
+
end
|
237
|
+
end while false
|
238
|
+
_trans = _magic_indicies[_trans]
|
239
|
+
cs = _magic_trans_targs[_trans]
|
240
|
+
if _magic_trans_actions[_trans] != 0
|
241
|
+
_acts = _magic_trans_actions[_trans]
|
242
|
+
_nacts = _magic_actions[_acts]
|
243
|
+
_acts += 1
|
244
|
+
while _nacts > 0
|
245
|
+
_nacts -= 1
|
246
|
+
_acts += 1
|
247
|
+
case _magic_actions[_acts - 1]
|
248
|
+
when 0 then
|
249
|
+
# line 6 "magics.rl"
|
250
|
+
begin
|
251
|
+
b = p end
|
252
|
+
# line 6 "magics.rl"
|
253
|
+
when 1 then
|
254
|
+
# line 7 "magics.rl"
|
255
|
+
begin
|
256
|
+
e = data[ b .. p] end
|
257
|
+
# line 7 "magics.rl"
|
258
|
+
when 2 then
|
259
|
+
# line 8 "magics.rl"
|
260
|
+
begin
|
261
|
+
n = e.pack("c*").to_i end
|
262
|
+
# line 8 "magics.rl"
|
263
|
+
when 3 then
|
264
|
+
# line 12 "magics.rl"
|
265
|
+
begin
|
266
|
+
type = e.pack("c*") end
|
267
|
+
# line 12 "magics.rl"
|
268
|
+
when 4 then
|
269
|
+
# line 17 "magics.rl"
|
270
|
+
begin
|
271
|
+
|
272
|
+
value_length = data[p+1, 2].pack("c*").unpack('n').first
|
273
|
+
p +=2
|
274
|
+
value = data[p+1, value_length]
|
275
|
+
mask = [0xff] * value_length
|
276
|
+
p += value_length
|
277
|
+
end
|
278
|
+
# line 17 "magics.rl"
|
279
|
+
when 5 then
|
280
|
+
# line 24 "magics.rl"
|
281
|
+
begin
|
282
|
+
|
283
|
+
mask = data[p+1, value_length]
|
284
|
+
p += value_length
|
285
|
+
end
|
286
|
+
# line 24 "magics.rl"
|
287
|
+
when 6 then
|
288
|
+
# line 28 "magics.rl"
|
289
|
+
begin
|
290
|
+
priority = n end
|
291
|
+
# line 28 "magics.rl"
|
292
|
+
when 7 then
|
293
|
+
# line 29 "magics.rl"
|
294
|
+
begin
|
295
|
+
indent = n end
|
296
|
+
# line 29 "magics.rl"
|
297
|
+
when 8 then
|
298
|
+
# line 30 "magics.rl"
|
299
|
+
begin
|
300
|
+
start_offset = n end
|
301
|
+
# line 30 "magics.rl"
|
302
|
+
when 9 then
|
303
|
+
# line 31 "magics.rl"
|
304
|
+
begin
|
305
|
+
word_size = n end
|
306
|
+
# line 31 "magics.rl"
|
307
|
+
when 10 then
|
308
|
+
# line 32 "magics.rl"
|
309
|
+
begin
|
310
|
+
range_length = n end
|
311
|
+
# line 32 "magics.rl"
|
312
|
+
when 11 then
|
313
|
+
# line 33 "magics.rl"
|
314
|
+
begin
|
315
|
+
magics << RootEntry.new(type, priority) end
|
316
|
+
# line 33 "magics.rl"
|
317
|
+
when 12 then
|
318
|
+
# line 34 "magics.rl"
|
319
|
+
begin
|
320
|
+
indent = 0; word_size = 0; range_length = 1 end
|
321
|
+
# line 34 "magics.rl"
|
322
|
+
when 13 then
|
323
|
+
# line 35 "magics.rl"
|
324
|
+
begin
|
325
|
+
|
326
|
+
magics.last.add_subentry Entry.new(indent, start_offset, value_length, value, mask, word_size, range_length)
|
327
|
+
end
|
328
|
+
# line 35 "magics.rl"
|
329
|
+
# line 330 "lib/magics.rb"
|
330
|
+
end # action switch
|
331
|
+
end
|
332
|
+
end
|
333
|
+
if _trigger_goto
|
334
|
+
next
|
335
|
+
end
|
336
|
+
end
|
337
|
+
if _goto_level <= _again
|
338
|
+
if cs == 0
|
339
|
+
_goto_level = _out
|
340
|
+
next
|
341
|
+
end
|
342
|
+
p += 1
|
343
|
+
if p != pe
|
344
|
+
_goto_level = _resume
|
345
|
+
next
|
346
|
+
end
|
347
|
+
end
|
348
|
+
if _goto_level <= _test_eof
|
349
|
+
end
|
350
|
+
if _goto_level <= _out
|
351
|
+
break
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
# line 62 "magics.rl"
|
357
|
+
if cs < magic_first_final
|
358
|
+
raise BadMagic
|
359
|
+
end
|
360
|
+
|
361
|
+
magics
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
data/lib/shared-mime-info.rb
CHANGED
@@ -1,377 +1,145 @@
|
|
1
|
-
# Copyright (c) 2006
|
2
|
-
#
|
3
|
-
# Permission
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# => "HTML page"
|
147
|
-
#
|
148
|
-
# MIME.types['text/html'].comment['fr']
|
149
|
-
# => "page HTML"
|
150
|
-
def comment
|
151
|
-
file = ''
|
152
|
-
MIME.mime_dirs.each { |dir|
|
153
|
-
file = "#{dir}/#{@type}.xml"
|
154
|
-
break if File.file? file
|
155
|
-
}
|
156
|
-
|
157
|
-
open(file) { |f|
|
158
|
-
doc = REXML::Document.new f
|
159
|
-
comments = {}
|
160
|
-
REXML::XPath.match(doc, '*/comment').each { |c|
|
161
|
-
if att = c.attributes['xml:lang']
|
162
|
-
comments[att] = c.text
|
163
|
-
else
|
164
|
-
comments.default = c.text
|
165
|
-
end
|
166
|
-
}
|
167
|
-
}
|
168
|
-
comments
|
169
|
-
end
|
170
|
-
|
171
|
-
# Returns all the types this type is a subclass of.
|
172
|
-
def parents
|
173
|
-
file = ''
|
174
|
-
MIME.mime_dirs.each { |dir|
|
175
|
-
file = "#{dir}/#{@type}.xml"
|
176
|
-
break if File.file? file
|
177
|
-
}
|
178
|
-
|
179
|
-
open(file) { |f|
|
180
|
-
doc = REXML::Document.new f
|
181
|
-
REXML::XPath.match(doc, '*/sub-class-of').collect { |c|
|
182
|
-
MIME[c.attributes['type']]
|
183
|
-
}
|
184
|
-
}
|
185
|
-
end
|
186
|
-
|
187
|
-
# Equality test.
|
188
|
-
#
|
189
|
-
# MIME['text/html'] == 'text/html'
|
190
|
-
# => true
|
191
|
-
def ==(type)
|
192
|
-
if type.is_a? Type
|
193
|
-
@type == type.type
|
194
|
-
elsif type.respond_to? :to_str
|
195
|
-
@type == type
|
196
|
-
else
|
197
|
-
false
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# Check if _filename_ is of this particular type by comparing it to
|
202
|
-
# some common extensions.
|
203
|
-
#
|
204
|
-
# MIME.types['text/html'].match_filename? 'index.html'
|
205
|
-
# => true
|
206
|
-
def match_filename?(filename)
|
207
|
-
@glob_patterns.any? {|pattern| File.fnmatch pattern, filename}
|
208
|
-
end
|
209
|
-
|
210
|
-
# Check if _file_ is of this particular type by looking for precise
|
211
|
-
# patterns (_magic_ numbers) in different locations of the file.
|
212
|
-
#
|
213
|
-
# _file_ must be an IO object opened with read permissions.
|
214
|
-
def match_file?(file)
|
215
|
-
if @magic.nil?
|
216
|
-
false
|
217
|
-
else
|
218
|
-
@magic.check_file file
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def initialize(type) # :nodoc:
|
223
|
-
@type = type.freeze
|
224
|
-
@glob_patterns = []
|
225
|
-
end
|
226
|
-
|
227
|
-
def load_magic(magic, priority) # :nodoc:
|
228
|
-
@magic_priority = priority
|
229
|
-
@magic = Magic.parse magic
|
230
|
-
end
|
231
|
-
|
232
|
-
def add_glob(glob) # :nodoc:
|
233
|
-
@glob_patterns << glob.freeze
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
class << self
|
238
|
-
attr_reader :mime_dirs # :nodoc:
|
239
|
-
|
240
|
-
# Returns the MIME::Type object corresponding to _type_.
|
241
|
-
def [](type)
|
242
|
-
@types.fetch type, nil
|
243
|
-
end
|
244
|
-
|
245
|
-
# Look for the type of a file by doing successive checks on
|
246
|
-
# the filename patterns.
|
247
|
-
#
|
248
|
-
# Returns a MIME::Type object or _nil_ if nothing matches.
|
249
|
-
def check_globs(filename)
|
250
|
-
enum = Enumerable::Enumerator.new(@globs, :each_key)
|
251
|
-
found = enum.select { |pattern| File.fnmatch pattern, filename }
|
252
|
-
|
253
|
-
if found.empty?
|
254
|
-
downcase_filename = filename.downcase
|
255
|
-
found = enum.select { |pattern|
|
256
|
-
File.fnmatch pattern, downcase_filename
|
257
|
-
}
|
258
|
-
end
|
259
|
-
|
260
|
-
@globs[found.max]
|
261
|
-
end
|
262
|
-
|
263
|
-
# Look for the type of a file by doing successive checks on
|
264
|
-
# _magic_ numbers.
|
265
|
-
#
|
266
|
-
# Returns a MIME::Type object or _nil_ if nothing matches.
|
267
|
-
def check_magics(file)
|
268
|
-
if file.respond_to? :read
|
269
|
-
check_magics_with_priority(file, 0)
|
270
|
-
else
|
271
|
-
open(file) {|f| check_magics_with_priority(f, 0) }
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# Look for the type of a file by doing successive checks with
|
276
|
-
# the filename patterns or magic numbers. If none of the matches
|
277
|
-
# are successful, returns a type of <b>application/octet-stream</b> if
|
278
|
-
# the file contains control characters at its beginning, or <b>text/plain</b> otherwise.
|
279
|
-
#
|
280
|
-
# Returns a MIME::Type object.
|
281
|
-
def check(filename)
|
282
|
-
check_special(filename) ||
|
283
|
-
open(filename) { |f|
|
284
|
-
check_magics_with_priority(f, 80) ||
|
285
|
-
check_globs(filename) ||
|
286
|
-
check_magics_with_priority(f, 0) ||
|
287
|
-
check_default(f)
|
288
|
-
}
|
289
|
-
end
|
290
|
-
|
291
|
-
private
|
292
|
-
def check_magics_with_priority(f, priority_threshold)
|
293
|
-
@magics.find { |t|
|
294
|
-
break if t.magic_priority < priority_threshold
|
295
|
-
t.match_file? f
|
296
|
-
}
|
297
|
-
end
|
298
|
-
|
299
|
-
def check_special(filename)
|
300
|
-
case File.ftype(filename)
|
301
|
-
when 'directory' then @types['inode/directory']
|
302
|
-
when 'characterSpecial' then @types['inode/chardevice']
|
303
|
-
when 'blockSpecial' then @types['inode/blockdevice']
|
304
|
-
when 'fifo' then @types['inode/fifo']
|
305
|
-
when 'socket' then @types['inode/socket']
|
306
|
-
else
|
307
|
-
nil
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def check_default(f)
|
312
|
-
f.pos = 0
|
313
|
-
firsts = f.read(32) || ''
|
314
|
-
bytes = firsts.unpack('C*')
|
315
|
-
if bytes.any? {|byte| byte < 32 && ![9, 10, 13].include?(byte) }
|
316
|
-
@types['application/octet-stream']
|
317
|
-
else
|
318
|
-
@types['text/plain']
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
def load_globs(file)
|
323
|
-
open(file) { |f|
|
324
|
-
f.each { |line|
|
325
|
-
next if line =~ /^#/
|
326
|
-
cline = line.chomp
|
327
|
-
type, pattern = cline.split ':', 2
|
328
|
-
@types[type].add_glob pattern
|
329
|
-
@globs[pattern] = @types[type] unless @globs.has_key? pattern
|
330
|
-
}
|
331
|
-
}
|
332
|
-
end
|
333
|
-
|
334
|
-
def load_magic(file)
|
335
|
-
open(file) { |f|
|
336
|
-
raise 'Bad magic file' if f.readline != "MIME-Magic\0\n"
|
337
|
-
|
338
|
-
f.gets =~ /^\[(\d\d):(.+)\]/
|
339
|
-
priority = $1.to_i
|
340
|
-
type = $2
|
341
|
-
buf =''
|
342
|
-
|
343
|
-
f.each { |line|
|
344
|
-
if line =~ /^\[(\d\d):(.+)\]/
|
345
|
-
@types[type].load_magic buf, priority
|
346
|
-
@magics << @types[type]
|
347
|
-
|
348
|
-
priority = $1.to_i
|
349
|
-
type = $2
|
350
|
-
buf = ''
|
351
|
-
else
|
352
|
-
buf << line
|
353
|
-
end
|
354
|
-
}
|
355
|
-
}
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
xdg_data_home = ENV['XDG_DATA_HOME'] || "#{ENV['HOME']}/.local/share"
|
360
|
-
xdg_data_dirs = ENV['XDG_DATA_DIRS'] || "/usr/local/share/:/usr/share"
|
361
|
-
|
362
|
-
@mime_dirs = (xdg_data_home + ':' + xdg_data_dirs).split(':').collect { |dir|
|
363
|
-
"#{dir}/mime"
|
364
|
-
}
|
365
|
-
|
366
|
-
@types = Hash.new {|h,k| h[k] = Type.new(k)}
|
367
|
-
@magics = []
|
368
|
-
@globs = {}
|
369
|
-
|
370
|
-
@mime_dirs.each {|dir|
|
371
|
-
glob_file = "#{dir}/globs"
|
372
|
-
load_globs glob_file if File.file? glob_file
|
373
|
-
|
374
|
-
magic_file = "#{dir}/magic"
|
375
|
-
load_magic magic_file if File.file? magic_file
|
376
|
-
}
|
377
|
-
end
|
1
|
+
# Copyright (c) 2006 Mael Clerambault <mael@clerambault.fr>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
require 'shared-mime-info/magic'
|
16
|
+
require 'shared-mime-info/type'
|
17
|
+
require 'shared-mime-info/version'
|
18
|
+
|
19
|
+
# This provides a way to guess the mime type of a file by doing both
|
20
|
+
# filename lookups and _magic_ file checks. This implementation tries to
|
21
|
+
# follow the version 0.13 of the
|
22
|
+
# specification[http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.13.html].
|
23
|
+
module MIME
|
24
|
+
class << self
|
25
|
+
attr_reader :mime_dirs # :nodoc:
|
26
|
+
|
27
|
+
# Returns the MIME::Type object corresponding to _type_.
|
28
|
+
def [](type)
|
29
|
+
@types.fetch type, nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Look for the type of a file by doing successive checks on
|
33
|
+
# the filename patterns.
|
34
|
+
#
|
35
|
+
# Returns a MIME::Type object or _nil_ if nothing matches.
|
36
|
+
def check_globs(filename)
|
37
|
+
basename = File.basename(filename)
|
38
|
+
found = @globs.each_key.select { |pattern| File.fnmatch pattern, basename }
|
39
|
+
|
40
|
+
if found.empty?
|
41
|
+
downcase_basename = basename.downcase
|
42
|
+
found = @globs.each_key.select { |pattern|
|
43
|
+
File.fnmatch pattern, downcase_basename
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
@globs[found.max]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Look for the type of a file by doing successive checks on
|
51
|
+
# _magic_ numbers.
|
52
|
+
#
|
53
|
+
# Returns a MIME::Type object or _nil_ if nothing matches.
|
54
|
+
def check_magics(file)
|
55
|
+
if file.respond_to? :read
|
56
|
+
check_magics_type(file, @magics)
|
57
|
+
else
|
58
|
+
open(file) {|f| check_magics_type(f, @magics) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Look for the type of a file by doing successive checks with
|
63
|
+
# the filename patterns or magic numbers. If none of the matches
|
64
|
+
# are successful, returns a type of <b>application/octet-stream</b> if
|
65
|
+
# the file contains control characters at its beginning, or <b>text/plain</b> otherwise.
|
66
|
+
#
|
67
|
+
# Returns a MIME::Type object.
|
68
|
+
def check(filename)
|
69
|
+
check_special(filename) ||
|
70
|
+
open(filename) { |f|
|
71
|
+
check_magics_gt80(f) ||
|
72
|
+
check_globs(filename) ||
|
73
|
+
check_magics_lt80(f) ||
|
74
|
+
check_default(f)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def check_magics_type(f, set); c = set.find {|m| m =~ f} and MIME[c.type] end
|
80
|
+
def check_magics_gt80(f); check_magics_type(f, @magics_gt80) end
|
81
|
+
def check_magics_lt80(f); check_magics_type(f, @magics_lt80) end
|
82
|
+
|
83
|
+
def check_special(filename)
|
84
|
+
case File.ftype(filename)
|
85
|
+
when 'directory' then @types['inode/directory']
|
86
|
+
when 'characterSpecial' then @types['inode/chardevice']
|
87
|
+
when 'blockSpecial' then @types['inode/blockdevice']
|
88
|
+
when 'fifo' then @types['inode/fifo']
|
89
|
+
when 'socket' then @types['inode/socket']
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_default(f)
|
96
|
+
f.pos = 0
|
97
|
+
firsts = f.read(32) || ''
|
98
|
+
bytes = firsts.unpack('C*')
|
99
|
+
if bytes.any? {|byte| byte < 32 && ![9, 10, 13].include?(byte) }
|
100
|
+
@types['application/octet-stream']
|
101
|
+
else
|
102
|
+
@types['text/plain']
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def load_globs(file)
|
107
|
+
open(file) { |f|
|
108
|
+
f.each { |line|
|
109
|
+
next if line =~ /^#/
|
110
|
+
cline = line.chomp
|
111
|
+
type, pattern = cline.split ':', 2
|
112
|
+
@types[type].glob_patterns << pattern
|
113
|
+
@globs[pattern] = @types[type] unless @globs.has_key? pattern
|
114
|
+
}
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def load_magic(file)
|
119
|
+
@magics.concat Magic.parse_magic(File.read(file))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
xdg_data_home = ENV['XDG_DATA_HOME'] || "#{ENV['HOME']}/.local/share"
|
124
|
+
xdg_data_dirs = ENV['XDG_DATA_DIRS'] || "/usr/local/share:/usr/share"
|
125
|
+
|
126
|
+
@mime_dirs = (xdg_data_home + ':' + xdg_data_dirs).split(':').collect { |dir|
|
127
|
+
"#{dir}/mime"
|
128
|
+
}
|
129
|
+
|
130
|
+
@types = Hash.new {|h,k| h[k] = Type.new(k)}
|
131
|
+
@magics = []
|
132
|
+
@globs = {}
|
133
|
+
|
134
|
+
@mime_dirs.each {|dir|
|
135
|
+
glob_file = "#{dir}/globs"
|
136
|
+
load_globs glob_file if File.file? glob_file
|
137
|
+
|
138
|
+
magic_file = "#{dir}/magic"
|
139
|
+
load_magic magic_file if File.file? magic_file
|
140
|
+
}
|
141
|
+
|
142
|
+
@magics.sort! {|a,b| b.priority <=> a.priority}
|
143
|
+
@magics.each {|m| @types[m.type].magics << m}
|
144
|
+
@magics_gt80, @magics_lt80 = @magics.partition {|m| m.priority >= 80}
|
145
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (c) 2006 Mael Clerambault <mael@clerambault.fr>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
require 'magics'
|
16
|
+
|
17
|
+
module MIME
|
18
|
+
module Magic # :nodoc: all
|
19
|
+
class BadMagic < StandardError; end
|
20
|
+
|
21
|
+
class Entry
|
22
|
+
attr_reader :indent
|
23
|
+
def initialize(indent, start_offset, value_length, value, mask, word_size, range_length)
|
24
|
+
@indent = indent
|
25
|
+
@start_offset = start_offset
|
26
|
+
@value_length = value_length
|
27
|
+
@value = value.freeze
|
28
|
+
@mask = mask.freeze
|
29
|
+
@word_size = word_size
|
30
|
+
@range_length = range_length
|
31
|
+
@sub_entries = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_subentry(entry)
|
35
|
+
if entry.indent == @indent + 1
|
36
|
+
@sub_entries << entry
|
37
|
+
elsif entry.indent > @indent + 1
|
38
|
+
if not @sub_entries.empty?
|
39
|
+
@sub_entries.last.add_subentry entry
|
40
|
+
else
|
41
|
+
raise BadMagic
|
42
|
+
end
|
43
|
+
else
|
44
|
+
raise BadMagic
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def =~(f)
|
49
|
+
check_file(f) and (@sub_entries.empty? || @sub_entries.any? {|e| e =~ f})
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def check_file(f)
|
54
|
+
f.pos = @start_offset
|
55
|
+
r = (f.read(@value_length + @range_length -1)|| '').unpack("c*")
|
56
|
+
range_length = 0
|
57
|
+
found = false
|
58
|
+
while not found and range_length < r.size
|
59
|
+
found = @value.zip(@mask, r[range_length, @value_length]).all? {|vb, mb, rb| (rb & mb) == (vb & mb) }
|
60
|
+
range_length = range_length + 1
|
61
|
+
end
|
62
|
+
found
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class RootEntry < Entry
|
67
|
+
attr_reader :priority, :type
|
68
|
+
def initialize(type, priority)
|
69
|
+
@indent = -1
|
70
|
+
@type = type
|
71
|
+
@priority = priority
|
72
|
+
@sub_entries = []
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def check_file(*args) true end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copyright (c) 2006 Mael Clerambault <mael@clerambault.fr>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
require 'rexml/document'
|
16
|
+
require 'mime/types'
|
17
|
+
|
18
|
+
module MIME
|
19
|
+
# Override the existing MIME::Type class
|
20
|
+
OriginalType = Type
|
21
|
+
MIME.send(:remove_const, :Type)
|
22
|
+
|
23
|
+
# Type represents a single mime type such as <b>text/html</b>.
|
24
|
+
class Type < OriginalType
|
25
|
+
attr_reader :magics, :glob_patterns
|
26
|
+
|
27
|
+
def initialize(content_type) # :nodoc:
|
28
|
+
@glob_patterns = []
|
29
|
+
@magics = []
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a Hash of the comments associated with a mime type in
|
34
|
+
# different languages.
|
35
|
+
#
|
36
|
+
# MIME['text/html'].comment.default
|
37
|
+
# => "HTML page"
|
38
|
+
#
|
39
|
+
# MIME['text/html'].comment['fr']
|
40
|
+
# => "page HTML"
|
41
|
+
def comment
|
42
|
+
file = ''
|
43
|
+
MIME.mime_dirs.each { |dir|
|
44
|
+
file = "#{dir}/#{content_type}.xml"
|
45
|
+
break if File.file? file
|
46
|
+
}
|
47
|
+
|
48
|
+
comments = {}
|
49
|
+
open(file) { |f|
|
50
|
+
doc = REXML::Document.new f
|
51
|
+
REXML::XPath.match(doc, '*/comment').each { |c|
|
52
|
+
if att = c.attributes['xml:lang']
|
53
|
+
comments[att] = c.text
|
54
|
+
else
|
55
|
+
comments.default = c.text
|
56
|
+
end
|
57
|
+
}
|
58
|
+
}
|
59
|
+
comments
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the types this type is a subclass of.
|
63
|
+
def parents
|
64
|
+
file = ''
|
65
|
+
MIME.mime_dirs.each { |dir|
|
66
|
+
file = "#{dir}/#{content_type}.xml"
|
67
|
+
break if File.file? file
|
68
|
+
}
|
69
|
+
|
70
|
+
open(file) { |f|
|
71
|
+
doc = REXML::Document.new f
|
72
|
+
REXML::XPath.match(doc, '*/sub-class-of').collect { |c|
|
73
|
+
MIME[c.attributes['type']]
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check if _filename_ is of this particular type by comparing it to
|
79
|
+
# some common extensions.
|
80
|
+
#
|
81
|
+
# MIME['text/html'].match_filename? 'index.html'
|
82
|
+
# => true
|
83
|
+
def matches_filename?(filename)
|
84
|
+
basename = File.basename(filename)
|
85
|
+
@glob_patterns.any? {|pattern| File.fnmatch pattern, basename.downcase}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Check if _file_ is of this particular type by looking for precise
|
89
|
+
# patterns (_magic_ numbers) in different locations of the file.
|
90
|
+
#
|
91
|
+
# _file_ must be an IO object opened with read permissions.
|
92
|
+
def matches_file?(f)
|
93
|
+
@magics.any? {|m| m =~ f }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
metadata
CHANGED
@@ -1,47 +1,53 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.11
|
3
|
-
specification_version: 1
|
1
|
+
--- !ruby/object:Gem::Specification
|
4
2
|
name: shared-mime-info
|
5
|
-
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date: 2006-09-24 00:00:00 +02:00
|
8
|
-
summary: Library to guess the MIME type of a file with both filename lookup and magic file detection
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: hanklords@gmail.com
|
12
|
-
homepage:
|
13
|
-
rubyforge_project:
|
14
|
-
description:
|
15
|
-
autorequire: rake
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.5
|
25
5
|
platform: ruby
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
-
|
34
|
-
|
35
|
-
|
36
|
-
rdoc_options: []
|
37
|
-
|
38
|
-
extra_rdoc_files: []
|
39
|
-
|
6
|
+
authors:
|
7
|
+
- Mael Clerambault
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: shared-mime-info is a pure Ruby library for accessing the MIME info database
|
14
|
+
provided by Freedesktop
|
15
|
+
email: mael@clerambault.fr
|
40
16
|
executables: []
|
41
|
-
|
42
17
|
extensions: []
|
43
|
-
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/magics.rb
|
21
|
+
- lib/shared-mime-info.rb
|
22
|
+
- lib/shared-mime-info/magic.rb
|
23
|
+
- lib/shared-mime-info/type.rb
|
24
|
+
- lib/shared-mime-info/version.rb
|
25
|
+
- Rakefile
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
homepage: http://shared-mime.rubyforge.org/
|
29
|
+
licenses:
|
30
|
+
- Public Domain
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
44
46
|
requirements: []
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.0.3
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: Library to guess the MIME type of a file with both filename lookup and magic
|
52
|
+
file detection
|
53
|
+
test_files: []
|
data/copying.txt
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2006 Hank Lords <hanklords@gmail.com>
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be included in all
|
12
|
-
copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/rakefile
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'rake/rdoctask'
|
2
|
-
require 'rake/packagetask'
|
3
|
-
require 'rake/gempackagetask'
|
4
|
-
|
5
|
-
require 'lib/shared-mime-info'
|
6
|
-
|
7
|
-
PKG_FILES = FileList["lib/*.rb", "rakefile", "copying.txt"].to_a
|
8
|
-
|
9
|
-
spec = Gem::Specification.new do |s|
|
10
|
-
s.summary = "Library to guess the MIME type of a file with both filename lookup and magic file detection"
|
11
|
-
s.name = "shared-mime-info"
|
12
|
-
s.author = "Hank Lords"
|
13
|
-
s.email = "hanklords@gmail.com"
|
14
|
-
s.version = MIME::VERSION
|
15
|
-
s.has_rdoc = true
|
16
|
-
s.require_path = 'lib'
|
17
|
-
s.autorequire = 'rake'
|
18
|
-
s.files = PKG_FILES
|
19
|
-
# s.description = ""
|
20
|
-
end
|
21
|
-
|
22
|
-
Rake::RDocTask.new do |rd|
|
23
|
-
rd.rdoc_files.include "lib/*.rb"
|
24
|
-
rd.options << "--inline-source"
|
25
|
-
rd.main = "MIME"
|
26
|
-
end
|
27
|
-
|
28
|
-
Rake::GemPackageTask.new spec do |p|
|
29
|
-
p.need_tar_gz = true
|
30
|
-
end
|