diff options
author | Austin Ziegler <austin@zieglers.ca> | 2015-05-12 01:32:11 -0400 |
---|---|---|
committer | Austin Ziegler <austin@zieglers.ca> | 2015-05-25 10:22:53 -0400 |
commit | 98a75c089dd1eed71022644af0be3beb394d3052 (patch) | |
tree | fb248f4389cd2e1d03f6b2d5202b93f55e466909 /lib | |
parent | 31b101475128ef22043f454132f67197ecb5da82 (diff) | |
download | mime-types-98a75c089dd1eed71022644af0be3beb394d3052.tar.gz |
mime-types 2.6 release ready code.
- Extend documentation.
- Add a logger and logger configuration.
- Add more tests to Travis.
- Update MIME registry.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mime/type.rb | 311 | ||||
-rw-r--r-- | lib/mime/types.rb | 45 | ||||
-rw-r--r-- | lib/mime/types/cache.rb | 76 | ||||
-rw-r--r-- | lib/mime/types/columnar.rb | 19 | ||||
-rw-r--r-- | lib/mime/types/deprecations.rb | 76 | ||||
-rw-r--r-- | lib/mime/types/loader.rb | 16 | ||||
-rw-r--r-- | lib/mime/types/logger.rb | 35 |
7 files changed, 349 insertions, 229 deletions
diff --git a/lib/mime/type.rb b/lib/mime/type.rb index c49ffb9..29066a2 100644 --- a/lib/mime/type.rb +++ b/lib/mime/type.rb @@ -1,8 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'mime/types/deprecations' -require 'json' - # The definition of one MIME content-type. # # == Usage @@ -50,16 +47,17 @@ class MIME::Type end def to_s - "Invalid Encoding #{@encoding.inspect} (valid values: #{VALID_ENCODINGS.inspect})." + "Invalid Encoding #{@encoding.inspect}" end # :startdoc: end # The released version of the mime-types library. - VERSION = '2.5' + VERSION = '2.6' include Comparable + # :stopdoc: MEDIA_TYPE_RE = %r{([-\w.+]+)/([-\w.+]*)}o UNREGISTERED_RE = %r{[Xx]-}o I18N_RE = %r{[^[:alnum:]]}o @@ -70,20 +68,22 @@ class MIME::Type TEXT_ENCODINGS = %w(7bit quoted-printable) VALID_ENCODINGS = DEFAULT_ENCODINGS + BINARY_ENCODINGS + TEXT_ENCODINGS - IANA_URL = "http://www.iana.org/assignments/media-types/%s/%s" - RFC_URL = "http://rfc-editor.org/rfc/rfc%s.txt" - DRAFT_URL = "http://datatracker.ietf.org/public/idindex.cgi?command=id_details&filename=%s" - CONTACT_URL = "http://www.iana.org/assignments/contact-people.htm#%s" + IANA_URL = 'http://www.iana.org/assignments/media-types/%s/%s' + RFC_URL = 'http://rfc-editor.org/rfc/rfc%s.txt' + DRAFT_URL = 'http://datatracker.ietf.org/public/idindex.cgi?command=id_details&filename=%s' # rubocop:disable Metrics/LineLength + CONTACT_URL = 'http://www.iana.org/assignments/contact-people.htm#%s' + # :startdoc: if respond_to? :private_constant private_constant :MEDIA_TYPE_RE, :UNREGISTERED_RE, :I18N_RE, :PLATFORM_RE, - :DEFAULT_ENCODINGS, :BINARY_ENCODINGS, :TEXT_ENCODINGS, :VALID_ENCODINGS, - :IANA_URL, :RFC_URL, :DRAFT_URL, :CONTACT_URL + :DEFAULT_ENCODINGS, :BINARY_ENCODINGS, :TEXT_ENCODINGS, + :VALID_ENCODINGS, :IANA_URL, :RFC_URL, :DRAFT_URL, + :CONTACT_URL end - # Builds a MIME::Type object from the provided MIME Content Type value - # (e.g., 'text/plain' or 'applicaton/x-eruby'). The constructed object is - # yielded to an optional block for additional configuration, such as + # Builds a MIME::Type object from the +content_type+, a MIME Content Type + # value (e.g., 'text/plain' or 'applicaton/x-eruby'). The constructed object + # is yielded to an optional block for additional configuration, such as # associating extensions and encoding information. # # * When provided a Hash or a MIME::Type, the MIME::Type will be @@ -92,39 +92,41 @@ class MIME::Type # the first two elements of the array as the content type and # extensions. # * Otherwise, the content_type will be used as a string. + # + # Yields the newly constructed +self+ object. def initialize(content_type) # :yields self: - @friendly = {} - self.system = nil - self.obsolete = false - self.registered = nil + @friendly = {} + self.system = nil + self.obsolete = false + self.registered = nil self.use_instead = nil - self.signature = nil + self.signature = nil case content_type when Hash init_with(content_type) when Array self.content_type = content_type[0] - self.extensions = content_type[1] || [] + self.extensions = content_type[1] || [] when MIME::Type init_with(content_type.to_h) else self.content_type = content_type end - self.extensions ||= [] - self.docs ||= nil - self.encoding ||= :default + self.extensions ||= [] + self.docs ||= [] + self.encoding ||= :default # This value will be deprecated in the future, as it will be an # alternative view on #xrefs. Silence an unnecessary warning for now by # assigning directly to the instance variable. - @references ||= [] - self.xrefs ||= {} + @references ||= [] + self.xrefs ||= {} yield self if block_given? end - # Returns +true+ if the simplified type matches the current + # Returns +true+ if the +other+ simplified type matches the current type. def like?(other) if other.respond_to?(:simplified) @simplified == other.simplified @@ -133,10 +135,10 @@ class MIME::Type end end - # Compares the MIME::Type against the exact content type or the simplified - # type (the simplified type will be used if comparing against something - # that can be treated as a String with #to_s). In comparisons, this is - # done against the lowercase version of the MIME::Type. + # Compares the +other+ MIME::Type against the exact content type or the + # simplified type (the simplified type will be used if comparing against + # something that can be treated as a String with #to_s). In comparisons, this + # is done against the lowercase version of the MIME::Type. def <=>(other) if other.respond_to?(:content_type) @content_type.downcase <=> other.content_type.downcase @@ -145,7 +147,7 @@ class MIME::Type end end - # Compares the MIME::Type based on how reliable it is before doing a + # Compares the +other+ MIME::Type based on how reliable it is before doing a # normal <=> comparison. Used by MIME::Types#[] to sort types. The # comparisons involved are: # @@ -157,6 +159,11 @@ class MIME::Type # 4. Current definitions < obsolete definitions. # 5. Obselete with use-instead references < obsolete without. # 6. Obsolete use-instead definitions are compared. + # + # While this method is public, its use is strongly discouraged by consumers + # of mime-types. In mime-types 3, this method is likely to see substantial + # revision and simplification to ensure current registered content types sort + # before unregistered or obsolete content types. def priority_compare(other) pc = simplified <=> other.simplified if pc.zero? @@ -184,7 +191,7 @@ class MIME::Type pc end - # Returns +true+ if the other object is a MIME::Type and the content types + # Returns +true+ if the +other+ object is a MIME::Type and the content types # match. def eql?(other) other.kind_of?(MIME::Type) and self == other @@ -235,12 +242,14 @@ class MIME::Type attr_reader :extensions def extensions=(ext) # :nodoc: @extensions = Array(ext).flatten.compact.uniq + # TODO: In mime-types 3.x, we probably want to have a clue about the + # container(s) we belong to so we can trigger reindexing when this is done. end - # Merge the extensions provided into this MIME::Type. The extensions added + # Merge the +extensions+ provided into this MIME::Type. The extensions added # will be merged uniquely. - def add_extensions(*ext) - self.extensions = self.extensions + ext + def add_extensions(*extensions) + self.extensions = self.extensions + extensions end ## @@ -253,33 +262,39 @@ class MIME::Type extensions.first end - # The encoding (7bit, 8bit, quoted-printable, or base64) required to - # transport the data of this content type safely across a network, which - # roughly corresponds to Content-Transfer-Encoding. A value of +nil+ or - # <tt>:default</tt> will reset the #encoding to the #default_encoding for - # the MIME::Type. Raises ArgumentError if the encoding provided is - # invalid. + ## + # The encoding (+7bit+, +8bit+, <tt>quoted-printable</tt>, or +base64+) + # required to transport the data of this content type safely across a + # network, which roughly corresponds to Content-Transfer-Encoding. A value of + # +nil+ or <tt>:default</tt> will reset the #encoding to the + # #default_encoding for the MIME::Type. Raises ArgumentError if the encoding + # provided is invalid. # # If the encoding is not provided on construction, this will be either # 'quoted-printable' (for text/* media types) and 'base64' for eveything # else. + # + # :attr_accessor: encoding + + ## attr_reader :encoding def encoding=(enc) # :nodoc: if DEFAULT_ENCODINGS.include?(enc) - @encoding = self.default_encoding + @encoding = default_encoding elsif BINARY_ENCODINGS.include?(enc) or TEXT_ENCODINGS.include?(enc) @encoding = enc else - raise InvalidEncoding, enc + fail InvalidEncoding, enc end end # If the MIME::Type is a system-specific MIME::Type, returns the regular # expression for the operating system indicated. # - # This information about MIME content types is deprecated. + # This information about MIME content types is deprecated and will be removed + # in mime-types 3. def system - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) @system end @@ -287,7 +302,7 @@ class MIME::Type if os.nil? or os.kind_of?(Regexp) @system = os else - @system = %r|#{os}| + @system = %r{#{os}} end end @@ -300,11 +315,17 @@ class MIME::Type # Returns the media type or types that should be used instead of this # media type, if it is obsolete. If there is no replacement media type, or # it is not obsolete, +nil+ will be returned. + # + # :attr_accessor: use_instead + + ## def use_instead return nil unless obsolete? @use_instead end - attr_writer :use_instead # :nodoc: + + ## + attr_writer :use_instead # Returns +true+ if the media type is obsolete. def obsolete? @@ -323,7 +344,7 @@ class MIME::Type # call-seq: # text_plain.friendly # => "Text File" # text_plain.friendly('en') # => "Text File" - def friendly(lang = 'en') + def friendly(lang = 'en'.freeze) @friendly ||= {} case lang @@ -334,7 +355,7 @@ class MIME::Type when Hash @friendly.merge!(lang) else - raise ArgumentError + fail ArgumentError end end @@ -349,28 +370,59 @@ class MIME::Type # # from application/x-msword attr_reader :i18n_key + ## # The encoded references URL list for this MIME::Type. See #urls for more # information. # # This was previously called #url. - attr_reader :references + # + # #references has been deprecated and both versions (#references and #url) + # will be removed in mime-types 3. + # + # :attr_accessor: references + + ## + def references(__internal__ = false) + MIME::Types.deprecated(self, __method__) unless __internal__ + @references + end + + ## def references=(r) # :nodoc: - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) @references = Array(r).flatten.compact.uniq end - def url # :nodoc: - MIME.deprecated(self, __method__, "and has been renamed to #references") - references + ## + # The encoded references URL list for this MIME::Type. See #urls for more + # information. + # + # #urls has been deprecated and both versions (#references and #url) will be + # removed in mime-types 3. + # + # :attr_accessor: url + + ## + def url + MIME::Types.deprecated(self, __method__) + references(true) end + ## def url=(r) # :nodoc: - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) self.references = r end + ## # The cross-references list for this MIME::Type. + # + # :attr_accessor: xrefs + + ## attr_reader :xrefs + + ## def xrefs=(x) # :nodoc: @xrefs = MIME::Types::Container.new.merge(x) @xrefs.each_value(&:sort!) @@ -394,8 +446,11 @@ class MIME::Type # # These values will be accessible through #urls, which always returns an # array. + # + # This method is deprecated and will be removed in mime-types 3. def urls - references.map do |el| + MIME::Types.deprecated(self, __method__) + references(true).map do |el| case el when %r{^IANA$} IANA_URL % [ @media_type, @sub_type ] @@ -417,32 +472,33 @@ class MIME::Type # The decoded cross-reference URL list for this MIME::Type. def xref_urls - xrefs.map { |(type, values)| + xrefs.flat_map { |(type, values)| case type - when 'rfc' - values.map { |data| "http://www.iana.org/go/#{data}" } - when 'draft' + when 'rfc'.freeze + values.map { |data| 'http://www.iana.org/go/%s'.freeze % data } + when 'draft'.freeze values.map { |data| - "http://www.iana.org/go/#{data.sub(/\ARFC/, 'draft')}" + 'http://www.iana.org/go/%s'.freeze % data.sub(/\ARFC/, 'draft') } - when 'rfc-errata' + when 'rfc-errata'.freeze values.map { |data| - "http://www.rfc-editor.org/errata_search.php?eid=#{data}" + 'http://www.rfc-editor.org/errata_search.php?eid=%s'.freeze % data } - when 'person' + when 'person'.freeze values.map { |data| - "http://www.iana.org/assignments/media-types/media-types.xhtml##{data}" + 'http://www.iana.org/assignments/media-types/media-types.xhtml#%s'.freeze % data # rubocop:disable Metrics/LineLength } - when 'template' + when 'template'.freeze values.map { |data| - "http://www.iana.org/assignments/media-types/#{data}" + 'http://www.iana.org/assignments/media-types/%s'.freeze % data } else # 'uri', 'text', etc. values end - }.flatten + } end + ## # Prior to BCP 178 (RFC 6648), it could be assumed that MIME content types # that start with <tt>x-</tt> were unregistered MIME. Per this BCP, this # assumption is no longer being made by default in this library. @@ -453,6 +509,10 @@ class MIME::Type # - Unspecified, in which case the media-type and the content-type will be # scanned to see if they start with <tt>x-</tt>, indicating that they # are assumed unregistered. + # + # In mime-types 3, only a MIME content type that is explicitly registered + # will be used; there will be assumption that <tt>x-</tt> types are + # unregistered. def registered? if @registered.nil? (@raw_media_type !~ UNREGISTERED_RE) and @@ -477,11 +537,11 @@ class MIME::Type # formats. This method returns +false+ when the MIME::Type encoding is # set to <tt>base64</tt>. def ascii? - not binary? + !binary? end - # Returns +true+ when the simplified MIME::Type is in the list of known - # digital signatures. + # Returns +true+ when the simplified MIME::Type is one of the known digital + # signature types. def signature? !!@signature end @@ -492,25 +552,25 @@ class MIME::Type # Returns +true+ if the MIME::Type is specific to an operating system. # - # This method is deprecated. + # This method is deprecated and will be removed in mime-types 3. def system?(__internal__ = false) - MIME.deprecated(self, __method__) unless __internal__ - not @system.nil? + MIME::Types.deprecated(self, __method__) unless __internal__ + !@system.nil? end # Returns +true+ if the MIME::Type is specific to the current operating # system as represented by RUBY_PLATFORM. # - # This method is deprecated. + # This method is deprecated and will be removed in mime-types 3. def platform?(__internal__ = false) - MIME.deprecated(self, __method__) unless __internal__ + MIME::Types.deprecated(self, __method__) unless __internal__ system?(__internal__) and (RUBY_PLATFORM =~ @system) end # Returns +true+ if the MIME::Type specifies an extension list, # indicating that it is a complete MIME::Type. def complete? - not @extensions.empty? + !@extensions.empty? end # Returns the MIME::Type as a string. @@ -529,9 +589,9 @@ class MIME::Type # Returns the MIME::Type as an array suitable for use with # MIME::Type.from_array. # - # This method is deprecated. + # This method is deprecated and will be removed in mime-types 3. def to_a - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) [ @content_type, @extensions, @encoding, @system, obsolete?, @docs, @references, registered? ] end @@ -539,9 +599,9 @@ class MIME::Type # Returns the MIME::Type as an array suitable for use with # MIME::Type.from_hash. # - # This method is deprecated. + # This method is deprecated and will be removed in mime-types 3. def to_hash - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) { 'Content-Type' => @content_type, 'Content-Transfer-Encoding' => @encoding, 'Extensions' => @extensions, @@ -555,6 +615,7 @@ class MIME::Type # Converts the MIME::Type to a JSON string. def to_json(*args) + require 'json' to_h.to_json(*args) end @@ -567,6 +628,8 @@ class MIME::Type # Populates the +coder+ with attributes about this record for # serialization. The structure of +coder+ should match the structure used # with #init_with. + # + # This method should be considered a private implementation detail. def encode_with(coder) coder['content-type'] = @content_type coder['docs'] = @docs unless @docs.nil? or @docs.empty? @@ -577,7 +640,7 @@ class MIME::Type coder['obsolete'] = obsolete? coder['use-instead'] = use_instead if use_instead end - coder['references'] = references unless references.empty? + coder['references'] = references(true) unless references(true).empty? coder['xrefs'] = xrefs unless xrefs.empty? coder['registered'] = registered? coder['signature'] = signature? if signature? @@ -587,10 +650,12 @@ class MIME::Type # Initialize an empty object from +coder+, which must contain the # attributes necessary for initializing an empty object. + # + # This method should be considered a private implementation detail. def init_with(coder) self.content_type = coder['content-type'] self.docs = coder['docs'] || [] - self.friendly(coder['friendly'] || {}) + friendly(coder['friendly'] || {}) self.encoding = coder['encoding'] self.extensions = coder['extensions'] || [] self.obsolete = coder['obsolete'] @@ -604,14 +669,13 @@ class MIME::Type self.xrefs = coder['xrefs'] || {} self.use_instead = coder['use-instead'] end - # :startdoc: class << self # The MIME types main- and sub-label can both start with <tt>x-</tt>, # which indicates that it is a non-registered name. Of course, after - # registration this flag can disappear, adds to the confusing - # proliferation of MIME types. The simplified string has the <tt>x-</tt> - # removed and are translated to lowercase. + # registration this flag may disappear, adds to the confusing + # proliferation of MIME types. The simplified +content_type+ string has the + # <tt>x-</tt> removed and is translated to lowercase. def simplified(content_type) matchdata = case content_type when MatchData @@ -620,16 +684,16 @@ class MIME::Type MEDIA_TYPE_RE.match(content_type) end - if matchdata - matchdata.captures.map { |e| - e.downcase! - e.gsub!(UNREGISTERED_RE, ''.freeze) - e - }.join('/'.freeze) - end + return unless matchdata + + matchdata.captures.map { |e| + e.downcase! + e.gsub!(UNREGISTERED_RE, ''.freeze) + e + }.join('/'.freeze) end - # Converts a provided content type into a translation key suitable for + # Converts a provided +content_type+ into a translation key suitable for # use with the I18n library. def i18n_key(content_type) matchdata = case content_type @@ -639,23 +703,23 @@ class MIME::Type MEDIA_TYPE_RE.match(content_type) end - if matchdata - matchdata.captures.map { |e| - e.downcase! - e.gsub!(UNREGISTERED_RE, ''.freeze) - e.gsub!(I18N_RE, '-'.freeze) - e - }.join('.'.freeze) - end + return unless matchdata + + matchdata.captures.map { |e| + e.downcase! + e.gsub!(UNREGISTERED_RE, ''.freeze) + e.gsub!(I18N_RE, '-'.freeze) + e + }.join('.'.freeze) end - # Creates a MIME::Type from an array in the form of: - # [type-name, [extensions], encoding, system] + # Creates a MIME::Type from an +args+ array in the form of: + # [ type-name, [ extensions ], encoding, system ] # # +extensions+, +encoding+, and +system+ are optional. # - # MIME::Type.from_array("application/x-ruby", ['rb'], '8bit') - # MIME::Type.from_array(["application/x-ruby", ['rb'], '8bit']) + # MIME::Type.from_array('application/x-ruby', %w(rb), '8bit') + # MIME::Type.from_array([ 'application/x-ruby', [ 'rb' ], '8bit' ]) # # These are equivalent to: # @@ -664,15 +728,18 @@ class MIME::Type # t.encoding = '8bit' # end # - # This method is deprecated. - def from_array(*args) # :yields MIME::Type.new: - MIME.deprecated(self, __method__) + # It will yield the type (+t+) if a block is given. + # + # This method is deprecated and will be removed in mime-types 3. + def from_array(*args) # :yields t: + MIME::Types.deprecated(self, __method__) # Dereferences the array one level, if necessary. args = args.first if args.first.kind_of? Array unless args.size.between?(1, 8) - raise ArgumentError, "Array provided must contain between one and eight elements." + fail ArgumentError, + 'Array provided must contain between one and eight elements.' end MIME::Type.new(args.shift) do |t| @@ -682,7 +749,7 @@ class MIME::Type end end - # Creates a MIME::Type from a hash. Keys are case-insensitive, dashes + # Creates a MIME::Type from a +hash+. Keys are case-insensitive, dashes # may be replaced with underscores, and the internal Symbol of the # lowercase-underscore version can be used as well. That is, # Content-Type can be provided as content-type, Content_Type, @@ -705,9 +772,12 @@ class MIME::Type # t.extensions = ['yaml', 'yml'] # end # - # This method has been deprecated. - def from_hash(hash) # :yields MIME::Type.new: - MIME.deprecated(self, __method__) + # It will yield the constructed type +t+ if a block has been provided. + # + # + # This method is deprecated and will be removed in mime-types 3. + def from_hash(hash) # :yields t: + MIME::Types.deprecated(self, __method__) type = {} hash.each_pair do |k, v| type[k.to_s.tr('A-Z', 'a-z').gsub(/-/, '_').to_sym] = v @@ -726,7 +796,7 @@ class MIME::Type end end - # Essentially a copy constructor. + # Essentially a copy constructor for +mime_type+. # # MIME::Type.from_mime_type(plaintext) # @@ -738,17 +808,20 @@ class MIME::Type # t.encoding = plaintext.encoding.dup # end # - # This method has been deprecated. + # It will yield the type (+t+) if a block is given. + # + # This method is deprecated and will be removed in mime-types 3. def from_mime_type(mime_type) # :yields the new MIME::Type: - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) new(mime_type) end end private + def content_type=(type_string) match = MEDIA_TYPE_RE.match(type_string) - raise InvalidContentType, type_string if match.nil? + fail InvalidContentType, type_string if match.nil? @content_type = type_string @raw_media_type, @raw_sub_type = match.captures diff --git a/lib/mime/types.rb b/lib/mime/types.rb index e12d8cc..2f0f66b 100644 --- a/lib/mime/types.rb +++ b/lib/mime/types.rb @@ -1,5 +1,6 @@ # -*- ruby encoding: utf-8 -*- +require 'mime/types/deprecations' require 'mime/type' require 'mime/types/cache' require 'mime/types/loader' @@ -77,19 +78,19 @@ class MIME::Types # This method is deprecated and will be removed in mime-types 3.0. def add_type_variant(mime_type) # :nodoc: - MIME.deprecated(self, __method__, :private) + MIME::Types.deprecated(self, __method__, :private) add_type_variant!(mime_type) end # This method is deprecated and will be removed in mime-types 3.0. def index_extensions(mime_type) # :nodoc: - MIME.deprecated(self, __method__, :private) + MIME::Types.deprecated(self, __method__, :private) index_extensions!(mime_type) end # This method is deprecated and will be removed in mime-types 3.0. def defined_types # :nodoc: - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) @type_variants.values.flatten end @@ -140,7 +141,7 @@ class MIME::Types # platform) is currently supported but deprecated. def [](type_id, flags = {}) if flags[:platform] - MIME.deprecated(self, __method__, "using the :platform flag") + MIME::Types.deprecated(self, __method__, 'using the :platform flag') end matches = case type_id @@ -176,8 +177,7 @@ class MIME::Types }.compact.sort { |a, b| a.priority_compare(b) }.uniq if platform - MIME.deprecated(self, __method__, - "using the platform parameter") + MIME::Types.deprecated(self, __method__, 'using the platform parameter') types.select(&:platform?) else types @@ -208,17 +208,18 @@ class MIME::Types end end - # Add a single MIME::Type object to the set of known types. If the type is - # already known, a warning will be displayed. The +quiet+ parameter may be - # a truthy value to suppress that warning. - def add_type(mime_type, quiet = false) - if !quiet and @type_variants[mime_type.simplified].include?(mime_type) - warn('Type %s is already registered as a variant of %s.' % - [ mime_type, mime_type.simplified ]) + # Add a single MIME::Type object to the set of known types. If the +type+ is + # already known, a warning will be displayed. The +quiet+ parameter may be a + # truthy value to suppress that warning. + def add_type(type, quiet = false) + if !quiet and @type_variants[type.simplified].include?(type) + MIME::Types.logger.warn <<-warning +Type #{type} is already registered as a variant of #{type.simplified}. + warning end - add_type_variant!(mime_type) - index_extensions!(mime_type) + add_type_variant!(type) + index_extensions!(type) end class << self @@ -228,7 +229,7 @@ class MIME::Types # # This method has been deprecated and will be removed in mime-types 3.0. def load_from_file(filename) - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) MIME::Types::Loader.load_from_v1(filename) end @@ -266,7 +267,7 @@ class MIME::Types # # This method has been deprecated and will be removed in mime-types 3.0. def cache_file - MIME.deprecated(self, __method__) + MIME::Types.deprecated(self, __method__) ENV['RUBY_MIME_TYPES_CACHE'] end @@ -279,6 +280,7 @@ class MIME::Types end private + def lazy_load? (lazy = ENV['RUBY_MIME_TYPES_LAZY_LOAD']) && (lazy != 'false') end @@ -304,6 +306,7 @@ class MIME::Types end private + def add_type_variant!(mime_type) @type_variants[mime_type.simplified] << mime_type end @@ -313,14 +316,14 @@ class MIME::Types end def prune_matches(matches, flags) - matches.delete_if { |e| not e.complete? } if flags[:complete] - matches.delete_if { |e| not e.platform? } if flags[:platform] - matches.delete_if { |e| not e.registered? } if flags[:registered] + matches.delete_if { |e| !e.complete? } if flags[:complete] + matches.delete_if { |e| !e.platform? } if flags[:platform] + matches.delete_if { |e| !e.registered? } if flags[:registered] matches end def match(pattern) - @type_variants.select { |k, v| k =~ pattern }.values.flatten + @type_variants.select { |k, _| k =~ pattern }.values.flatten end load_default_mime_types(load_mode) unless lazy_load? diff --git a/lib/mime/types/cache.rb b/lib/mime/types/cache.rb index c2e8dce..027c71d 100644 --- a/lib/mime/types/cache.rb +++ b/lib/mime/types/cache.rb @@ -1,6 +1,8 @@ # -*- ruby encoding: utf-8 -*- class MIME::Types + Cache = Struct.new(:version, :data) # :nodoc: + # Caching of MIME::Types registries is advisable if you will be loading # the default registry relatively frequently. With the class methods on # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly @@ -8,46 +10,50 @@ class MIME::Types # # The cache is invalidated on a per-version basis; a cache file for # version 2.0 will not be reused with version 2.0.1. - Cache = Struct.new(:version, :data) - - class << Cache - # Attempts to load the cache from the file provided as a parameter or in - # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the - # file does not exist, if the file cannot be loaded, or if the data in - # the cache version is different than this version. - def load(cache_file = nil) - cache_file = cache_file || ENV['RUBY_MIME_TYPES_CACHE'] - return nil unless cache_file and File.exist?(cache_file) + class Cache + class << self + # Attempts to load the cache from the file provided as a parameter or in + # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the + # file does not exist, if the file cannot be loaded, or if the data in + # the cache version is different than this version. + def load(cache_file = nil) + cache_file ||= ENV['RUBY_MIME_TYPES_CACHE'] + return nil unless cache_file and File.exist?(cache_file) - cache = Marshal.load(File.binread(cache_file)) - if cache.version == MIME::Types::VERSION - Marshal.load(cache.data) - else - warn "Could not load MIME::Types cache: invalid version" - nil + cache = Marshal.load(File.binread(cache_file)) + if cache.version == MIME::Types::VERSION + Marshal.load(cache.data) + else + MIME::Types.logger.warn <<-warning.chomp +Could not load MIME::Types cache: invalid version + warning + nil + end + rescue => e + MIME::Types.logger.warn <<-warning.chomp +Could not load MIME::Types cache: #{e} + warning + return nil end - rescue => e - warn "Could not load MIME::Types cache: #{e}" - return nil - end - # Attempts to save the types provided to the cache file provided. - # - # If +types+ is not provided or is +nil+, the cache will contain the - # current MIME::Types default registry. - # - # If +cache_file+ is not provided or is +nil+, the cache will be written - # to the file specified in the environment variable - # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either - # directly or through the environment, this method will return +nil+ - def save(types = nil, cache_file = nil) - cache_file = cache_file || ENV['RUBY_MIME_TYPES_CACHE'] - return nil unless cache_file + # Attempts to save the types provided to the cache file provided. + # + # If +types+ is not provided or is +nil+, the cache will contain the + # current MIME::Types default registry. + # + # If +cache_file+ is not provided or is +nil+, the cache will be written + # to the file specified in the environment variable + # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either + # directly or through the environment, this method will return +nil+ + def save(types = nil, cache_file = nil) + cache_file ||= ENV['RUBY_MIME_TYPES_CACHE'] + return nil unless cache_file - types = types || MIME::Types.send(:__types__) + types ||= MIME::Types.send(:__types__) - File.open(cache_file, 'wb') do |f| - f.write(Marshal.dump(new(types.data_version, Marshal.dump(types)))) + File.open(cache_file, 'wb') do |f| + f.write(Marshal.dump(new(types.data_version, Marshal.dump(types)))) + end end end end diff --git a/lib/mime/types/columnar.rb b/lib/mime/types/columnar.rb index 7b63651..594a727 100644 --- a/lib/mime/types/columnar.rb +++ b/lib/mime/types/columnar.rb @@ -13,9 +13,9 @@ require 'mime/type/columnar' # to an instance of MIME::Types when it is loaded with # MIME::Types::Loader#load_columnar. module MIME::Types::Columnar - LOAD_MUTEX = Mutex.new + LOAD_MUTEX = Mutex.new # :nodoc: - def self.extended(obj) + def self.extended(obj) # :nodoc: super obj.instance_variable_set(:@__mime_data__, []) obj.instance_variable_set(:@__attributes__, []) @@ -49,7 +49,7 @@ module MIME::Types::Columnar line.chomp! if lookup - next unless type = @__mime_data__[i += 1] + type = @__mime_data__[i += 1] or next yield type, line else yield line @@ -117,26 +117,19 @@ module MIME::Types::Columnar end def load_use_instead - empty = '-' - pipe = '|' each_file_line('use_instead') do |type, line| type.use_instad = (line unless line == '-'.freeze) end end def dict(line) - empty = '-'.freeze - pipe = '|'.freeze - caret = '^'.freeze - - if line == empty + if line == '-'.freeze {} else - line.split(pipe).inject({}) { |h, l| - k, v = line.split(caret) + line.split('|'.freeze).each_with_object({}) { |h, l| + k, v = l.split('^'.freeze) v = [ nil ] if v.empty? h[k] = v - h } end end diff --git a/lib/mime/types/deprecations.rb b/lib/mime/types/deprecations.rb index 8696894..2535d34 100644 --- a/lib/mime/types/deprecations.rb +++ b/lib/mime/types/deprecations.rb @@ -1,45 +1,53 @@ # -*- ruby encoding: utf-8 -*- -# The namespace for MIME applications, tools, and libraries. -module MIME # :nodoc: -end +require 'mime/types/logger' -class << MIME - # Used to mark a method as deprecated in the mime-types interface. - def deprecated(klass, sym, message = nil, &block) # :nodoc: - level = case klass - when Class, Module - '.' - else - klass = klass.class - '#' - end - message = case message - when :private, :protected - "and will be #{message}" - when nil - "and will be removed" +# The namespace for MIME applications, tools, and libraries. +module MIME + class Types + # Used to mark a method as deprecated in the mime-types interface. + def self.deprecated(klass, sym, message = nil, &block) # :nodoc: + level = case klass + when Class, Module + '.' else - message + klass = klass.class + '#' end - warn "#{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}." - block.call if block + message = case message + when :private, :protected + "and will be #{message}" + when nil + 'and will be removed' + else + message + end + MIME::Types.logger.warn <<-warning.chomp +#{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}. + warning + block.call if block + end end - # MIME::InvalidContentType was moved to MIME::Type::InvalidContentType. - # Provide a single warning about this fact in the interim. - def const_missing(name) # :nodoc: - case name.to_s - when "InvalidContentType" - warn_about_moved_constants(name) - MIME::Type.const_get(name.to_sym) - else - super + class << self + # MIME::InvalidContentType was moved to MIME::Type::InvalidContentType. + # Provide a single warning about this fact in the interim. + def const_missing(name) # :nodoc: + case name.to_s + when 'InvalidContentType' + warn_about_moved_constants(name) + MIME::Type.const_get(name.to_sym) + else + super + end end - end - private - def warn_about_moved_constants(name) # :nodoc: - warn "#{caller[1]}: MIME::#{name} is deprecated. Use MIME::Type::#{name} instead." + private + + def warn_about_moved_constants(name) + MIME::Types.logger.warn <<-warning.chomp +#{caller[1]}: MIME::#{name} is deprecated. Use MIME::Type::#{name} instead. + warning + end end end diff --git a/lib/mime/types/loader.rb b/lib/mime/types/loader.rb index 7833a2a..87433d0 100644 --- a/lib/mime/types/loader.rb +++ b/lib/mime/types/loader.rb @@ -95,9 +95,9 @@ class MIME::Types::Loader # # This method has been deprecated and will be removed from mime-types 3.0. def load_v1 - MIME.deprecated(self.class, __method__) + MIME::Types.deprecated(self.class, __method__) Dir[v1_path].sort.each do |f| - next if f =~ /\.ya?ml$|\.json$/ + next if f =~ /\.(?:ya?ml|json|column)$/ container.add(self.class.load_from_v1(f, true), true) end container @@ -152,7 +152,7 @@ class MIME::Types::Loader # # This method has been deprecated and will be removed in mime-types 3.0. def load_from_v1(filename, __internal__ = false) - MIME.deprecated(self.class, __method__) unless __internal__ + MIME::Types.deprecated(self.class, __method__) unless __internal__ data = read_file(filename).split($/) mime = MIME::Types.new data.each_with_index { |line, index| @@ -162,11 +162,11 @@ class MIME::Types::Loader m = V1_FORMAT.match(item) unless m - warn <<-EOS + MIME::Types.logger.warn <<-EOS #{filename}:#{index + 1}: Parsing error in v1 MIME type definition. => #{line} EOS - raise BadV1Format, line + fail BadV1Format, line end unregistered, obsolete, platform, mediatype, subtype, extensions, @@ -181,7 +181,7 @@ class MIME::Types::Loader use_instead = nil else use_instead = docs.scan(%r{use-instead:(\S+)}).flatten.first - docs = docs.gsub(%r{use-instead:\S+}, "").squeeze(" \t") + docs = docs.gsub(%r{use-instead:\S+}, '').squeeze(' \t') end mime_type = MIME::Type.new("#{mediatype}/#{subtype}") do |t| @@ -195,7 +195,7 @@ class MIME::Types::Loader # This is being removed. Cheat to silence it for now. t.instance_variable_set :@references, - Array(urls).flatten.compact.uniq + Array(urls).flatten.compact.uniq end mime.add_type(mime_type, true) @@ -233,12 +233,14 @@ class MIME::Types::Loader end private + def read_file(filename) File.open(filename, 'r:UTF-8:-') { |f| f.read } end end private + def yaml_path File.join(path, '*.y{,a}ml') end diff --git a/lib/mime/types/logger.rb b/lib/mime/types/logger.rb new file mode 100644 index 0000000..2f0b858 --- /dev/null +++ b/lib/mime/types/logger.rb @@ -0,0 +1,35 @@ +# -*- ruby encoding: utf-8 -*- + +require 'logger' + +module MIME + class Types + class << self + # Configure the MIME::Types logger. This defaults to an instance of a + # logger that passes messages (unformatted) through to Kernel#warn. + attr_accessor :logger + end + + class WarnLogger < ::Logger #:nodoc: + class WarnLogDevice < ::Logger::LogDevice #:nodoc: + def initialize(*) + end + + def write(m) + Kernel.warn(m) + end + + def close + end + end + + def initialize(_1, _2 = nil, _3 = nil) + super nil + @logdev = WarnLogDevice.new + @formatter = ->(_s, _d, _p, m) { m } + end + end + + self.logger = WarnLogger.new(nil) + end +end |