mime-types 2.99.3 → 3.4.1

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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/{Code-of-Conduct.rdoc → Code-of-Conduct.md} +29 -30
  3. data/Contributing.md +132 -0
  4. data/History.md +269 -0
  5. data/{Licence.rdoc → Licence.md} +4 -18
  6. data/Manifest.txt +8 -25
  7. data/README.rdoc +63 -73
  8. data/Rakefile +200 -97
  9. data/lib/mime/type/columnar.rb +30 -63
  10. data/lib/mime/type.rb +294 -458
  11. data/lib/mime/types/_columnar.rb +137 -0
  12. data/lib/mime/types/cache.rb +52 -74
  13. data/lib/mime/types/columnar.rb +2 -147
  14. data/lib/mime/types/container.rb +96 -0
  15. data/lib/mime/types/deprecations.rb +17 -34
  16. data/lib/mime/types/full.rb +19 -0
  17. data/lib/mime/types/loader.rb +36 -152
  18. data/lib/mime/types/logger.rb +7 -5
  19. data/lib/mime/types/registry.rb +90 -0
  20. data/lib/mime/types.rb +55 -148
  21. data/lib/mime-types.rb +2 -2
  22. data/test/minitest_helper.rb +8 -18
  23. data/test/test_mime_type.rb +489 -464
  24. data/test/test_mime_types.rb +139 -91
  25. data/test/test_mime_types_cache.rb +85 -57
  26. data/test/test_mime_types_class.rb +120 -100
  27. data/test/test_mime_types_lazy.rb +30 -28
  28. data/test/test_mime_types_loader.rb +18 -45
  29. metadata +92 -77
  30. data/Contributing.rdoc +0 -170
  31. data/History-Types.rdoc +0 -454
  32. data/History.rdoc +0 -590
  33. data/data/mime-types.json +0 -1
  34. data/data/mime.content_type.column +0 -1980
  35. data/data/mime.docs.column +0 -1980
  36. data/data/mime.encoding.column +0 -1980
  37. data/data/mime.friendly.column +0 -1980
  38. data/data/mime.obsolete.column +0 -1980
  39. data/data/mime.registered.column +0 -1980
  40. data/data/mime.signature.column +0 -1980
  41. data/data/mime.use_instead.column +0 -1980
  42. data/data/mime.xrefs.column +0 -1980
  43. data/docs/COPYING.txt +0 -339
  44. data/docs/artistic.txt +0 -127
  45. data/lib/mime/types/loader_path.rb +0 -15
  46. data/support/apache_mime_types.rb +0 -108
  47. data/support/benchmarks/load.rb +0 -64
  48. data/support/benchmarks/load_allocations.rb +0 -83
  49. data/support/benchmarks/object_counts.rb +0 -41
  50. data/support/convert/columnar.rb +0 -88
  51. data/support/convert.rb +0 -158
  52. data/support/iana_registry.rb +0 -172
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mime/type/columnar"
4
+
5
+ # MIME::Types::Columnar is used to extend a MIME::Types container to load data
6
+ # by columns instead of from JSON or YAML. Column loads of MIME types loaded
7
+ # through the columnar store are synchronized with a Mutex.
8
+ #
9
+ # MIME::Types::Columnar is not intended to be used directly, but will be added
10
+ # to an instance of MIME::Types when it is loaded with
11
+ # MIME::Types::Loader#load_columnar.
12
+ module MIME::Types::Columnar
13
+ LOAD_MUTEX = Mutex.new # :nodoc:
14
+
15
+ def self.extended(obj) # :nodoc:
16
+ super
17
+ obj.instance_variable_set(:@__mime_data__, [])
18
+ obj.instance_variable_set(:@__files__, Set.new)
19
+ end
20
+
21
+ # Load the first column data file (type and extensions).
22
+ def load_base_data(path) # :nodoc:
23
+ @__root__ = path
24
+
25
+ each_file_line("content_type", false) do |line|
26
+ line = line.split
27
+ content_type = line.shift
28
+ extensions = line
29
+ # content_type, *extensions = line.split
30
+
31
+ type = MIME::Type::Columnar.new(self, content_type, extensions)
32
+ @__mime_data__ << type
33
+ add(type)
34
+ end
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def each_file_line(name, lookup = true)
42
+ LOAD_MUTEX.synchronize do
43
+ next if @__files__.include?(name)
44
+
45
+ i = -1
46
+ column = File.join(@__root__, "mime.#{name}.column")
47
+
48
+ IO.readlines(column, encoding: "UTF-8").each do |line|
49
+ line.chomp!
50
+
51
+ if lookup
52
+ (type = @__mime_data__[i += 1]) || next
53
+ yield type, line
54
+ else
55
+ yield line
56
+ end
57
+ end
58
+
59
+ @__files__ << name
60
+ end
61
+ end
62
+
63
+ def load_encoding
64
+ each_file_line("encoding") do |type, line|
65
+ pool ||= {}
66
+ type.instance_variable_set(:@encoding, (pool[line] ||= line))
67
+ end
68
+ end
69
+
70
+ def load_docs
71
+ each_file_line("docs") do |type, line|
72
+ type.instance_variable_set(:@docs, opt(line))
73
+ end
74
+ end
75
+
76
+ def load_preferred_extension
77
+ each_file_line("pext") do |type, line|
78
+ type.instance_variable_set(:@preferred_extension, opt(line))
79
+ end
80
+ end
81
+
82
+ def load_flags
83
+ each_file_line("flags") do |type, line|
84
+ line = line.split
85
+ type.instance_variable_set(:@obsolete, flag(line.shift))
86
+ type.instance_variable_set(:@registered, flag(line.shift))
87
+ type.instance_variable_set(:@signature, flag(line.shift))
88
+ type.instance_variable_set(:@provisional, flag(line.shift))
89
+ end
90
+ end
91
+
92
+ def load_xrefs
93
+ each_file_line("xrefs") { |type, line|
94
+ type.instance_variable_set(:@xrefs, dict(line, array: true))
95
+ }
96
+ end
97
+
98
+ def load_friendly
99
+ each_file_line("friendly") { |type, line|
100
+ type.instance_variable_set(:@friendly, dict(line))
101
+ }
102
+ end
103
+
104
+ def load_use_instead
105
+ each_file_line("use_instead") do |type, line|
106
+ type.instance_variable_set(:@use_instead, opt(line))
107
+ end
108
+ end
109
+
110
+ def dict(line, array: false)
111
+ if line == "-"
112
+ {}
113
+ else
114
+ line.split("|").each_with_object({}) { |l, h|
115
+ k, v = l.split("^")
116
+ v = nil if v.empty?
117
+ h[k] = array ? Array(v) : v
118
+ }
119
+ end
120
+ end
121
+
122
+ def arr(line)
123
+ if line == "-"
124
+ []
125
+ else
126
+ line.split("|").flatten.compact.uniq
127
+ end
128
+ end
129
+
130
+ def opt(line)
131
+ line unless line == "-"
132
+ end
133
+
134
+ def flag(line)
135
+ line == "1"
136
+ end
137
+ end
@@ -1,80 +1,58 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- class MIME::Types
4
- Cache = Struct.new(:version, :data) # :nodoc:
5
-
6
- # Caching of MIME::Types registries is advisable if you will be loading
7
- # the default registry relatively frequently. With the class methods on
8
- # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly
9
- # and easily.
10
- #
11
- # The cache is invalidated on a per-version basis; a cache file for
12
- # version 2.0 will not be reused with version 2.0.1.
13
- class Cache
14
- class << self
15
- # Attempts to load the cache from the file provided as a parameter or in
16
- # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
17
- # file does not exist, if the file cannot be loaded, or if the data in
18
- # the cache version is different than this version.
19
- def load(cache_file = nil)
20
- cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
21
- return nil unless cache_file and File.exist?(cache_file)
22
-
23
- cache = Marshal.load(File.binread(cache_file))
24
- if cache.version == MIME::Types::VERSION
25
- Marshal.load(cache.data)
26
- else
27
- MIME::Types.logger.warn <<-warning.chomp
28
- Could not load MIME::Types cache: invalid version
29
- warning
30
- nil
31
- end
32
- rescue => e
33
- MIME::Types.logger.warn <<-warning.chomp
34
- Could not load MIME::Types cache: #{e}
35
- warning
36
- return nil
37
- end
38
-
39
- # Attempts to save the types provided to the cache file provided.
40
- #
41
- # If +types+ is not provided or is +nil+, the cache will contain the
42
- # current MIME::Types default registry.
43
- #
44
- # If +cache_file+ is not provided or is +nil+, the cache will be written
45
- # to the file specified in the environment variable
46
- # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
47
- # directly or through the environment, this method will return +nil+
48
- def save(types = nil, cache_file = nil)
49
- cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
50
- return nil unless cache_file
51
-
52
- types ||= MIME::Types.send(:__types__)
53
-
54
- File.open(cache_file, 'wb') do |f|
55
- f.write(Marshal.dump(new(types.data_version, Marshal.dump(types))))
56
- end
57
- end
1
+ # frozen_string_literal: true
2
+
3
+ MIME::Types::Cache = Struct.new(:version, :data) # :nodoc:
4
+
5
+ # Caching of MIME::Types registries is advisable if you will be loading
6
+ # the default registry relatively frequently. With the class methods on
7
+ # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly
8
+ # and easily.
9
+ #
10
+ # The cache is invalidated on a per-data-version basis; a cache file for
11
+ # version 3.2015.1118 will not be reused with version 3.2015.1201.
12
+ class << MIME::Types::Cache
13
+ # Attempts to load the cache from the file provided as a parameter or in
14
+ # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
15
+ # file does not exist, if the file cannot be loaded, or if the data in
16
+ # the cache version is different than this version.
17
+ def load(cache_file = nil)
18
+ cache_file ||= ENV["RUBY_MIME_TYPES_CACHE"]
19
+ return nil unless cache_file && File.exist?(cache_file)
20
+
21
+ cache = Marshal.load(File.binread(cache_file))
22
+ if cache.version == MIME::Types::Data::VERSION
23
+ Marshal.load(cache.data)
24
+ else
25
+ MIME::Types.logger.warn <<-WARNING.chomp.strip
26
+ Could not load MIME::Types cache: invalid version
27
+ WARNING
28
+ nil
58
29
  end
