class Mail::ContentTypeField
:nodoc:
def attempt_to_clean
def attempt_to_clean # Sanitize the value, handle special cases Mail::ContentTypeElement.new(sanitize(value)) rescue Mail::Field::ParseError # All else fails, just get the MIME media type Mail::ContentTypeElement.new(get_mime_type(value)) end
def decoded
def decoded p = "; #{parameters.decoded}" if parameters && parameters.length > 0 "#{content_type}#{p}" end
def default
def default decoded end
def element
def element @element ||= begin Mail::ContentTypeElement.new(value) rescue Mail::Field::ParseError attempt_to_clean end end
def encoded
def encoded p = ";\r\n\s#{parameters.encoded}" if parameters && parameters.length > 0 "#{name}: #{content_type}#{p}\r\n" end
def filename
def filename @filename ||= parameters['filename'] || parameters['name'] end
def generate_boundary
def generate_boundary "--==_mimepart_#{Mail.random_tag}" end
def get_mime_type(val)
def get_mime_type(val) case val when /^([\w\-]+)\/([\w\-]+);.+$/i "#{$1}/#{$2}" else 'text/plain' end end
def initialize(value = nil, charset = nil)
def initialize(value = nil, charset = nil) if value.is_a? Array @main_type = value[0] @sub_type = value[1] @parameters = ParameterHash.new.merge!(value.last) else @main_type = nil @sub_type = nil value = value.to_s end super ensure_filename_quoted(value), charset end
def main_type
def main_type @main_type ||= element.main_type end
def method_missing(name, *args, &block)
def method_missing(name, *args, &block) if name.to_s =~ /(\w+)=/ self.parameters[$1] = args.first @value = "#{content_type}; #{stringify(parameters)}" else super end end
def parameters
def parameters unless defined? @parameters @parameters = ParameterHash.new element.parameters.each { |p| @parameters.merge!(p) } end @parameters end
def sanitize(val)
Various special cases from random emails found that I am not going to change
def sanitize(val) # TODO: check if there are cases where whitespace is not a separator val = val. gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL) gsub(/;\s*$/,'') #remove trailing to keep examples below if val =~ /((boundary|name|filename)=(\S*))/i val = "#{$`.downcase}#{$2}=#{$3}#{$'.downcase}" else val.downcase! end case when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i # Microsoft helper: # Handles 'type/subtype;ISO-8559-1' "#{$1}/#{$2}; charset=#{Utilities.quote_atom($3)}" when val.chomp =~ /^text;?$/i # Handles 'text;' and 'text' "text/plain;" when val.chomp =~ /^(\w+);\s(.*)$/i # Handles 'text; <parameters>' "text/plain; #{$2}" when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i # Handles text/html; charset="charset="GB2312"" "#{$1}; charset=#{Utilities.quote_atom($2)}" when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i type = $1 # Handles misquoted param values # e.g: application/octet-stream; name=archiveshelp1[1].htm # and: audio/x-midi;\r\n\sname=Part .exe params = $2.to_s.split(/\s+/) params = params.map { |i| i.to_s.chomp.strip } params = params.map { |i| i.split(/\s*\=\s*/, 2) } params = params.map { |i| "#{i[0]}=#{Utilities.dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ') "#{type}; #{params}" when val =~ /^\s*$/ 'text/plain' else val end end
def singular?
def singular? true end
def string
def string "#{main_type}/#{sub_type}" end
def stringify(params)
def stringify(params) params.map { |k,v| "#{k}=#{Encodings.param_encode(v)}" }.join("; ") end
def sub_type
def sub_type @sub_type ||= element.sub_type end
def value
def value if @value.is_a? Array "#{@main_type}/#{@sub_type}; #{stringify(parameters)}" else @value end end
def with_boundary(type)
def with_boundary(type) new "#{type}; boundary=#{generate_boundary}" end