Class: MIME::Types

Inherits:
Object
  • Object
show all
Extended by:
Enumerable
Defined in:
lib/mime/types.rb

Overview

MIME::Types

MIME types are used in MIME-compliant communications, as in e-mail or HTTP traffic, to indicate the type of content which is transmitted. MIME::Types provides the ability for detailed information about MIME entities (provided as a set of MIME::Type objects) to be determined and used programmatically. There are many types defined by RFCs and vendors, so the list is long but not complete; don’t hesitate to ask to add additional information. This library follows the IANA collection of MIME types (see below for reference).

Description

MIME types are used in MIME entities, as in email or HTTP traffic. It is useful at times to have information available about MIME types (or, inversely, about files). A MIME::Type stores the known information about one MIME type.

Usage

require 'mime/types'

plaintext = MIME::Types['text/plain']
print plaintext.media_type           # => 'text'
print plaintext.sub_type             # => 'plain'

puts plaintext.extensions.join(" ")  # => 'asc txt c cc h hh cpp'

puts plaintext.encoding              # => 8bit
puts plaintext.binary?               # => false
puts plaintext.ascii?                # => true
puts plaintext.obsolete?             # => false
puts plaintext.registered?           # => true
puts plaintext == 'text/plain'       # => true
puts MIME::Type.simplified('x-appl/x-zip') # => 'appl/zip'

This module is built to conform to the MIME types of RFCs 2045 and 2231. It follows the official IANA registry at www.iana.org/assignments/media-types/ and ftp.iana.org/assignments/media-types with some unofficial types added from the the collection at www.ltsw.se/knbase/internet/mime.htp

This is originally based on Perl MIME::Types by Mark Overmeer.

Author

Copyright

Copyright 2002–2013 by Austin Ziegler <[email protected]>

Version

1.20.1

Licence

See Licence.rdoc

See Also

www.iana.org/assignments/media-types/ www.ltsw.se/knbase/internet/mime.htp

Constant Summary collapse

VERSION =

The released version of Ruby MIME::Types

MIME::Type::VERSION
TEXT_FORMAT_RE =

The regular expression used to match a file-based MIME type definition.

