mime-types 3.3.1 → 3.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Code-of-Conduct.md +10 -10
- data/Contributing.md +82 -93
- data/History.md +167 -138
- data/Licence.md +3 -3
- data/README.rdoc +1 -0
- data/Rakefile +131 -145
- data/lib/mime/type/columnar.rb +3 -3
- data/lib/mime/type.rb +141 -94
- data/lib/mime/types/_columnar.rb +20 -19
- data/lib/mime/types/cache.rb +8 -8
- data/lib/mime/types/columnar.rb +1 -1
- data/lib/mime/types/container.rb +14 -14
- data/lib/mime/types/deprecations.rb +15 -11
- data/lib/mime/types/full.rb +2 -2
- data/lib/mime/types/loader.rb +28 -15
- data/lib/mime/types/logger.rb +3 -5
- data/lib/mime/types/registry.rb +7 -7
- data/lib/mime/types.rb +18 -16
- data/lib/mime-types.rb +1 -1
- data/test/minitest_helper.rb +7 -9
- data/test/test_mime_type.rb +272 -261
- data/test/test_mime_types.rb +72 -72
- data/test/test_mime_types_cache.rb +38 -38
- data/test/test_mime_types_class.rb +59 -59
- data/test/test_mime_types_lazy.rb +16 -16
- data/test/test_mime_types_loader.rb +14 -14
- metadata +15 -43
data/lib/mime/type.rb
CHANGED
@@ -9,25 +9,61 @@ end
|
|
9
9
|
# == Usage
|
10
10
|
# require 'mime/types'
|
11
11
|
#
|
12
|
-
# plaintext = MIME::Types['text/plain']
|
13
|
-
# # returns [text/plain, text/plain]
|
12
|
+
# plaintext = MIME::Types['text/plain'] # => [ text/plain ]
|
14
13
|
# text = plaintext.first
|
15
|
-
#
|
16
|
-
#
|
14
|
+
# puts text.media_type # => 'text'
|
15
|
+
# puts text.sub_type # => 'plain'
|
17
16
|
#
|
18
|
-
# puts text.extensions.join(
|
17
|
+
# puts text.extensions.join(' ') # => 'txt asc c cc h hh cpp hpp dat hlp'
|
18
|
+
# puts text.preferred_extension # => 'txt'
|
19
|
+
# puts text.friendly # => 'Text Document'
|
20
|
+
# puts text.i18n_key # => 'text.plain'
|
19
21
|
#
|
20
|
-
# puts text.encoding # =>
|
22
|
+
# puts text.encoding # => quoted-printable
|
23
|
+
# puts text.default_encoding # => quoted-printable
|
21
24
|
# puts text.binary? # => false
|
22
25
|
# puts text.ascii? # => true
|
26
|
+
# puts text.obsolete? # => false
|
27
|
+
# puts text.registered? # => true
|
28
|
+
# puts text.provisional? # => false
|
29
|
+
# puts text.complete? # => true
|
30
|
+
#
|
31
|
+
# puts text # => 'text/plain'
|
32
|
+
#
|
23
33
|
# puts text == 'text/plain' # => true
|
24
|
-
# puts
|
34
|
+
# puts 'text/plain' == text # => true
|
35
|
+
# puts text == 'text/x-plain' # => false
|
36
|
+
# puts 'text/x-plain' == text # => false
|
37
|
+
#
|
38
|
+
# puts MIME::Type.simplified('x-appl/x-zip') # => 'x-appl/x-zip'
|
39
|
+
# puts MIME::Type.i18n_key('x-appl/x-zip') # => 'x-appl.x-zip'
|
40
|
+
#
|
41
|
+
# puts text.like?('text/x-plain') # => true
|
42
|
+
# puts text.like?(MIME::Type.new('x-text/x-plain')) # => true
|
43
|
+
#
|
44
|
+
# puts text.xrefs.inspect # => { "rfc" => [ "rfc2046", "rfc3676", "rfc5147" ] }
|
45
|
+
# puts text.xref_urls # => [ "http://www.iana.org/go/rfc2046",
|
46
|
+
# # "http://www.iana.org/go/rfc3676",
|
47
|
+
# # "http://www.iana.org/go/rfc5147" ]
|
48
|
+
#
|
49
|
+
# xtext = MIME::Type.new('x-text/x-plain')
|
50
|
+
# puts xtext.media_type # => 'text'
|
51
|
+
# puts xtext.raw_media_type # => 'x-text'
|
52
|
+
# puts xtext.sub_type # => 'plain'
|
53
|
+
# puts xtext.raw_sub_type # => 'x-plain'
|
54
|
+
# puts xtext.complete? # => false
|
55
|
+
#
|
56
|
+
# puts MIME::Types.any? { |type| type.content_type == 'text/plain' } # => true
|
57
|
+
# puts MIME::Types.all?(&:registered?) # => false
|
25
58
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# puts
|
30
|
-
#
|
59
|
+
# # Various string representations of MIME types
|
60
|
+
# qcelp = MIME::Types['audio/QCELP'].first # => audio/QCELP
|
61
|
+
# puts qcelp.content_type # => 'audio/QCELP'
|
62
|
+
# puts qcelp.simplified # => 'audio/qcelp'
|
63
|
+
#
|
64
|
+
# xwingz = MIME::Types['application/x-Wingz'].first # => application/x-Wingz
|
65
|
+
# puts xwingz.content_type # => 'application/x-Wingz'
|
66
|
+
# puts xwingz.simplified # => 'application/x-wingz'
|
31
67
|
class MIME::Type
|
32
68
|
# Reflects a MIME content-type specification that is not correctly
|
33
69
|
# formatted (it isn't +type+/+subtype+).
|
@@ -57,24 +93,24 @@ class MIME::Type
|
|
57
93
|
end
|
58
94
|
|
59
95
|
# The released version of the mime-types library.
|
60
|
-
VERSION =
|
96
|
+
VERSION = "3.4.1"
|
61
97
|
|
62
98
|
include Comparable
|
63
99
|
|
64
100
|
# :stopdoc:
|
65
101
|
# TODO verify mime-type character restrictions; I am pretty sure that this is
|
66
102
|
# too wide open.
|
67
|
-
MEDIA_TYPE_RE
|
68
|
-
I18N_RE
|
69
|
-
BINARY_ENCODINGS = %w
|
70
|
-
ASCII_ENCODINGS
|
103
|
+
MEDIA_TYPE_RE = %r{([-\w.+]+)/([-\w.+]*)}.freeze
|
104
|
+
I18N_RE = /[^[:alnum:]]/.freeze
|
105
|
+
BINARY_ENCODINGS = %w[base64 8bit].freeze
|
106
|
+
ASCII_ENCODINGS = %w[7bit quoted-printable].freeze
|
71
107
|
# :startdoc:
|
72
108
|
|
73
109
|
private_constant :MEDIA_TYPE_RE, :I18N_RE, :BINARY_ENCODINGS,
|
74
|
-
|
110
|
+
:ASCII_ENCODINGS
|
75
111
|
|
76
112
|
# Builds a MIME::Type object from the +content_type+, a MIME Content Type
|
77
|
-
# value (e.g., 'text/plain' or '
|
113
|
+
# value (e.g., 'text/plain' or 'application/x-eruby'). The constructed object
|
78
114
|
# is yielded to an optional block for additional configuration, such as
|
79
115
|
# associating extensions and encoding information.
|
80
116
|
#
|
@@ -86,9 +122,9 @@ class MIME::Type
|
|
86
122
|
# * Otherwise, the content_type will be used as a string.
|
87
123
|
#
|
88
124
|
# Yields the newly constructed +self+ object.
|
89
|
-
def initialize(content_type) # :yields self
|
125
|
+
def initialize(content_type) # :yields: self
|
90
126
|
@friendly = {}
|
91
|
-
@obsolete = @registered = false
|
127
|
+
@obsolete = @registered = @provisional = false
|
92
128
|
@preferred_extension = @docs = @use_instead = nil
|
93
129
|
self.extensions = []
|
94
130
|
|
@@ -113,11 +149,12 @@ class MIME::Type
|
|
113
149
|
# Indicates that a MIME type is like another type. This differs from
|
114
150
|
# <tt>==</tt> because <tt>x-</tt> prefixes are removed for this comparison.
|
115
151
|
def like?(other)
|
116
|
-
other =
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
152
|
+
other =
|
153
|
+
if other.respond_to?(:simplified)
|
154
|
+
MIME::Type.simplified(other.simplified, remove_x_prefix: true)
|
155
|
+
else
|
156
|
+
MIME::Type.simplified(other.to_s, remove_x_prefix: true)
|
157
|
+
end
|
121
158
|
MIME::Type.simplified(simplified, remove_x_prefix: true) == other
|
122
159
|
end
|
123
160
|
|
@@ -131,8 +168,8 @@ class MIME::Type
|
|
131
168
|
elsif other.respond_to?(:simplified)
|
132
169
|
simplified <=> other.simplified
|
133
170
|
else
|
134
|
-
filtered =
|
135
|
-
filtered ||=
|
171
|
+
filtered = "silent" if other == :silent
|
172
|
+
filtered ||= "true" if other == true
|
136
173
|
filtered ||= other.to_s
|
137
174
|
|
138
175
|
simplified <=> MIME::Type.simplified(filtered)
|
@@ -158,23 +195,24 @@ class MIME::Type
|
|
158
195
|
def priority_compare(other)
|
159
196
|
pc = simplified <=> other.simplified
|
160
197
|
if pc.zero? || !(extensions & other.extensions).empty?
|
161
|
-
pc =
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
198
|
+
pc =
|
199
|
+
if (reg = registered?) != other.registered?
|
200
|
+
reg ? -1 : 1 # registered < unregistered
|
201
|
+
elsif (comp = complete?) != other.complete?
|
202
|
+
comp ? -1 : 1 # complete < incomplete
|
203
|
+
elsif (obs = obsolete?) != other.obsolete?
|
204
|
+
obs ? 1 : -1 # current < obsolete
|
205
|
+
elsif obs && ((ui = use_instead) != (oui = other.use_instead))
|
206
|
+
if ui.nil?
|
207
|
+
1
|
208
|
+
elsif oui.nil?
|
209
|
+
-1
|
210
|
+
else
|
211
|
+
ui <=> oui
|
212
|
+
end
|
213
|
+
else
|
214
|
+
0
|
215
|
+
end
|
178
216
|
end
|
179
217
|
|
180
218
|
pc
|
@@ -183,7 +221,7 @@ class MIME::Type
|
|
183
221
|
# Returns +true+ if the +other+ object is a MIME::Type and the content types
|
184
222
|
# match.
|
185
223
|
def eql?(other)
|
186
|
-
other.
|
224
|
+
other.is_a?(MIME::Type) && (self == other)
|
187
225
|
end
|
188
226
|
|
189
227
|
# Returns the whole MIME content-type string.
|
@@ -197,8 +235,7 @@ class MIME::Type
|
|
197
235
|
# audio/QCELP => audio/QCELP
|
198
236
|
attr_reader :content_type
|
199
237
|
# A simplified form of the MIME content-type string, suitable for
|
200
|
-
# case-insensitive comparison, with
|
201
|
-
# removed and converted to lowercase.
|
238
|
+
# case-insensitive comparison, with the content_type converted to lowercase.
|
202
239
|
#
|
203
240
|
# text/plain => text/plain
|
204
241
|
# x-chemical/x-pdb => x-chemical/x-pdb
|
@@ -290,9 +327,9 @@ class MIME::Type
|
|
290
327
|
|
291
328
|
##
|
292
329
|
def encoding=(enc) # :nodoc:
|
293
|
-
if enc.nil?
|
330
|
+
if enc.nil? || (enc == :default)
|
294
331
|
@encoding = default_encoding
|
295
|
-
elsif BINARY_ENCODINGS.include?(enc)
|
332
|
+
elsif BINARY_ENCODINGS.include?(enc) || ASCII_ENCODINGS.include?(enc)
|
296
333
|
@encoding = enc
|
297
334
|
else
|
298
335
|
fail InvalidEncoding, enc
|
@@ -301,7 +338,7 @@ class MIME::Type
|
|
301
338
|
|
302
339
|
# Returns the default encoding for the MIME::Type based on the media type.
|
303
340
|
def default_encoding
|
304
|
-
@media_type ==
|
341
|
+
@media_type == "text" ? "quoted-printable" : "base64"
|
305
342
|
end
|
306
343
|
|
307
344
|
##
|
@@ -321,7 +358,7 @@ class MIME::Type
|
|
321
358
|
|
322
359
|
# Returns +true+ if the media type is obsolete.
|
323
360
|
attr_accessor :obsolete
|
324
|
-
|
361
|
+
alias_method :obsolete?, :obsolete
|
325
362
|
|
326
363
|
# The documentation for this MIME::Type.
|
327
364
|
attr_accessor :docs
|
@@ -331,7 +368,7 @@ class MIME::Type
|
|
331
368
|
# call-seq:
|
332
369
|
# text_plain.friendly # => "Text File"
|
333
370
|
# text_plain.friendly('en') # => "Text File"
|
334
|
-
def friendly(lang =
|
371
|
+
def friendly(lang = "en")
|
335
372
|
@friendly ||= {}
|
336
373
|
|
337
374
|
case lang
|
@@ -343,7 +380,7 @@ class MIME::Type
|
|
343
380
|
@friendly.update(lang)
|
344
381
|
else
|
345
382
|
fail ArgumentError,
|
346
|
-
|
383
|
+
"Expected a language or translation set, not #{lang.inspect}"
|
347
384
|
end
|
348
385
|
end
|
349
386
|
|
@@ -374,14 +411,22 @@ class MIME::Type
|
|
374
411
|
# The decoded cross-reference URL list for this MIME::Type.
|
375
412
|
def xref_urls
|
376
413
|
xrefs.flat_map { |type, values|
|
377
|
-
name = :"xref_url_for_#{type.tr(
|
378
|
-
respond_to?(name, true)
|
414
|
+
name = :"xref_url_for_#{type.tr("-", "_")}"
|
415
|
+
respond_to?(name, true) && xref_map(values, name) || values.to_a
|
379
416
|
}
|
380
417
|
end
|
381
418
|
|
382
419
|
# Indicates whether the MIME type has been registered with IANA.
|
383
420
|
attr_accessor :registered
|
384
|
-
|
421
|
+
alias_method :registered?, :registered
|
422
|
+
|
423
|
+
# Indicates whether the MIME type's registration with IANA is provisional.
|
424
|
+
attr_accessor :provisional
|
425
|
+
|
426
|
+
# Indicates whether the MIME type's registration with IANA is provisional.
|
427
|
+
def provisional?
|
428
|
+
registered? && @provisional
|
429
|
+
end
|
385
430
|
|
386
431
|
# MIME types can be specified to be sent across a network in particular
|
387
432
|
# formats. This method returns +true+ when the MIME::Type encoding is set
|
@@ -399,7 +444,7 @@ class MIME::Type
|
|
399
444
|
|
400
445
|
# Indicateswhether the MIME type is declared as a signature type.
|
401
446
|
attr_accessor :signature
|
402
|
-
|
447
|
+
alias_method :signature?, :signature
|
403
448
|
|
404
449
|
# Returns +true+ if the MIME::Type specifies an extension list,
|
405
450
|
# indicating that it is a complete MIME::Type.
|
@@ -422,7 +467,7 @@ class MIME::Type
|
|
422
467
|
|
423
468
|
# Converts the MIME::Type to a JSON string.
|
424
469
|
def to_json(*args)
|
425
|
-
require
|
470
|
+
require "json"
|
426
471
|
to_h.to_json(*args)
|
427
472
|
end
|
428
473
|
|
@@ -438,26 +483,27 @@ class MIME::Type
|
|
438
483
|
#
|
439
484
|
# This method should be considered a private implementation detail.
|
440
485
|
def encode_with(coder)
|
441
|
-
coder[
|
442
|
-
coder[
|
443
|
-
coder[
|
444
|
-
coder[
|
445
|
-
coder[
|
446
|
-
coder[
|
486
|
+
coder["content-type"] = @content_type
|
487
|
+
coder["docs"] = @docs unless @docs.nil? || @docs.empty?
|
488
|
+
coder["friendly"] = @friendly unless @friendly.nil? || @friendly.empty?
|
489
|
+
coder["encoding"] = @encoding
|
490
|
+
coder["extensions"] = @extensions.to_a unless @extensions.empty?
|
491
|
+
coder["preferred-extension"] = @preferred_extension if @preferred_extension
|
447
492
|
if obsolete?
|
448
|
-
coder[
|
449
|
-
coder[
|
493
|
+
coder["obsolete"] = obsolete?
|
494
|
+
coder["use-instead"] = use_instead if use_instead
|
450
495
|
end
|
451
496
|
unless xrefs.empty?
|
452
497
|
{}.tap do |hash|
|
453
498
|
xrefs.each do |k, v|
|
454
499
|
hash[k] = v.to_a.sort
|
455
500
|
end
|
456
|
-
coder[
|
501
|
+
coder["xrefs"] = hash
|
457
502
|
end
|
458
503
|
end
|
459
|
-
coder[
|
460
|
-
coder[
|
504
|
+
coder["registered"] = registered?
|
505
|
+
coder["provisional"] = provisional? if provisional?
|
506
|
+
coder["signature"] = signature? if signature?
|
461
507
|
coder
|
462
508
|
end
|
463
509
|
|
@@ -466,18 +512,19 @@ class MIME::Type
|
|
466
512
|
#
|
467
513
|
# This method should be considered a private implementation detail.
|
468
514
|
def init_with(coder)
|
469
|
-
self.content_type
|
470
|
-
self.docs
|
471
|
-
self.encoding
|
472
|
-
self.extensions
|
473
|
-
self.preferred_extension = coder[
|
474
|
-
self.obsolete
|
475
|
-
self.registered
|
476
|
-
self.
|
477
|
-
self.
|
478
|
-
self.
|
515
|
+
self.content_type = coder["content-type"]
|
516
|
+
self.docs = coder["docs"] || ""
|
517
|
+
self.encoding = coder["encoding"]
|
518
|
+
self.extensions = coder["extensions"] || []
|
519
|
+
self.preferred_extension = coder["preferred-extension"]
|
520
|
+
self.obsolete = coder["obsolete"] || false
|
521
|
+
self.registered = coder["registered"] || false
|
522
|
+
self.provisional = coder["provisional"] || false
|
523
|
+
self.signature = coder["signature"]
|
524
|
+
self.xrefs = coder["xrefs"] || {}
|
525
|
+
self.use_instead = coder["use-instead"]
|
479
526
|
|
480
|
-
friendly(coder[
|
527
|
+
friendly(coder["friendly"] || {})
|
481
528
|
end
|
482
529
|
|
483
530
|
def inspect # :nodoc:
|
@@ -501,8 +548,8 @@ class MIME::Type
|
|
501
548
|
# Converts a provided +content_type+ into a translation key suitable for
|
502
549
|
# use with the I18n library.
|
503
550
|
def i18n_key(content_type)
|
504
|
-
simplify_matchdata(match(content_type), joiner:
|
505
|
-
e.gsub!(I18N_RE,
|
551
|
+
simplify_matchdata(match(content_type), joiner: ".") { |e|
|
552
|
+
e.gsub!(I18N_RE, "-")
|
506
553
|
}
|
507
554
|
end
|
508
555
|
|
@@ -519,12 +566,12 @@ class MIME::Type
|
|
519
566
|
|
520
567
|
private
|
521
568
|
|
522
|
-
def simplify_matchdata(matchdata, remove_x = false, joiner:
|
569
|
+
def simplify_matchdata(matchdata, remove_x = false, joiner: "/")
|
523
570
|
return nil unless matchdata
|
524
571
|
|
525
572
|
matchdata.captures.map { |e|
|
526
573
|
e.downcase!
|
527
|
-
e.sub!(/^x-/,
|
574
|
+
e.sub!(/^x-/, "") if remove_x
|
528
575
|
yield e if block_given?
|
529
576
|
e
|
530
577
|
}.join(joiner)
|
@@ -537,11 +584,11 @@ class MIME::Type
|
|
537
584
|
match = MEDIA_TYPE_RE.match(type_string)
|
538
585
|
fail InvalidContentType, type_string if match.nil?
|
539
586
|
|
540
|
-
@content_type
|
587
|
+
@content_type = intern_string(type_string)
|
541
588
|
@raw_media_type, @raw_sub_type = match.captures
|
542
|
-
@simplified
|
543
|
-
@i18n_key
|
544
|
-
@media_type, @sub_type
|
589
|
+
@simplified = intern_string(MIME::Type.simplified(match))
|
590
|
+
@i18n_key = intern_string(MIME::Type.i18n_key(match))
|
591
|
+
@media_type, @sub_type = MEDIA_TYPE_RE.match(@simplified).captures
|
545
592
|
|
546
593
|
@raw_media_type = intern_string(@raw_media_type)
|
547
594
|
@raw_sub_type = intern_string(@raw_sub_type)
|
@@ -566,22 +613,22 @@ class MIME::Type
|
|
566
613
|
end
|
567
614
|
|
568
615
|
def xref_url_for_rfc(value)
|
569
|
-
|
616
|
+
"http://www.iana.org/go/%s" % value
|
570
617
|
end
|
571
618
|
|
572
619
|
def xref_url_for_draft(value)
|
573
|
-
|
620
|
+
"http://www.iana.org/go/%s" % value.sub(/\ARFC/, "draft")
|
574
621
|
end
|
575
622
|
|
576
623
|
def xref_url_for_rfc_errata(value)
|
577
|
-
|
624
|
+
"http://www.rfc-editor.org/errata_search.php?eid=%s" % value
|
578
625
|
end
|
579
626
|
|
580
627
|
def xref_url_for_person(value)
|
581
|
-
|
628
|
+
"http://www.iana.org/assignments/media-types/media-types.xhtml#%s" % value
|
582
629
|
end
|
583
630
|
|
584
631
|
def xref_url_for_template(value)
|
585
|
-
|
632
|
+
"http://www.iana.org/assignments/media-types/%s" % value
|
586
633
|
end
|
587
634
|
end
|
data/lib/mime/types/_columnar.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "mime/type/columnar"
|
4
4
|
|
5
5
|
# MIME::Types::Columnar is used to extend a MIME::Types container to load data
|
6
6
|
# by columns instead of from JSON or YAML. Column loads of MIME types loaded
|
@@ -19,10 +19,10 @@ module MIME::Types::Columnar
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Load the first column data file (type and extensions).
|
22
|
-
def load_base_data(path)
|
22
|
+
def load_base_data(path) # :nodoc:
|
23
23
|
@__root__ = path
|
24
24
|
|
25
|
-
each_file_line(
|
25
|
+
each_file_line("content_type", false) do |line|
|
26
26
|
line = line.split
|
27
27
|
content_type = line.shift
|
28
28
|
extensions = line
|
@@ -45,11 +45,11 @@ module MIME::Types::Columnar
|
|
45
45
|
i = -1
|
46
46
|
column = File.join(@__root__, "mime.#{name}.column")
|
47
47
|
|
48
|
-
IO.readlines(column, encoding:
|
48
|
+
IO.readlines(column, encoding: "UTF-8").each do |line|
|
49
49
|
line.chomp!
|
50
50
|
|
51
51
|
if lookup
|
52
|
-
type = @__mime_data__[i += 1]
|
52
|
+
(type = @__mime_data__[i += 1]) || next
|
53
53
|
yield type, line
|
54
54
|
else
|
55
55
|
yield line
|
@@ -61,57 +61,58 @@ module MIME::Types::Columnar
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def load_encoding
|
64
|
-
each_file_line(
|
64
|
+
each_file_line("encoding") do |type, line|
|
65
65
|
pool ||= {}
|
66
66
|
type.instance_variable_set(:@encoding, (pool[line] ||= line))
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def load_docs
|
71
|
-
each_file_line(
|
71
|
+
each_file_line("docs") do |type, line|
|
72
72
|
type.instance_variable_set(:@docs, opt(line))
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
def load_preferred_extension
|
77
|
-
each_file_line(
|
77
|
+
each_file_line("pext") do |type, line|
|
78
78
|
type.instance_variable_set(:@preferred_extension, opt(line))
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
82
|
def load_flags
|
83
|
-
each_file_line(
|
83
|
+
each_file_line("flags") do |type, line|
|
84
84
|
line = line.split
|
85
85
|
type.instance_variable_set(:@obsolete, flag(line.shift))
|
86
86
|
type.instance_variable_set(:@registered, flag(line.shift))
|
87
87
|
type.instance_variable_set(:@signature, flag(line.shift))
|
88
|
+
type.instance_variable_set(:@provisional, flag(line.shift))
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
91
92
|
def load_xrefs
|
92
|
-
each_file_line(
|
93
|
+
each_file_line("xrefs") { |type, line|
|
93
94
|
type.instance_variable_set(:@xrefs, dict(line, array: true))
|
94
95
|
}
|
95
96
|
end
|
96
97
|
|
97
98
|
def load_friendly
|
98
|
-
each_file_line(
|
99
|
+
each_file_line("friendly") { |type, line|
|
99
100
|
type.instance_variable_set(:@friendly, dict(line))
|
100
101
|
}
|
101
102
|
end
|
102
103
|
|
103
104
|
def load_use_instead
|
104
|
-
each_file_line(
|
105
|
+
each_file_line("use_instead") do |type, line|
|
105
106
|
type.instance_variable_set(:@use_instead, opt(line))
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
109
110
|
def dict(line, array: false)
|
110
|
-
if line ==
|
111
|
+
if line == "-"
|
111
112
|
{}
|
112
113
|
else
|
113
|
-
line.split(
|
114
|
-
k, v = l.split(
|
114
|
+
line.split("|").each_with_object({}) { |l, h|
|
115
|
+
k, v = l.split("^")
|
115
116
|
v = nil if v.empty?
|
116
117
|
h[k] = array ? Array(v) : v
|
117
118
|
}
|
@@ -119,18 +120,18 @@ module MIME::Types::Columnar
|
|
119
120
|
end
|
120
121
|
|
121
122
|
def arr(line)
|
122
|
-
if line ==
|
123
|
+
if line == "-"
|
123
124
|
[]
|
124
125
|
else
|
125
|
-
line.split(
|
126
|
+
line.split("|").flatten.compact.uniq
|
126
127
|
end
|
127
128
|
end
|
128
129
|
|
129
130
|
def opt(line)
|
130
|
-
line unless line ==
|
131
|
+
line unless line == "-"
|
131
132
|
end
|
132
133
|
|
133
134
|
def flag(line)
|
134
|
-
line ==
|
135
|
+
line == "1"
|
135
136
|
end
|
136
137
|
end
|
data/lib/mime/types/cache.rb
CHANGED
@@ -15,21 +15,21 @@ class << MIME::Types::Cache
|
|
15
15
|
# file does not exist, if the file cannot be loaded, or if the data in
|
16
16
|
# the cache version is different than this version.
|
17
17
|
def load(cache_file = nil)
|
18
|
-
cache_file ||= ENV[
|
19
|
-
return nil unless cache_file
|
18
|
+
cache_file ||= ENV["RUBY_MIME_TYPES_CACHE"]
|
19
|
+
return nil unless cache_file && File.exist?(cache_file)
|
20
20
|
|
21
21
|
cache = Marshal.load(File.binread(cache_file))
|
22
22
|
if cache.version == MIME::Types::Data::VERSION
|
23
23
|
Marshal.load(cache.data)
|
24
24
|
else
|
25
|
-
MIME::Types.logger.warn <<-WARNING.chomp
|
26
|
-
Could not load MIME::Types cache: invalid version
|
25
|
+
MIME::Types.logger.warn <<-WARNING.chomp.strip
|
26
|
+
Could not load MIME::Types cache: invalid version
|
27
27
|
WARNING
|
28
28
|
nil
|
29
29
|
end
|
30
30
|
rescue => e
|
31
|
-
MIME::Types.logger.warn <<-WARNING.chomp
|
32
|
-
Could not load MIME::Types cache: #{e}
|
31
|
+
MIME::Types.logger.warn <<-WARNING.chomp.strip
|
32
|
+
Could not load MIME::Types cache: #{e}
|
33
33
|
WARNING
|
34
34
|
nil
|
35
35
|
end
|
@@ -44,12 +44,12 @@ Could not load MIME::Types cache: #{e}
|
|
44
44
|
# +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
|
45
45
|
# directly or through the environment, this method will return +nil+
|
46
46
|
def save(types = nil, cache_file = nil)
|
47
|
-
cache_file ||= ENV[
|
47
|
+
cache_file ||= ENV["RUBY_MIME_TYPES_CACHE"]
|
48
48
|
return nil unless cache_file
|
49
49
|
|
50
50
|
types ||= MIME::Types.send(:__types__)
|
51
51
|
|
52
|
-
File.open(cache_file,
|
52
|
+
File.open(cache_file, "wb") do |f|
|
53
53
|
f.write(
|
54
54
|
Marshal.dump(new(MIME::Types::Data::VERSION, Marshal.dump(types)))
|
55
55
|
)
|
data/lib/mime/types/columnar.rb
CHANGED
data/lib/mime/types/container.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "set"
|
4
|
+
require "forwardable"
|
5
5
|
|
6
6
|
# MIME::Types requires a serializable keyed container that returns an empty Set
|
7
7
|
# on a key miss. Hash#default_value cannot be used because, while it traverses
|
@@ -9,7 +9,7 @@ require 'forwardable'
|
|
9
9
|
# format (plus, a default of a mutable object resuls in a shared mess).
|
10
10
|
# Hash#default_proc cannot be used without a wrapper because it prevents
|
11
11
|
# Marshal serialization (and doesn't survive the round-trip).
|
12
|
-
class MIME::Types::Container
|
12
|
+
class MIME::Types::Container # :nodoc:
|
13
13
|
extend Forwardable
|
14
14
|
|
15
15
|
def initialize(hash = {})
|
@@ -37,7 +37,7 @@ class MIME::Types::Container #:nodoc:
|
|
37
37
|
|
38
38
|
def merge!(other)
|
39
39
|
tap {
|
40
|
-
other = other.
|
40
|
+
other = other.is_a?(MIME::Types::Container) ? other.container : other
|
41
41
|
container.merge!(other)
|
42
42
|
normalize
|
43
43
|
}
|
@@ -48,15 +48,15 @@ class MIME::Types::Container #:nodoc:
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def_delegators :@container,
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
:==,
|
52
|
+
:count,
|
53
|
+
:each,
|
54
|
+
:each_value,
|
55
|
+
:empty?,
|
56
|
+
:flat_map,
|
57
|
+
:keys,
|
58
|
+
:select,
|
59
|
+
:values
|
60
60
|
|
61
61
|
def add(key, value)
|
62
62
|
(container[key] ||= Set.new).add(value)
|
@@ -85,7 +85,7 @@ class MIME::Types::Container #:nodoc:
|
|
85
85
|
|
86
86
|
def normalize
|
87
87
|
container.each do |k, v|
|
88
|
-
next if v.
|
88
|
+
next if v.is_a?(Set)
|
89
89
|
|
90
90
|
container[k] = Set[*v]
|
91
91
|
end
|