mime-types 3.3.1 → 3.7.0

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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mime/type/columnar'
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
@@ -18,21 +18,28 @@ module MIME::Types::Columnar
18
18
  obj.instance_variable_set(:@__files__, Set.new)
19
19
  end
20
20
 
21
+ def __fully_loaded? # :nodoc:
22
+ @__files__.size == 10
23
+ end
24
+
21
25
  # Load the first column data file (type and extensions).
22
- def load_base_data(path) #:nodoc:
26
+ def load_base_data(path) # :nodoc:
23
27
  @__root__ = path
24
28
 
25
- each_file_line('content_type', false) do |line|
29
+ each_file_line("content_type", false) do |line|
26
30
  line = line.split
27
31
  content_type = line.shift
28
32
  extensions = line
29
- # content_type, *extensions = line.split
30
33
 
31
34
  type = MIME::Type::Columnar.new(self, content_type, extensions)
32
35
  @__mime_data__ << type
33
36
  add(type)
34
37
  end
35
38
 
39
+ each_file_byte("spri") do |type, byte|
40
+ type.instance_variable_set(:@__sort_priority, byte)
41
+ end
42
+
36
43
  self
37
44
  end
38
45
 
@@ -45,11 +52,11 @@ module MIME::Types::Columnar
45
52
  i = -1
46
53
  column = File.join(@__root__, "mime.#{name}.column")
47
54
 
48
- IO.readlines(column, encoding: 'UTF-8').each do |line|
55
+ IO.readlines(column, encoding: "UTF-8").each do |line|
49
56
  line.chomp!
50
57
 
51
58
  if lookup
52
- type = @__mime_data__[i += 1] or next
59
+ (type = @__mime_data__[i += 1]) || next
53
60
  yield type, line
54
61
  else
55
62
  yield line
@@ -60,77 +67,118 @@ module MIME::Types::Columnar
60
67
  end
61
68
  end
62
69
 
70
+ def each_file_byte(name)
71
+ LOAD_MUTEX.synchronize do
72
+ next if @__files__.include?(name)
73
+
74
+ i = -1
75
+
76
+ filename = File.join(@__root__, "mime.#{name}.column")
77
+
78
+ next unless File.exist?(filename)
79
+
80
+ IO.binread(filename).unpack("C*").each do |byte|
81
+ (type = @__mime_data__[i += 1]) || next
82
+ yield type, byte
83
+ end
84
+
85
+ @__files__ << name
86
+ end
87
+ end
88
+
63
89
  def load_encoding
64
- each_file_line('encoding') do |type, line|
90
+ each_file_line("encoding") do |type, line|
65
91
  pool ||= {}
66
- type.instance_variable_set(:@encoding, (pool[line] ||= line))
92
+ type.instance_variable_set(:@encoding, pool[line] ||= line)
67
93
  end
68
94
  end
69
95
 
70
96
  def load_docs
71
- each_file_line('docs') do |type, line|
97
+ each_file_line("docs") do |type, line|
72
98
  type.instance_variable_set(:@docs, opt(line))
73
99
  end
74
100
  end
75
101
 
76
102
  def load_preferred_extension
77
- each_file_line('pext') do |type, line|
103
+ each_file_line("pext") do |type, line|
78
104
  type.instance_variable_set(:@preferred_extension, opt(line))
79
105
  end
80
106
  end
81
107
 
82
108
  def load_flags
83
- each_file_line('flags') do |type, line|
109
+ each_file_line("flags") do |type, line|
84
110
  line = line.split
85
111
  type.instance_variable_set(:@obsolete, flag(line.shift))
86
112
  type.instance_variable_set(:@registered, flag(line.shift))
87
113
  type.instance_variable_set(:@signature, flag(line.shift))
114
+ type.instance_variable_set(:@provisional, flag(line.shift))
88
115
  end
89
116
  end
90
117
 
91
118
  def load_xrefs
