mime-types 1.17.2 → 3.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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +35 -0
  3. data/.gitignore +17 -0
  4. data/.hoerc +20 -12
  5. data/Code-of-Conduct.rdoc +41 -0
  6. data/Contributing.rdoc +169 -0
  7. data/History.rdoc +531 -30
  8. data/Licence.rdoc +25 -0
  9. data/Manifest.txt +32 -34
  10. data/README.rdoc +198 -13
  11. data/Rakefile +181 -159
  12. data/lib/mime/type/columnar.rb +55 -0
  13. data/lib/mime/type.rb +566 -0
  14. data/lib/mime/types/cache.rb +56 -0
  15. data/lib/mime/types/columnar.rb +142 -0
  16. data/lib/mime/types/container.rb +30 -0
  17. data/lib/mime/types/deprecations.rb +32 -0
  18. data/lib/mime/types/full.rb +17 -0
  19. data/lib/mime/types/loader.rb +148 -0
  20. data/lib/mime/types/logger.rb +37 -0
  21. data/lib/mime/types/registry.rb +81 -0
  22. data/lib/mime/types.rb +199 -819
  23. data/lib/mime-types.rb +1 -0
  24. data/support/benchmarks/load.rb +65 -0
  25. data/support/benchmarks/load_allocations.rb +90 -0
  26. data/support/benchmarks/object_counts.rb +43 -0
  27. data/support/profile/columnar.rb +5 -0
  28. data/support/profile/columnar_full.rb +5 -0
  29. data/support/profile/full.rb +5 -0
  30. data/test/bad-fixtures/malformed +9 -0
  31. data/test/fixture/json.json +1 -0
  32. data/test/fixture/old-data +9 -0
  33. data/test/fixture/yaml.yaml +55 -0
  34. data/test/minitest_helper.rb +12 -0
  35. data/test/test_mime_type.rb +527 -242
  36. data/test/test_mime_types.rb +130 -68
  37. data/test/test_mime_types_cache.rb +100 -0
  38. data/test/test_mime_types_class.rb +155 -0
  39. data/test/test_mime_types_lazy.rb +43 -0
  40. data/test/test_mime_types_loader.rb +32 -0
  41. metadata +286 -229
  42. data/License.rdoc +0 -10
  43. data/lib/mime/types/application +0 -940
  44. data/lib/mime/types/application.mac +0 -2
  45. data/lib/mime/types/application.nonstandard +0 -114
  46. data/lib/mime/types/application.obsolete +0 -40
  47. data/lib/mime/types/audio +0 -131
  48. data/lib/mime/types/audio.nonstandard +0 -10
  49. data/lib/mime/types/audio.obsolete +0 -1
  50. data/lib/mime/types/image +0 -43
  51. data/lib/mime/types/image.nonstandard +0 -17
  52. data/lib/mime/types/image.obsolete +0 -5
  53. data/lib/mime/types/message +0 -19
  54. data/lib/mime/types/message.obsolete +0 -1
  55. data/lib/mime/types/model +0 -15
  56. data/lib/mime/types/multipart +0 -14
  57. data/lib/mime/types/multipart.nonstandard +0 -1
  58. data/lib/mime/types/multipart.obsolete +0 -7
  59. data/lib/mime/types/other.nonstandard +0 -8
  60. data/lib/mime/types/text +0 -54
  61. data/lib/mime/types/text.nonstandard +0 -5
  62. data/lib/mime/types/text.obsolete +0 -7
  63. data/lib/mime/types/text.vms +0 -1
  64. data/lib/mime/types/video +0 -68
  65. data/lib/mime/types/video.nonstandard +0 -11
  66. data/lib/mime/types/video.obsolete +0 -3
  67. data/mime-types.gemspec +0 -57
  68. data/type-lists/application.txt +0 -951
  69. data/type-lists/audio.txt +0 -132
  70. data/type-lists/image.txt +0 -43
  71. data/type-lists/message.txt +0 -20
  72. data/type-lists/model.txt +0 -15
  73. data/type-lists/multipart.txt +0 -14
  74. data/type-lists/text.txt +0 -57
  75. data/type-lists/video.txt +0 -67