%r{
  \A
  \s*
  ([*])?                                 # 0: Unregistered?
  (!)?                                   # 1: Obsolete?
  (?:(\w+):)?                            # 2: Platform marker
  #{MIME::Type::MEDIA_TYPE_RE}?          # 3,4: Media type
  (?:\s+@([^\s]+))?                      # 5: Extensions
  (?:\s+:(#{MIME::Type::ENCODING_RE}))?  # 6: Encoding
  (?:\s+'(.+))?                          # 7: URL list
  (?:\s+=(.+))?                          # 8: Documentation
  (?:\s*([#].*)?)?
  \s*
  \z
}x
STARTUP =
true

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data_version = nil) ⇒ Types

Returns a new instance of Types.



582
583
584
585
586
# File 'lib/mime/types.rb', line 582

def initialize(data_version = nil)
  @type_variants    = Hash.new { |h, k| h[k] = [] }
  @extension_index  = Hash.new { |h, k| h[k] = [] }
  @data_version = data_version
end

Instance Attribute Details

#data_versionObject (readonly)

The data version.



580
581
582
# File 'lib/mime/types.rb', line 580

def data_version
  @data_version
end

Class Method Details

.[](type_id, flags = {}) ⇒ Object

Returns a list of MIME::Type objects, which may be empty. The optional flag parameters are :complete (finds only complete MIME::Type objects) and :platform (finds only MIME::Types for the current platform). It is possible for multiple matches to be returned for either type (in the example below, ‘text/plain’ returns two values – one for the general case, and one for VMS systems.

puts "\nMIME::Types['text/plain']"
MIME::Types['text/plain'].each { |t| puts t.to_a.join(", ") }

puts "\nMIME::Types[/^image/, :complete => true]"
MIME::Types[/^image/, :complete => true].each do |t|
  puts t.to_a.join(", ")
end


830
831
832
# File 'lib/mime/types.rb', line 830

def [](type_id, flags = {})
  @__types__[type_id, flags]
end

.add(*types) ⇒ Object

Add one or more MIME::Type objects to the set of known types. Each type should be experimental (e.g., ‘application/x-ruby’). If the type is already known, a warning will be displayed.

<strong>Please inform the maintainer of this module when registered types are missing.</strong>



869
870
871
# File 'lib/mime/types.rb', line 869

def add(*types)
  @__types__.add(*types)
end

.add_type_variant(mime_type) ⇒ Object

:nodoc:



703
704
705
# File 'lib/mime/types.rb', line 703

def add_type_variant(mime_type) #:nodoc:
  @__types__.add_type_variant(mime_type)
end

.countObject



836
837
838
# File 'lib/mime/types.rb', line 836

def count
  @__types__.count
end

.eachObject



840
841
842
# File 'lib/mime/types.rb', line 840

def each
  @__types__.each {|t| yield t }
end

.index_extensions(mime_type) ⇒ Object

:nodoc:



707
708
709
# File 'lib/mime/types.rb', line 707

def index_extensions(mime_type) #:nodoc:
  @__types__.index_extensions(mime_type)
end

.load_from_file(filename) ⇒ Object

Build the type list from a file in the format:

[*][!][os:]mt/st[<ws>@ext][<ws>:enc][<ws>'url-list][<ws>=docs]

*

An unofficial MIME type. This should be used if and only if the MIME type is not properly specified (that is, not under either x-type or vnd.name.type).

!

An obsolete MIME type. May be used with an unofficial MIME type.

os:

Platform-specific MIME type definition.

mt

The media type.

st

The media subtype.

<ws>@ext

The list of comma-separated extensions.

<ws>:enc

The encoding.

<ws>‘url-list

The list of comma-separated URLs.

<ws>=docs

The documentation string.

That is, everything except the media type and the subtype is optional. The more information that’s available, though, the richer the values that can be provided.



765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
# File 'lib/mime/types.rb', line 765

def load_from_file(filename) #:nodoc:
  if defined? ::Encoding
    data = File.open(filename, 'r:UTF-8') { |f| f.read }
  else
    data = File.open(filename) { |f| f.read }
  end
  data = data.split($/)
  mime = MIME::Types.new
  data.each_with_index { |line, index|
    item = line.chomp.strip
    next if item.empty?

    begin
      m = TEXT_FORMAT_RE.match(item).captures
    rescue Exception
      puts "#{filename}:#{index}: Parsing error in MIME type definitions."
      puts "=> #{line}"
      raise
    end

    unregistered, obsolete, platform, mediatype, subtype, extensions,
      encoding, urls, docs, comment = *m

    if mediatype.nil?
      if comment.nil?
        puts "#{filename}:#{index}: Parsing error in MIME type definitions."
        puts "=> #{line}"
        raise RuntimeError
      end

      next
    end

    extensions &&= extensions.split(/,/)
    urls &&= urls.split(/,/)

    mime_type = MIME::Type.new("#{mediatype}/#{subtype}") do |t|
      t.extensions  = extensions
      t.encoding    = encoding
      t.system      = platform
      t.obsolete    = obsolete
      t.registered  = false if unregistered
      t.docs        = docs
      t.url         = urls
    end

    mime.add(mime_type)
  }
  mime
end

.of(filename, platform = false) ⇒ Object

A synonym for MIME::Types.type_for



859
860
861
# File 'lib/mime/types.rb', line 859

def of(filename, platform = false)
  @__types__.type_for(filename, platform)
end

.type_for(filename, platform = false) ⇒ Object

Return the list of MIME::Types which belongs to the file based on its filename extension. If platform is true, then only file types that are specific to the current platform will be returned.

This will always return an array.

puts "MIME::Types.type_for('citydesk.xml')
  => [application/xml, text/xml]
puts "MIME::Types.type_for('citydesk.gif')
  => [image/gif]


854
855
856
# File 'lib/mime/types.rb', line 854

def type_for(filename, platform = false)
  @__types__.type_for(filename, platform)
end

Instance Method Details

#[](type_id, flags = {}) ⇒ Object

Returns a list of MIME::Type objects, which may be empty. The optional flag parameters are :complete (finds only complete MIME::Type objects) and :platform (finds only MIME::Types for the current platform). It is possible for multiple matches to be returned for either type (in the example below, ‘text/plain’ returns two values – one for the general case, and one for VMS systems.

puts "\nMIME::Types['text/plain']"
MIME::Types['text/plain'].each { |t| puts t.to_a.join(", ") }

puts "\nMIME::Types[/^image/, :complete => true]"
MIME::Types[/^image/, :complete => true].each do |t|
  puts t.to_a.join(", ")
end

If multiple type definitions are returned, returns them sorted as follows:

1. Complete definitions sort before incomplete ones;
2. IANA-registered definitions sort before LTSW-recorded
   definitions.
3. Generic definitions sort before platform-specific ones;
4. Current definitions sort before obsolete ones;
5. Obsolete definitions with use-instead clauses sort before those
   without;
6. Obsolete definitions use-instead clauses are compared.
7. Sort on name.


639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/mime/types.rb', line 639

def [](type_id, flags = {})
  if type_id.kind_of?(Regexp)
    matches = []
    @type_variants.each_key do |k|
      matches << @type_variants[k] if k =~ type_id
    end
    matches.flatten!
  elsif type_id.kind_of?(MIME::Type)
    matches = [type_id]
  else
    matches = @type_variants[MIME::Type.simplified(type_id)]
  end

  matches.delete_if { |e| not e.complete? } if flags[:complete]
  matches.delete_if { |e| not e.platform? } if flags[:platform]

  matches.sort { |a, b| a.priority_compare(b) }
end

#add(*types) ⇒ Object

Add one or more MIME::Type objects to the set of known types. Each type should be experimental (e.g., ‘application/x-ruby’). If the type is already known, a warning will be displayed.

<strong>Please inform the maintainer of this module when registered types are missing.</strong>



686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'lib/mime/types.rb', line 686

def add(*types)
  types.each do |mime_type|
    if mime_type.kind_of? MIME::Types
      add(*mime_type.defined_types)
    else
      if @type_variants.include?(mime_type.simplified)
        if @type_variants[mime_type.simplified].include?(mime_type)
          warn "Type #{mime_type} already registered as a variant of #{mime_type.simplified}." unless defined? MIME::Types::STARTUP
        end
      end
      add_type_variant(mime_type)
      index_extensions(mime_type)
    end
  end
end

#add_type_variant(mime_type) ⇒ Object

:nodoc:



588
589
590
# File 'lib/mime/types.rb', line 588

def add_type_variant(mime_type) #:nodoc:
  @type_variants[mime_type.simplified] << mime_type
end

#countObject

Returns the number of known types. A shortcut of MIME::Types.size. (Keep in mind that this is memory intensive, cache the result to spare resources)



603
604
605
# File 'lib/mime/types.rb', line 603

def count
  defined_types.size
end

#defined_typesObject

:nodoc:



596
597
598
# File 'lib/mime/types.rb', line 596

def defined_types #:nodoc:
  @type_variants.values.flatten
end

#eachObject



607
608
609
# File 'lib/mime/types.rb', line 607

def each
 defined_types.each { |t| yield t }
end

#index_extensions(mime_type) ⇒ Object

:nodoc:



592
593
594
# File 'lib/mime/types.rb', line 592

def index_extensions(mime_type) #:nodoc:
  mime_type.extensions.each { |ext| @extension_index[ext] << mime_type }
end

#of(filename, platform = false) ⇒ Object

A synonym for MIME::Types.type_for



676
677
678
# File 'lib/mime/types.rb', line 676

def of(filename, platform = false)
  type_for(filename, platform)
end

#type_for(filename, platform = false) ⇒ Object

Return the list of MIME::Types which belongs to the file based on its filename extension. If platform is true, then only file types that are specific to the current platform will be returned.

This will always return an array.

puts "MIME::Types.type_for('citydesk.xml')
  => [application/xml, text/xml]
puts "MIME::Types.type_for('citydesk.gif')
  => [image/gif]


668
669
670
671
672
673
# File 'lib/mime/types.rb', line 668

def type_for(filename, platform = false)
  ext = filename.chomp.downcase.gsub(/.*\./o, '')
  list = @extension_index[ext]
  list.delete_if { |e| not e.platform? } if platform
  list
end