30
+ rescue => e
31
+ MIME::Types.logger.warn <<-WARNING.chomp.strip
32
+ Could not load MIME::Types cache: #{e}
33
+ WARNING
34
+ nil
59
35
  end
60
36
 
61
- # MIME::Types requires a container Hash with a default values for keys
62
- # resulting in an empty array (<tt>[]</tt>), but this cannot be dumped
63
- # through Marshal because of the presence of that default Proc. This class
64
- # exists solely to satisfy that need.
65
- class Container < Hash # :nodoc:
66
- def initialize
67
- super
68
- self.default_proc = ->(h, k) { h[k] = [] }
69
- end
70
-
71
- def marshal_dump
72
- {}.merge(self)
73
- end
74
-
75
- def marshal_load(hash)
76
- self.default_proc = ->(h, k) { h[k] = [] }
77
- self.merge!(hash)
37
+ # Attempts to save the types provided to the cache file provided.
38
+ #
39
+ # If +types+ is not provided or is +nil+, the cache will contain the
40
+ # current MIME::Types default registry.
41
+ #
42
+ # If +cache_file+ is not provided or is +nil+, the cache will be written
43
+ # to the file specified in the environment variable
44
+ # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
45
+ # directly or through the environment, this method will return +nil+
46
+ def save(types = nil, cache_file = nil)
47
+ cache_file ||= ENV["RUBY_MIME_TYPES_CACHE"]
48
+ return nil unless cache_file
49
+
50
+ types ||= MIME::Types.send(:__types__)
51
+
52
+ File.open(cache_file, "wb") do |f|
53
+ f.write(
54
+ Marshal.dump(new(MIME::Types::Data::VERSION, Marshal.dump(types)))
55
+ )
78
56
  end
