Commit c5f2b145 by Jon Yurek

Add a way to allow content_types that file misses

There are some file types that the file command doesn't understand.
Notably, files that have a format, but are ASCII-text based (like ruby,
certificates, etc), show up as text/plain. This presents a problem,
because the mime-types gem either doesn't report them at all (as for
.pem files) or reports them differently (as for .rb files).

This change allows a Paperclip.options[:content_type_mapping] hash,
which allows for a mapping of { :pem => "text/plain" } which tells the
spoof detector that this is an OK matchup and to allow it.
parent 7084ddc6
......@@ -77,12 +77,13 @@ module Paperclip
# nil, which uses the first executable found in the user's search path.
def self.options
@options ||= {
:whiny => true,
:whiny => true,
:image_magick_path => nil,
:command_path => nil,
:log => true,
:log_command => true,
:swallow_stderr => true
:command_path => nil,
:log => true,
:log_command => true,
:swallow_stderr => true,
:content_type_mappings => {}
}
end
......
......@@ -10,19 +10,44 @@ module Paperclip
end
def spoofed?
if ! @name.blank?
! supplied_file_media_type.include?(calculated_media_type)
if @name.present? && media_type_mismatch? && mapping_override_mismatch?
Paperclip.log("Content Type Spoof: Filename #{File.basename(@name)} (#{supplied_file_content_types}), content type discovered from file command: #{calculated_content_type}. See documentation to allow this combination.")
true
end
end
private
def supplied_file_media_type
MIME::Types.type_for(@name).collect(&:media_type)
def media_type_mismatch?
! supplied_file_media_types.include?(calculated_media_type)
end
def mapping_override_mismatch?
mapped_content_type != calculated_content_type
end
def supplied_file_media_types
@supplied_file_media_types ||= MIME::Types.type_for(@name).collect(&:media_type)
end
def calculated_media_type
type_from_file_command.split("/").first
@calculated_media_type ||= calculated_content_type.split("/").first
end
def supplied_file_content_types
@supplied_file_content_types ||= MIME::Types.type_for(@name).collect(&:content_type)
end
def calculated_content_type
@calculated_content_type ||= type_from_file_command.chomp
end
def mapped_content_type
Paperclip.options[:content_type_mappings][filename_extension]
end
def filename_extension
File.extname(@name.to_s.downcase).sub(/^\./, '').to_sym
end
def type_from_file_command
......
......@@ -25,4 +25,17 @@ class MediaTypeSpoofDetectorTest < Test::Unit::TestCase
adapter = Paperclip.io_adapters.for(File.new(fixture_file("5k.png")))
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
end
should 'not reject when the extension => content_type is in :content_type_mappings' do
begin
Paperclip.options[:content_type_mappings] = { pem: "text/plain" }
file = Tempfile.open(["test", ".PEM"])
file.puts "Certificate!"
file.close
adapter = Paperclip.io_adapters.for(File.new(file.path));
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
ensure
Paperclip.options[:content_type_mappings] = {}
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment