Skip to content

Commit

Permalink
Fix Illustrator detection as application/pdf instead of application/i…
Browse files Browse the repository at this point in the history
…llustrator

Given an .ai file with an application/postscript declared type, the
filename extension would be ignored as a potential subtype of the
application/pdf magic-byte-detected type.

Fix by evaluating all candidate types rather than a single fallback.
  • Loading branch information
jeremy committed Feb 28, 2024
1 parent 12fc8da commit 8080070
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 26 deletions.
32 changes: 6 additions & 26 deletions lib/marcel/mime_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,8 @@ def extend(type, extensions: [], parents: [], magic: nil)
#
# If no type can be determined, then +application/octet-stream+ is returned.
def for(pathname_or_io = nil, name: nil, extension: nil, declared_type: nil)
type_from_data = for_data(pathname_or_io)
fallback_type = for_declared_type(declared_type) || for_name(name) || for_extension(extension) || BINARY

if type_from_data
most_specific_type type_from_data, fallback_type
else
fallback_type
end
filename_type = for_name(name) || for_extension(extension)
most_specific_type for_data(pathname_or_io), for_declared_type(declared_type), filename_type, BINARY
end

private
Expand Down Expand Up @@ -66,11 +60,7 @@ def for_extension(extension)
end

def for_declared_type(declared_type)
type = parse_media_type(declared_type)

if type != BINARY && !type.nil?
type.downcase
end
parse_media_type(declared_type)
end

def with_io(pathname_or_io, &block)
Expand All @@ -91,19 +81,9 @@ def parse_media_type(content_type)
# For some document types (notably Microsoft Office) we recognise the main content
# type with magic, but not the specific subclass. In this situation, if we can get a more
# specific class using either the name or declared_type, we should use that in preference
def most_specific_type(from_magic_type, fallback_type)
if (root_types(from_magic_type) & root_types(fallback_type)).any?
fallback_type
else
from_magic_type
end
end

def root_types(type)
if TYPE_EXTS[type].nil? || TYPE_PARENTS[type].nil?
[ type ]
else
TYPE_PARENTS[type].map {|t| root_types t }.flatten
def most_specific_type(*candidates)
candidates.compact.uniq.reduce do |type, candidate|
Marcel::Magic.child?(candidate, type) ? candidate : type
end
end
end
Expand Down
9 changes: 9 additions & 0 deletions test/illustrator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'test_helper'
require 'rack'

class Marcel::MimeType::IllustratorTest < Marcel::TestCase
test ".ai uploaded as application/postscript" do
file = files("name/application/illustrator/illustrator.ai")
assert_equal "application/illustrator", Marcel::MimeType.for(file, name: "illustrator.ai", declared_type: "application/postscript")
end
end

0 comments on commit 8080070

Please sign in to comment.