require'set'require'active_support/core_ext/class/attribute_accessors'require'active_support/core_ext/object/blank'moduleMimeclassMimes<Arraydefsymbols@symbols||=map{|m|m.to_sym}end%w(<< concat shift unshift push pop []= clear compact! collect!
delete delete_at delete_if flatten! map! insert reject! reverse!
replace slice! sort! uniq!).eachdo|method|module_eval<<-CODE,__FILE__,__LINE__+1
def #{method}(*)
@symbols = nil
super
end
CODEendendSET=Mimes.newEXTENSION_LOOKUP={}LOOKUP=Hash.new{|h,k|h[k]=Type.new(k)unlessk.blank?}defself.[](type)returntypeiftype.is_a?(Type)Type.lookup_by_extension(type.to_s)end# Encapsulates the notion of a mime type. Can be used at render time, for example, with:## class PostsController < ActionController::Base# def show# @post = Post.find(params[:id])## respond_to do |format|# format.html# format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] }# format.xml { render :xml => @people.to_xml }# end# end# endclassType@@html_types=Set.new[:html,:all]cattr_reader:html_types# These are the content types which browsers can generate without using ajax, flash, etc# i.e. following a link, getting an image or posting a form. CSRF protection# only needs to protect against these types.@@browser_generated_types=Set.new[:html,:url_encoded_form,:multipart_form,:text]cattr_reader:browser_generated_typesattr_reader:symbol# A simple helper class used in parsing the accept headerclassAcceptItem#:nodoc:attr_accessor:order,:name,:qdefinitialize(order,name,q=nil)@order=order@name=name.stripq||=0.0if@name==Mime::ALL# default wildcard match to end of list@q=((q||1.0).to_f*100).to_ienddefto_s@nameenddef<=>(item)result=item.q<=>qresult=order<=>item.orderifresult==0resultenddef==(item)name==(item.respond_to?(:name)?item.name:item)endendclass<<selfdeflookup(string)LOOKUP[string]enddeflookup_by_extension(extension)EXTENSION_LOOKUP[extension.to_s]end# Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for# rendering different HTML versions depending on the user agent, like an iPhone.defregister_alias(string,symbol,extension_synonyms=[])register(string,symbol,[],extension_synonyms,true)enddefregister(string,symbol,mime_type_synonyms=[],extension_synonyms=[],skip_lookup=false)Mime.const_set(symbol.to_s.upcase,Type.new(string,symbol,mime_type_synonyms))SET<<Mime.const_get(symbol.to_s.upcase)([string]+mime_type_synonyms).each{|str|LOOKUP[str]=SET.last}unlessskip_lookup([symbol.to_s]+extension_synonyms).each{|ext|EXTENSION_LOOKUP[ext]=SET.last}enddefparse(accept_header)ifaccept_header!~/,/[Mime::Type.lookup(accept_header)]else# keep track of creation order to keep the subsequent sort stablelist=[]accept_header.split(/,/).each_with_indexdo|header,index|params,q=header.split(/;\s*q=/)ifparamsparams.strip!list<<AcceptItem.new(index,params,q)unlessparams.empty?endendlist.sort!# Take care of the broken text/xml entry by renaming or deleting ittext_xml=list.index("text/xml")app_xml=list.index(Mime::XML.to_s)iftext_xml&&app_xml# set the q value to the max of the twolist[app_xml].q=[list[text_xml].q,list[app_xml].q].max# make sure app_xml is ahead of text_xml in the listifapp_xml>text_xmllist[app_xml],list[text_xml]=list[text_xml],list[app_xml]app_xml,text_xml=text_xml,app_xmlend# delete text_xml from the listlist.delete_at(text_xml)elsiftext_xmllist[text_xml].name=Mime::XML.to_send# Look for more specific XML-based types and sort them ahead of app/xmlifapp_xmlidx=app_xmlapp_xml_type=list[app_xml]while(idx<list.length)type=list[idx]breakiftype.q<app_xml_type.qiftype.name=~/\+xml$/list[app_xml],list[idx]=list[idx],list[app_xml]app_xml=idxendidx+=1endendlist.map!{|i|Mime::Type.lookup(i.name)}.uniq!listendendenddefinitialize(string,symbol=nil,synonyms=[])@symbol,@synonyms=symbol,synonyms@string=stringenddefto_s@stringenddefto_strto_senddefto_sym@symbolenddefrefto_sym||to_senddef===(list)iflist.is_a?(Array)(@synonyms+[self]).any?{|synonym|list.include?(synonym)}elsesuperendenddef==(mime_type)returnfalseifmime_type.blank?(@synonyms+[self]).any?do|synonym|synonym.to_s==mime_type.to_s||synonym.to_sym==mime_type.to_symendenddef=~(mime_type)returnfalseifmime_type.blank?regexp=Regexp.new(Regexp.quote(mime_type.to_s))(@synonyms+[self]).any?do|synonym|synonym.to_s=~regexpendend# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See# ActionController::RequestForgeryProtection.defverify_request?@@browser_generated_types.include?(to_sym)enddefhtml?@@html_types.include?(to_sym)||@string=~/html/endprivatedefmethod_missing(method,*args)ifmethod.to_s=~/(\w+)\?$/$1.downcase.to_sym==to_symelsesuperendendendendrequire'action_dispatch/http/mime_types'