92
- each_file_line('xrefs') { |type, line|
93
- type.instance_variable_set(:@xrefs, dict(line, array: true))
119
+ each_file_line("xrefs") { |type, line|
120
+ type.instance_variable_set(:@xrefs, dict(line, transform: :array))
94
121
  }
95
122
  end
96
123
 
97
124
  def load_friendly
98
- each_file_line('friendly') { |type, line|
125
+ each_file_line("friendly") { |type, line|
99
126
  type.instance_variable_set(:@friendly, dict(line))
100
127
  }
101
128
  end
102
129
 
103
130
  def load_use_instead
104
- each_file_line('use_instead') do |type, line|
131
+ each_file_line("use_instead") do |type, line|
105
132
  type.instance_variable_set(:@use_instead, opt(line))
106
133
  end
107
134
  end
108
135
 
109
- def dict(line, array: false)
110
- if line == '-'
136
+ def dict(line, transform: nil)
137
+ if line == "-"
111
138
  {}
112
139
  else
113
- line.split('|').each_with_object({}) { |l, h|
114
- k, v = l.split('^')
140
+ line.split("|").each_with_object({}) { |l, h|
141
+ k, v = l.split("^")
115
142
  v = nil if v.empty?
116
- h[k] = array ? Array(v) : v
143
+
144
+ if transform
145
+ send(:"dict_#{transform}", h, k, v)
146
+ else
147
+ h[k] = v
148
+ end
117
149
  }
118
150
  end
119
151
  end
120
152
 
153
+ def dict_extension_priority(h, k, v)
154
+ return if v.nil?
155
+
156
+ v = v.to_i if v.is_a?(String)
157
+ v = v.trunc if v.is_a?(Float)
158
+ v = [[-20, v].max, 20].min
159
+
160
+ return if v.zero?
161
+
162
+ h[k] = v
163
+ end
164
+
165
+ def dict_array(h, k, v)
166
+ h[k] = Array(v)
167
+ end
168
+
121
169
  def arr(line)
122
- if line == '-'
170
+ if line == "-"
123
171
  []
124
172
  else
125
- line.split('|').flatten.compact.uniq
173
+ line.split("|").flatten.compact.uniq
126
174
  end
127
175
  end
128
176
 
129
177
  def opt(line)
130
- line unless line == '-'
178
+ line unless line == "-"
131
179
  end
132
180
 
133
181
  def flag(line)
134
- line == '1'
182
+ line == "1"
135
183
  end
136
184
  end
@@ -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['RUBY_MIME_TYPES_CACHE']
19
- return nil unless cache_file and File.exist?(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.error <<-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.error <<-WARNING.chomp.strip
32
+ Could not load MIME::Types cache: #{e}
33
33
  WARNING
34
34
  nil
35
35
  end
@@ -44,15 +44,11 @@ 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['RUBY_MIME_TYPES_CACHE']
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, 'wb') do |f|
53
- f.write(
54
- Marshal.dump(new(MIME::Types::Data::VERSION, Marshal.dump(types)))
55
- )
56
- end
52
+ File.binwrite(cache_file, Marshal.dump(new(MIME::Types::Data::VERSION, Marshal.dump(types))))
57
53
  end
58
54
  end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mime/types'
3
+ require "mime/types"
@@ -1,17 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require 'forwardable'
3
+ require "set"
5
4
 
6
5
  # MIME::Types requires a serializable keyed container that returns an empty Set
7
6
  # 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
7
+ # the Marshal format correctly, it will not survive any other serialization
9
8
  # format (plus, a default of a mutable object resuls in a shared mess).
10
9
  # 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
-
10
+ # Marshal serialization (and does not survive the round-trip).
11
+ class MIME::Types::Container # :nodoc:
15
12
  def initialize(hash = {})
16
13
  @container = {}
17
14
  merge!(hash)
@@ -37,7 +34,7 @@ class MIME::Types::Container #:nodoc:
37
34
 
38
35
  def merge!(other)
39
36
  tap {
40
- other = other.kind_of?(MIME::Types::Container) ? other.container : other
37
+ other = other.is_a?(MIME::Types::Container) ? other.container : other
41
38
  container.merge!(other)
42
39
  normalize
43
40
  }
@@ -47,16 +44,49 @@ class MIME::Types::Container #:nodoc:
47
44
  container
48
45
  end
49
46
 
50
- def_delegators :@container,
51
- :==,
52
- :count,
53
- :each,
54
- :each_value,
55
- :empty?,
56
- :flat_map,
57
- :keys,
58
- :select,
59
- :values
47
+ def ==(other)
48
+ container == other
49
+ end
50
+
51
+ def count(*args, &block)
52
+ if args.size == 0
53
+ container.count
54
+ elsif block
55
+ container.count(&block)
56
+ else
57
+ container.count(args.first)
58
+ end
59
+ end
60
+
61
+ def each_pair(&block)
62
+ container.each_pair(&block)
63
+ end
64
+
65
+ alias_method :each, :each_pair
66
+
67
+ def each_value(&block)
68
+ container.each_value(&block)
69
+ end
70
+
71
+ def empty?
72
+ container.empty?
73
+ end
74
+
75
+ def flat_map(&block)
76
+ container.flat_map(&block)
77
+ end
78
+
79
+ def keys
80
+ container.keys
81
+ end
82
+
83
+ def values
84
+ container.values
85
+ end
86
+
87
+ def select(&block)
88
+ container.select(&block)
89
+ end
60
90
 
61
91
  def add(key, value)
62
92
  (container[key] ||= Set.new).add(value)
@@ -85,7 +115,7 @@ class MIME::Types::Container #:nodoc:
85
115
 
86
116
  def normalize
87
117
  container.each do |k, v|
88
- next if v.kind_of?(Set)
118
+ next if v.is_a?(Set)
89
119
 
90
120
  container[k] = Set[*v]
91
121
  end
@@ -1,32 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mime/types/logger'
4
-
5
- # The namespace for MIME applications, tools, and libraries.
6
- module MIME
7
- ##
8
- class Types
9
- # Used to mark a method as deprecated in the mime-types interface.
10
- def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
11
- level = case klass
12
- when Class, Module
13
- '.'
14
- else
15
- klass = klass.class
16
- '#'
17
- end
18
- message = case message
19
- when :private, :protected
20
- "and will be #{message}"
21
- when nil
22
- 'and will be removed'
23
- else
24
- message
25
- end
26
- MIME::Types.logger.warn <<-WARNING.chomp
27
- #{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}.
28
- WARNING
29
- block.call if block
3
+ require "mime/types/logger"
4
+
5
+ class << MIME::Types
6
+ # Used to mark a method as deprecated in the mime-types interface.
7
+ def deprecated(options = {}, &block) # :nodoc:
8
+ message =
9
+ if options[:message]
10
+ options[:message]
11
+ else
12
+ klass = options.fetch(:class)
13
+
14
+ msep = case klass
15
+ when Class, Module
16
+ "."
17
+ else
18
+ klass = klass.class
19
+ "#"
20
+ end
21
+
22
+ method = "#{klass}#{msep}#{options.fetch(:method)}"
23
+ pre = " #{options[:pre]}" if options[:pre]
24
+ post = case options[:next]
25
+ when :private, :protected
26
+ " and will be made #{options[:next]}"
27
+ when :removed
28
+ " and will be removed"
29
+ when nil, ""
30
+ nil
31
+ else
32
+ " #{options[:next]}"
33
+ end
34
+
35
+ <<-WARNING.chomp.strip
36
+ #{caller(2..2).first}: #{klass}#{msep}#{method}#{pre} is deprecated#{post}.
37
+ WARNING
38
+ end
39
+
40
+ if !__deprecation_logged?(message, options[:once])
41
+ MIME::Types.logger.__send__(options[:level] || :debug, message)
30
42
  end
43
+
44
+ return unless block
45
+ block.call
46
+ end
47
+
48
+ private
49
+
50
+ def __deprecation_logged?(message, once)
51
+ return false unless once
52
+
53
+ @__deprecations_logged = {} unless defined?(@__deprecations_logged)
54
+ @__deprecations_logged.key?(message)
31
55
  end
32
56
  end
@@ -9,11 +9,11 @@ module MIME
9
9
  private
10
10
 
11
11
  def load_mode
12
- { columnar: false }
12
+ {columnar: false}
13
13
  end
14
14
  end
15
15
  end
16
16
  end
17
17
  end
18
18
 
19
- require 'mime/types'
19
+ require "mime/types"
@@ -1,20 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # -*- ruby encoding: utf-8 -*-
4
-
5
3
  ##
6
4
  module MIME; end
5
+
7
6
  ##
8
7
  class MIME::Types; end
9
8
 
10
- require 'mime/types/data'
9
+ require "mime/types/data"
11
10
 
12
11
  # This class is responsible for initializing the MIME::Types registry from
13
12
  # the data files supplied with the mime-types library.
14
13
  #
15
14
  # The Loader will use one of the following paths:
16
15
  # 1. The +path+ provided in its constructor argument;
17
- # 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
16
+ # 2. The value of ENV["RUBY_MIME_TYPES_DATA"]; or
18
17
  # 3. The value of MIME::Types::Data::PATH.
19
18
  #
20
19
  # When #load is called, the +path+ will be searched recursively for all YAML
@@ -30,7 +29,7 @@ class MIME::Types::Loader
30
29
  # Creates a Loader object that can be used to load MIME::Types registries
31
30
  # into memory, using YAML, JSON, or Columnar registry format loaders.
32
31
  def initialize(path = nil, container = nil)
33
- path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Data::PATH
32
+ path = path || ENV["RUBY_MIME_TYPES_DATA"] || MIME::Types::Data::PATH
34
33
  @container = container || MIME::Types.new
35
34
  @path = File.expand_path(path)
36
35
  end
@@ -68,7 +67,7 @@ class MIME::Types::Loader
68
67
  # Loads a MIME::Types registry from columnar files recursively found in
69
68
  # +path+.
70
69
  def load_columnar
71
- require 'mime/types/columnar' unless defined?(MIME::Types::Columnar)
70
+ require "mime/types/columnar" unless defined?(MIME::Types::Columnar)
72
71
  container.extend(MIME::Types::Columnar)
73
72
  container.load_base_data(path)
74
73
 
@@ -80,7 +79,7 @@ class MIME::Types::Loader
80
79
  #
81
80
  # This will load from columnar files (#load_columnar) if <tt>columnar:
82
81
  # true</tt> is provided in +options+ and there are columnar files in +path+.
83
- def load(options = { columnar: false })
82
+ def load(options = {columnar: true})
84
83
  if options[:columnar] && !Dir[columnar_path].empty?
85
84
  load_columnar
86
85
  else
@@ -90,7 +89,7 @@ class MIME::Types::Loader
90
89
 
91
90
  class << self
92
91
  # Loads the default MIME::Type registry.
93
- def load(options = { columnar: false })
92
+ def load(options = {columnar: false})
94
93
  new.load(options)
95
94
  end
96
95
 
@@ -105,12 +104,18 @@ class MIME::Types::Loader
105
104
  # NOTE: The purpose of this format is purely for maintenance reasons.
106
105
  def load_from_yaml(filename)
107
106
  begin
108
- require 'psych'
107
+ require "psych"
109
108
  rescue LoadError
110
109
  nil
111
110
  end
112
- require 'yaml'
113
- YAML.load(read_file(filename))
111
+
112
+ require "yaml"
113
+
114
+ if old_yaml?
115
+ YAML.safe_load(read_file(filename), [MIME::Type])
116
+ else
117
+ YAML.safe_load(read_file(filename), permitted_classes: [MIME::Type])
118
+ end
114
119
  end
115
120
 
116
121
  # Loads MIME::Types from a single JSON file.
@@ -119,28 +124,36 @@ class MIME::Types::Loader
119
124
  # The JSON format is the registry format for the MIME types registry
120
125
  # shipped with the mime-types library.
121
126
  def load_from_json(filename)
122
- require 'json'
127
+ require "json"
123
128
  JSON.parse(read_file(filename)).map { |type| MIME::Type.new(type) }
124
129
  end
125
130
 
126
131
  private
127
132
 
128
133
  def read_file(filename)
129
- File.open(filename, 'r:UTF-8:-', &:read)
134
+ File.open(filename, "r:UTF-8:-", &:read)
135
+ end
136
+
137
+ def old_yaml?
138
+ @old_yaml ||=
139
+ begin
140
+ require "rubygems/version"
141
+ Gem::Version.new(YAML::VERSION) < Gem::Version.new("3.1")
142
+ end
130
143
  end
131
144
  end
132
145
 
133
146
  private
134
147
 
135
148
  def yaml_path
136
- File.join(path, '*.y{,a}ml')
149
+ File.join(path, "*.y{,a}ml")
137
150
  end
138
151
 
139
152
  def json_path
140
- File.join(path, '*.json')
153
+ File.join(path, "*.json")
141
154
  end
142
155
 
143
156
  def columnar_path
144
- File.join(path, '*.column')
157
+ File.join(path, "*.column")
145
158
  end
146
159
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # -*- ruby encoding: utf-8 -*-
4
-
5
- require 'logger'
3
+ require "logger"
6
4
 
7
5
  ##
8
6
  module MIME
@@ -11,11 +9,22 @@ module MIME
11
9
  class << self
12
10
  # Configure the MIME::Types logger. This defaults to an instance of a
13
11
  # logger that passes messages (unformatted) through to Kernel#warn.
14
- attr_accessor :logger
12
+ # :attr_accessor: logger
13
+ attr_reader :logger
14
+
15
+ ##
16
+ def logger=(logger) # :nodoc
17
+ @logger =
18
+ if logger.nil?
19
+ NullLogger.new
20
+ else
21
+ logger
22
+ end
23
+ end
15
24
  end
16
25
 
17
- class WarnLogger < ::Logger #:nodoc:
18
- class WarnLogDevice < ::Logger::LogDevice #:nodoc:
26
+ class WarnLogger < ::Logger # :nodoc:
27
+ class WarnLogDevice < ::Logger::LogDevice # :nodoc:
19
28
  def initialize(*)
20
29
  end
21
30
 
@@ -27,13 +36,33 @@ module MIME
27
36
  end
28
37
  end
29
38
 
30
- def initialize(_one, _two = nil, _three = nil)
31
- super nil
39
+ def initialize(*)
40
+ super(nil)
32
41
  @logdev = WarnLogDevice.new
33
42
  @formatter = ->(_s, _d, _p, m) { m }
34
43
  end
35
44
  end
36
45
 
37
- self.logger = WarnLogger.new(nil)
46
+ class NullLogger < ::Logger
47
+ def initialize(*)
48
+ super(nil)
49
+ @logdev = nil
50
+ end
51
+
52
+ def reopen(_)
53
+ self
54
+ end
55
+
56
+ def <<(_)
57
+ end
58
+
59
+ def close
60
+ end
61
+
62
+ def add(_severity, _message = nil, _progname = nil)
63
+ end
64
+ end
65
+
66
+ self.logger = WarnLogger.new
38
67
  end
39
68
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "mime/types/deprecations"
4
+
3
5
  class << MIME::Types
4
6
  include Enumerable
5
7
 
@@ -33,7 +35,7 @@ class << MIME::Types
33
35
  def type_for(filename)
34
36
  __types__.type_for(filename)
35
37
  end
36
- alias of type_for
38
+ alias_method :of, :type_for
37
39
 
38
40
  # MIME::Types#add against the default MIME::Types registry.
39
41
  def add(*types)
@@ -43,22 +45,22 @@ class << MIME::Types
43
45
  private
44
46
 
45
47
  def lazy_load?
46
- return unless ENV.key?('RUBY_MIME_TYPES_LAZY_LOAD')
48
+ return unless ENV.key?("RUBY_MIME_TYPES_LAZY_LOAD")
47
49
 
48
- MIME::Types.logger.warn <<-WARNING.chomp
49
- Lazy loading ($RUBY_MIME_TYPES_LAZY_LOAD) is deprecated and will be removed.
50
- WARNING
50
+ deprecated(
51
+ message: "Lazy loading ($RUBY_MIME_TYPES_LAZY_LOAD) is deprecated and will be removed."
52
+ )
51
53
 
52
- (lazy = ENV['RUBY_MIME_TYPES_LAZY_LOAD']) && (lazy != 'false')
54
+ ENV["RUBY_MIME_TYPES_LAZY_LOAD"] != "false"
53
55
  end
54
56
 
55
57
  def __types__
56
- (defined?(@__types__) and @__types__) or load_default_mime_types
58
+ (defined?(@__types__) && @__types__) || load_default_mime_types
57
59
  end
58
60
 
59
61
  unless private_method_defined?(:load_mode)
60
62
  def load_mode
61
- { columnar: true }
63
+ {columnar: true}
62
64
  end
63
65
  end
64
66