5 EXTENSION_LOOKUP
= Hash
.new
{ |h
, k
| h
[k
] = Type
.new(k
) unless k
.blank
? }
6 LOOKUP
= Hash
.new
{ |h
, k
| h
[k
] = Type
.new(k
) unless k
.blank
? }
8 # Encapsulates the notion of a mime type. Can be used at render time, for example, with:
10 # class PostsController < ActionController::Base
12 # @post = Post.find(params[:id])
14 # respond_to do |format|
16 # format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] }
17 # format.xml { render :xml => @people.to_xml }
22 @
@html_types = Set
.new
[:html, :all]
23 cattr_reader
:html_types
25 # These are the content types which browsers can generate without using ajax, flash, etc
26 # i.e. following a link, getting an image or posting a form. CSRF protection
27 # only needs to protect against these types.
28 @
@browser_generated_types = Set
.new
[:html, :url_encoded_form, :multipart_form, :text]
29 cattr_reader
:browser_generated_types
32 @
@unverifiable_types = Set
.new
[:text, :json, :csv, :xml, :rss, :atom, :yaml]
33 def self.unverifiable_types
34 ActiveSupport
::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller
)
38 # A simple helper class used in parsing the accept header
39 class AcceptItem
#:nodoc:
40 attr_accessor
:order, :name, :q
42 def initialize(order
, name
, q
=nil)
45 q
||= 0.0 if @name == Mime
::ALL # default wilcard match to end of list
46 @q = ((q
|| 1.0).to_f
* 100).to_i
55 result
= order
<=> item
.order
if result
== 0
60 name
== (item
.respond_to
?(:name) ? item
.name
: item
)
69 def lookup_by_extension(extension
)
70 EXTENSION_LOOKUP
[extension
]
73 # Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for
74 # rendering different HTML versions depending on the user agent, like an iPhone.
75 def register_alias(string
, symbol
, extension_synonyms
= [])
76 register(string
, symbol
, [], extension_synonyms
, true)
79 def register(string
, symbol
, mime_type_synonyms
= [], extension_synonyms
= [], skip_lookup
= false)
80 Mime
.instance_eval
{ const_set symbol
.to_s
.upcase
, Type
.new(string
, symbol
, mime_type_synonyms
) }
82 SET
<< Mime
.const_get(symbol
.to_s
.upcase
)
84 ([string
] + mime_type_synonyms
).each
{ |string
| LOOKUP
[string
] = SET
.last
} unless skip_lookup
85 ([symbol
.to_s
] + extension_synonyms
).each
{ |ext
| EXTENSION_LOOKUP
[ext
] = SET
.last
}
88 def parse(accept_header
)
89 if accept_header
!~
/,/
90 [Mime
::Type.lookup(accept_header
)]
92 # keep track of creation order to keep the subsequent sort stable
94 accept_header
.split(/,/).each_with_index
do |header
, index
|
95 params
, q
= header
.split(/;\s*q=/)
98 list
<< AcceptItem
.new(index
, params
, q
) unless params
.empty
?
103 # Take care of the broken text/xml entry by renaming or deleting it
104 text_xml
= list
.index("text/xml")
105 app_xml
= list
.index(Mime
::XML.to_s
)
107 if text_xml
&& app_xml
108 # set the q value to the max of the two
109 list
[app_xml
].q
= [list
[text_xml
].q
, list
[app_xml
].q
].max
111 # make sure app_xml is ahead of text_xml in the list
112 if app_xml
> text_xml
113 list
[app_xml
], list
[text_xml
] = list
[text_xml
], list
[app_xml
]
114 app_xml
, text_xml
= text_xml
, app_xml
117 # delete text_xml from the list
118 list
.delete_at(text_xml
)
121 list
[text_xml
].name
= Mime
::XML.to_s
124 # Look for more specific XML-based types and sort them ahead of app/xml
128 app_xml_type
= list
[app_xml
]
130 while(idx
< list
.length
)
132 break if type
.q
< app_xml_type
.q
133 if type
.name
=~
/\+xml$/
134 list
[app_xml
], list
[idx
] = list
[idx
], list
[app_xml
]
141 list
.map
! { |i
| Mime
::Type.lookup(i
.name
) }.uniq
!
147 def initialize(string
, symbol
= nil, synonyms
= [])
148 @symbol, @synonyms = symbol
, synonyms
161 @symbol || @string.to_sym
166 (@synonyms + [ self ]).any
? { |synonym
| list
.include?(synonym
) }
173 return false if mime_type
.blank
?
174 (@synonyms + [ self ]).any
? do |synonym
|
175 synonym
.to_s
== mime_type
.to_s
|| synonym
.to_sym
== mime_type
.to_sym
179 # Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
180 # ActionController::RequestForgeryProtection.
186 @
@html_types.include?(to_sym
) || @string =~
/html/
189 def browser_generated
?
190 @
@browser_generated_types.include?(to_sym
)
194 def method_missing(method
, *args
)
195 if method
.to_s
=~
/(\w+)\?$/
196 $1.downcase
.to_sym
== to_sym
204 require 'action_controller/mime_types'