@@ -0,0 +1,142 @@
1
+ module MIME
2
+ class Types
3
+ end
4
+ end
5
+
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(:@__files__, Set.new)
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
+ line = line.split
30
+ content_type = line.shift
31
+ extensions = line
32
+ # content_type, *extensions = line.split
33
+
34
+ type = MIME::Type::Columnar.new(self, content_type, extensions)
35
+ @__mime_data__ << type
36
+ add(type)
37
+ end
38
+
39
+ self
40
+ end
41
+
42
+ private
43
+
44
+ def each_file_line(name, lookup = true)
45
+ LOAD_MUTEX.synchronize do
46
+ next if @__files__.include?(name)
47
+
48
+ i = -1
49
+ column = File.join(@__root__, "mime.#{name}.column")
50
+
51
+ IO.readlines(column, encoding: 'UTF-8'.freeze).each do |line|
52
+ line.chomp!
53
+
54
+ if lookup
55
+ type = @__mime_data__[i += 1] or next
56
+ yield type, line
57
+ else
58
+ yield line
59
+ end
60
+ end
61
+
62
+ @__files__ << name
63
+ end
64
+ end
65
+
66
+ def load_encoding
67
+ each_file_line('encoding') do |type, line|
68
+ pool ||= {}
69
+ line.freeze
70
+ type.instance_variable_set(:@encoding, (pool[line] ||= line))
71
+ end
72
+ end
73
+
74
+ def load_docs
75
+ each_file_line('docs') do |type, line|
76
+ type.instance_variable_set(:@docs, opt(line))
77
+ end
78
+ end
79
+
80
+ def load_preferred_extension
81
+ each_file_line('pext') do |type, line|
82
+ type.instance_variable_set(:@preferred_extension, opt(line))
83
+ end
84
+ end
85
+
86
+ def load_flags
87
+ each_file_line('flags') do |type, line|
88
+ line = line.split
89
+ type.instance_variable_set(:@obsolete, flag(line.shift))
90
+ type.instance_variable_set(:@registered, flag(line.shift))
91
+ type.instance_variable_set(:@signature, flag(line.shift))
92
+ end
93
+ end
94
+
95
+ def load_xrefs
96
+ each_file_line('xrefs') { |type, line|
97
+ type.instance_variable_set(:@xrefs, dict(line, array: true))
98
+ }
99
+ end
100
+
101
+ def load_friendly
102
+ each_file_line('friendly') { |type, line|
103
+ type.instance_variable_set(:@friendly, dict(line))
104
+ }
105
+ end
106
+
107
+ def load_use_instead
108
+ each_file_line('use_instead') do |type, line|
109
+ type.instance_variable_set(:@use_instead, opt(line))
110
+ end
111
+ end
112
+
113
+ def dict(line, array: false)
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] = array ? Array(v) : 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 opt(line)
134
+ line unless line == '-'.freeze
135
+ end
136
+
137
+ def flag(line)
138
+ line == '1'.freeze ? true : false
139
+ end
140
+ end
141
+
142
+ require 'mime/types' unless defined?(MIME::Types::VERSION)
@@ -0,0 +1,30 @@
1
+ require 'set'
2
+
3
+ # MIME::Types requires a container Hash with a default values for keys
4
+ # resulting in an empty array (<tt>[]</tt>), but this cannot be dumped through
5
+ # Marshal because of the presence of that default Proc. This class exists
6
+ # solely to satisfy that need.
7
+ class MIME::Types::Container < Hash # :nodoc:
8
+ def initialize
9
+ super
10
+ self.default_proc = ->(h, k) { h[k] = Set.new }
11
+ end
12
+
13
+ def marshal_dump
14
+ {}.merge(self)
15
+ end
16
+
17
+ def marshal_load(hash)
18
+ self.default_proc = ->(h, k) { h[k] = Set.new }
19
+ merge!(hash)
20
+ end
21
+
22
+ def encode_with(coder)
23
+ each { |k, v| coder[k] = v.to_a }
24
+ end
25
+
26
+ def init_with(coder)
27
+ self.default_proc = ->(h, k) { h[k] = Set.new }
28
+ coder.map.each { |k, v| self[k] = Set[*v] }
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ # -*- ruby encoding: utf-8 -*-
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
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ ##
2
+ module MIME
3
+ ##
4
+ class Types
5
+ unless private_method_defined?(:load_mode)
6
+ class << self
7
+ private
8
+
9
+ def load_mode
10
+ { columnar: false }
11
+ end
12
+ end
13
+
14
+ require 'mime/types'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,148 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ ##
4
+ module MIME; end
5
+ ##
6
+ class MIME::Types; end
7
+
8
+ require 'mime/types/data'
9
+
10
+ # This class is responsible for initializing the MIME::Types registry from
11
+ # the data files supplied with the mime-types library.
12
+ #
13
+ # The Loader will use one of the following paths:
14
+ # 1. The +path+ provided in its constructor argument;
15
+ # 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
16
+ # 3. The value of MIME::Types::Data::PATH.
17
+ #
18
+ # When #load is called, the +path+ will be searched recursively for all YAML
19
+ # (.yml or .yaml) files. By convention, there is one file for each media
20
+ # type (application.yml, audio.yml, etc.), but this is not required.
21
+ class MIME::Types::Loader
22
+ # The path that will be read for the MIME::Types files.
23
+ attr_reader :path
24
+ # The MIME::Types container instance that will be loaded. If not provided
25
+ # at initialization, a new MIME::Types instance will be constructed.
26
+ attr_reader :container
27
+
28
+ # Creates a Loader object that can be used to load MIME::Types registries
29
+ # into memory, using YAML, JSON, or Columnar registry format loaders.
30
+ def initialize(path = nil, container = nil)
31
+ path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Data::PATH
32
+ @container = container || MIME::Types.new
33
+ @path = File.expand_path(path)
34
+ # begin
35
+ # require 'mime/lazy_types'
36
+ # @container.extend(MIME::LazyTypes)
37
+ # end
38
+ end
39
+
40
+ # Loads a MIME::Types registry from YAML files (<tt>*.yml</tt> or
41
+ # <tt>*.yaml</tt>) recursively found in +path+.
42
+ #
43
+ # It is expected that the YAML objects contained within the registry array
44
+ # will be tagged as <tt>!ruby/object:MIME::Type</tt>.
45
+ #
46
+ # Note that the YAML format is about 2½ times *slower* than the JSON format.
47
+ #
48
+ # NOTE: The purpose of this format is purely for maintenance reasons.
49
+ def load_yaml
50
+ Dir[yaml_path].sort.each do |f|
51
+ container.add(*self.class.load_from_yaml(f), :silent)
52
+ end
53
+ container
54
+ end
55
+
56
+ # Loads a MIME::Types registry from JSON files (<tt>*.json</tt>)
57
+ # recursively found in +path+.
58
+ #
59
+ # It is expected that the JSON objects will be an array of hash objects.
60
+ # The JSON format is the registry format for the MIME types registry
61
+ # shipped with the mime-types library.
62
+ def load_json
63
+ Dir[json_path].sort.each do |f|
64
+ types = self.class.load_from_json(f)
65
+ container.add(*types, :silent)
66
+ end
67
+ container
68
+ end
69
+
70
+ # Loads a MIME::Types registry from columnar files recursively found in
71
+ # +path+.
72
+ def load_columnar
73
+ require 'mime/types/columnar' unless defined?(MIME::Types::Columnar)
74
+ container.extend(MIME::Types::Columnar)
75
+ container.load_base_data(path)
76
+
77
+ container
78
+ end
79
+
80
+ # Loads a MIME::Types registry. Loads from JSON files by default
81
+ # (#load_json).
82
+ #
83
+ # This will load from columnar files (#load_columnar) if <tt>columnar:
84
+ # true</tt> is provided in +options+ and there are columnar files in +path+.
85
+ def load(options = { columnar: false })
86
+ if options[:columnar] && !Dir[columnar_path].empty?
87
+ load_columnar
88
+ else
89
+ load_json
90
+ end
91
+ end
92
+
93
+ class << self
94
+ # Loads the default MIME::Type registry.
95
+ def load(options = { columnar: false })
96
+ new.load(options)
97
+ end
98
+
99
+ # Loads MIME::Types from a single YAML file.
100
+ #
101
+ # It is expected that the YAML objects contained within the registry
102
+ # array will be tagged as <tt>!ruby/object:MIME::Type</tt>.
103
+ #
104
+ # Note that the YAML format is about 2½ times *slower* than the JSON
105
+ # format.
106
+ #
107
+ # NOTE: The purpose of this format is purely for maintenance reasons.
108
+ def load_from_yaml(filename)
109
+ begin
110
+ require 'psych'
111
+ rescue LoadError
112
+ nil
113
+ end
114
+ require 'yaml'
115
+ YAML.load(read_file(filename))
116
+ end
117
+
118
+ # Loads MIME::Types from a single JSON file.
119
+ #
120
+ # It is expected that the JSON objects will be an array of hash objects.
121
+ # The JSON format is the registry format for the MIME types registry
122
+ # shipped with the mime-types library.
123
+ def load_from_json(filename)
124
+ require 'json'
125
+ JSON.parse(read_file(filename)).map { |type| MIME::Type.new(type) }
126
+ end
127
+
128
+ private
129
+
130
+ def read_file(filename)
131
+ File.open(filename, 'r:UTF-8:-', &:read)
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def yaml_path
138
+ File.join(path, '*.y{,a}ml')
139
+ end
140
+
141
+ def json_path
142
+ File.join(path, '*.json')
143
+ end
144
+
145
+ def columnar_path
146
+ File.join(path, '*.column')
147
+ end
148
+ end
@@ -0,0 +1,37 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'logger'
4
+
5
+ ##
6
+ module MIME
7
+ ##
8
+ class Types
9
+ class << self
10
+ # Configure the MIME::Types logger. This defaults to an instance of a
11
+ # logger that passes messages (unformatted) through to Kernel#warn.
12
+ attr_accessor :logger
13
+ end
14
+
15
+ class WarnLogger < ::Logger #:nodoc:
16
+ class WarnLogDevice < ::Logger::LogDevice #:nodoc:
17
+ def initialize(*)
18
+ end
19
+
20
+ def write(m)
21
+ Kernel.warn(m)
22
+ end
23
+
24
+ def close
25
+ end
26
+ end
27
+
28
+ def initialize(_1, _2 = nil, _3 = nil)
29
+ super nil
30
+ @logdev = WarnLogDevice.new
31
+ @formatter = ->(_s, _d, _p, m) { m }
32
+ end
33
+ end
34
+
35
+ self.logger = WarnLogger.new(nil)
36
+ end
37
+ end
@@ -0,0 +1,81 @@
1
+ class << MIME::Types
2
+ include Enumerable
3
+
4
+ ##
5
+ def new(*) # :nodoc:
6
+ super.tap do |types|
7
+ __instances__.add types
8
+ end
9
+ end
10
+
11
+ # MIME::Types#[] against the default MIME::Types registry.
12
+ def [](type_id, complete: false, registered: false)
13
+ __types__[type_id, complete: complete, registered: registered]
14
+ end
15
+
16
+ # MIME::Types#count against the default MIME::Types registry.
17
+ def count
18
+ __types__.count
19
+ end
20
+
21
+ # MIME::Types#each against the default MIME::Types registry.
22
+ def each
23
+ if block_given?
24
+ __types__.each { |t| yield t }
25
+ else
26
+ enum_for(:each)
27
+ end
28
+ end
29
+
30
+ # MIME::Types#type_for against the default MIME::Types registry.
31
+ def type_for(filename)
32
+ __types__.type_for(filename)
33
+ end
34
+ alias_method :of, :type_for
35
+
36
+ # MIME::Types#add against the default MIME::Types registry.
37
+ def add(*types)
38
+ __types__.add(*types)
39
+ end
40
+
41
+ private
42
+
43
+ def lazy_load?
44
+ (lazy = ENV['RUBY_MIME_TYPES_LAZY_LOAD']) && (lazy != 'false')
45
+ end
46
+
47
+ def __types__
48
+ (defined?(@__types__) and @__types__) or load_default_mime_types
49
+ end
50
+
51
+ unless private_method_defined?(:load_mode)
52
+ def load_mode
53
+ { columnar: true }
54
+ end
55
+ end
56
+
57
+ def load_default_mime_types(mode = load_mode)
58
+ @__types__ = MIME::Types::Cache.load
59
+ unless @__types__
60
+ @__types__ = MIME::Types::Loader.load(mode)
61
+ MIME::Types::Cache.save(@__types__)
62
+ end
63
+ @__types__
64
+ end
65
+
66
+ def __instances__
67
+ @__instances__ ||= Set.new
68
+ end
69
+
70
+ def reindex_extensions(type)
71
+ __instances__.each do |instance|
72
+ instance.send(:reindex_extensions!, type)
73
+ end
74
+ true
75
+ end
76
+ end
77
+
78
+ ##
79
+ class MIME::Types
80
+ load_default_mime_types(load_mode) unless lazy_load?
81
+ end