79
57
  end
80
58
  end
@@ -1,148 +1,3 @@
1
- module MIME
2
- class Types
3
- end
4
- end
1
+ # frozen_string_literal: true
5
2
 
6
- require 'mime/type/columnar'
7
-
8
- # MIME::Types::Columnar is used to extend a MIME::Types container to load data
9
- # by columns instead of from JSON or YAML. Column loads of MIME types loaded
10
- # through the columnar store are synchronized with a Mutex.
11
- #
12
- # MIME::Types::Columnar is not intended to be used directly, but will be added
13
- # to an instance of MIME::Types when it is loaded with
14
- # MIME::Types::Loader#load_columnar.
15
- module MIME::Types::Columnar
16
- LOAD_MUTEX = Mutex.new # :nodoc:
17
-
18
- def self.extended(obj) # :nodoc:
19
- super
20
- obj.instance_variable_set(:@__mime_data__, [])
21
- obj.instance_variable_set(:@__attributes__, [])
22
- end
23
-
24
- # Load the first column data file (type and extensions).
25
- def load_base_data(path) #:nodoc:
26
- @__root__ = path
27
-
28
- each_file_line('content_type', false) do |line|
29
- content_type, *extensions = line.split
30
-
31
- type = MIME::Type::Columnar.new(self, content_type, extensions)
32
- @__mime_data__ << type
33
- add(type)
34
- end
35
-
36
- self
37
- end
38
-
39
- private
40
-
41
- def each_file_line(name, lookup = true)
42
- LOAD_MUTEX.synchronize do
43
- next if @__attributes__.include?(name)
44
-
45
- File.open(File.join(@__root__, "mime.#{name}.column"), 'r:UTF-8') do |f|
46
- i = -1
47
-
48
- f.each_line do |line|
49
- line.chomp!
50
-
51
- if lookup
52
- type = @__mime_data__[i += 1] or next
53
- yield type, line
54
- else
55
- yield line
56
- end
57
- end
58
- end
59
-
60
- @__attributes__ << name
61
- end
62
- end
63
-
64
- def load_encoding
65
- pool = {}
66
- each_file_line('encoding') do |type, line|
67
- line.freeze
68
- type.encoding = (pool[line] ||= line)
69
- end
70
- end
71
-
72
- def load_docs
73
- each_file_line('docs') do |type, line|
74
- type.docs = arr(line)
75
- end
76
- end
77
-
78
- def load_obsolete
79
- each_file_line('obsolete') do |type, line|
80
- type.obsolete = bool(line)
81
- end
82
- end
83
-
84
- def load_registered
85
- each_file_line('registered') do |type, line|
86
- type.registered = bool(line)
87
- end
88
- end
89
-
90
- def load_signature
91
- each_file_line('signature') do |type, line|
92
- type.signature = bool(line)
93
- end
94
- end
95
-
96
- def load_xrefs
97
- each_file_line('xrefs') { |type, line| type.xrefs = dict(line) }
98
- end
99
-
100
- def load_friendly
101
- each_file_line('friendly') { |type, line|
102
- v = dict(line)
103
- type.friendly = v.empty? ? nil : v
104
- }
105
- end
106
-
107
- def load_use_instead
108
- each_file_line('use_instead') do |type, line|
109
- type.use_instead = (line unless line == '-'.freeze)
110
- end
111
- end
112
-
113
- def dict(line)
114
- if line == '-'.freeze
115
- {}
116
- else
117
- line.split('|'.freeze).each_with_object({}) { |l, h|
118
- k, v = l.split('^'.freeze)
119
- v = [ nil ] if v.empty?
120
- h[k] = v
121
- }
122
- end
123
- end
124
-
125
- def arr(line)
126
- if line == '-'.freeze
127
- []
128
- else
129
- line.split('|'.freeze).flatten.compact.uniq
130
- end
131
- end
132
-
133
- def bool(line)
134
- line == '1'.freeze ? true : false
135
- end
136
- end
137
-
138
- unless MIME::Types.private_method_defined?(:load_mode)
139
- class << MIME::Types
140
- private
141
-
142
- def load_mode
143
- { columnar: true }
144
- end
145
- end
146
-
147
- require 'mime/types'
148
- end
3
+ require "mime/types"
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "forwardable"
5
+
6
+ # MIME::Types requires a serializable keyed container that returns an empty Set
7
+ # on a key miss. Hash#default_value cannot be used because, while it traverses
8
+ # the Marshal format correctly, it won't survive any other serialization
9
+ # format (plus, a default of a mutable object resuls in a shared mess).
10
+ # Hash#default_proc cannot be used without a wrapper because it prevents
11
+ # Marshal serialization (and doesn't survive the round-trip).
12
+ class MIME::Types::Container # :nodoc:
13
+ extend Forwardable
14
+
15
+ def initialize(hash = {})
16
+ @container = {}
17
+ merge!(hash)
18
+ end
19
+
20
+ def [](key)
21
+ container[key] || EMPTY_SET
22
+ end
23
+
24
+ def []=(key, value)
25
+ container[key] =
26
+ case value
27
+ when Set
28
+ value
29
+ else
30
+ Set[*value]
31
+ end
32
+ end
33
+
34
+ def merge(other)
35
+ self.class.new(other)
36
+ end
37
+
38
+ def merge!(other)
39
+ tap {
40
+ other = other.is_a?(MIME::Types::Container) ? other.container : other
41
+ container.merge!(other)
42
+ normalize
43
+ }
44
+ end
45
+
46
+ def to_hash
47
+ container
48
+ end
49
+
50
+ def_delegators :@container,
51
+ :==,
52
+ :count,
53
+ :each,
54
+ :each_value,
55
+ :empty?,
56
+ :flat_map,
57
+ :keys,
58
+ :select,
59
+ :values
60
+
61
+ def add(key, value)
62
+ (container[key] ||= Set.new).add(value)
63
+ end
64
+
65
+ def marshal_dump
66
+ {}.merge(container)
67
+ end
68
+
69
+ def marshal_load(hash)
70
+ @container = hash
71
+ end
72
+
73
+ def encode_with(coder)
74
+ container.each { |k, v| coder[k] = v.to_a }
75
+ end
76
+
77
+ def init_with(coder)
78
+ @container = {}
79
+ coder.map.each { |k, v| container[k] = Set[*v] }
80
+ end
81
+
82
+ protected
83
+
84
+ attr_accessor :container
85
+
86
+ def normalize
87
+ container.each do |k, v|
88
+ next if v.is_a?(Set)
89
+
90
+ container[k] = Set[*v]
91
+ end
92
+ end
93
+
94
+ EMPTY_SET = Set.new.freeze
95
+ private_constant :EMPTY_SET
96
+ end
@@ -1,53 +1,36 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
- require 'mime/types/logger'
3
+ require "mime/types/logger"
4
4
 
5
5
  # The namespace for MIME applications, tools, and libraries.
6
6
  module MIME
7
+ ##
7
8
  class Types
8
9
  # Used to mark a method as deprecated in the mime-types interface.
9
10
  def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
10
- level = case klass
11
+ level =
12
+ case klass
11
13
  when Class, Module
12
- '.'
14
+ "."
13
15
  else
14
16
  klass = klass.class
15
- '#'
16
- end
17
- message = case message
17
+ "#"
18
+ end
19
+ message =
20
+ case message
18
21
  when :private, :protected
19
22
  "and will be #{message}"
20
23
  when nil
21
- 'and will be removed'
24
+ "and will be removed"
22
25
  else
23
26
  message
24
- end
25
- MIME::Types.logger.warn <<-warning.chomp
26
- #{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}.
27
- warning
28
- block.call if block
29
- end
30
- end
31
-
32
- class << self
33
- # MIME::InvalidContentType was moved to MIME::Type::InvalidContentType.
34
- # Provide a single warning about this fact in the interim.
35
- def const_missing(name) # :nodoc:
36
- case name.to_s
37
- when 'InvalidContentType'
38
- warn_about_moved_constants(name)
39
- MIME::Type.const_get(name.to_sym)
40
- else
41
- super
42
- end
43
- end
44
-
45
- private
27
+ end
28
+ MIME::Types.logger.warn <<-WARNING.chomp.strip
29
+ #{caller(2..2).first}: #{klass}#{level}#{sym} is deprecated #{message}.
30
+ WARNING
46
31
 
47
- def warn_about_moved_constants(name)
48
- MIME::Types.logger.warn <<-warning.chomp
49
- #{caller[1]}: MIME::#{name} is deprecated. Use MIME::Type::#{name} instead.
50
- warning
32
+ return unless block
33
+ block.call
51
34
  end
52
35
  end
53
36
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ module MIME
5
+ ##
6
+ class Types
7
+ unless private_method_defined?(:load_mode)
8
+ class << self
9
+ private
10
+
11
+ def load_mode
12
+ {columnar: false}
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ require "mime/types"