From c89579c93bdce2ff1b1b403ee400fb05dbed07d6 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Tue, 12 Sep 2023 21:46:54 -0700 Subject: [PATCH] Fix Illustrator detection as application/pdf instead of application/illustrator 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. --- lib/marcel/mime_type.rb | 32 ++++++-------------------------- marcel.gemspec | 1 - test/illustrator_test.rb | 9 +++++++++ test/test_helper.rb | 4 +--- 4 files changed, 16 insertions(+), 30 deletions(-) create mode 100644 test/illustrator_test.rb diff --git a/lib/marcel/mime_type.rb b/lib/marcel/mime_type.rb index 01db58e..6d7c15e 100644 --- a/lib/marcel/mime_type.rb +++ b/lib/marcel/mime_type.rb @@ -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 @@ -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) @@ -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 diff --git a/marcel.gemspec b/marcel.gemspec index 112af8f..9a1417a 100644 --- a/marcel.gemspec +++ b/marcel.gemspec @@ -24,5 +24,4 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rake', '~> 13.0' spec.add_development_dependency 'rack', '~> 2.0' spec.add_development_dependency 'nokogiri', '>= 1.9.1' - spec.add_development_dependency 'byebug', '~> 10.0.2' end diff --git a/test/illustrator_test.rb b/test/illustrator_test.rb new file mode 100644 index 0000000..9831d67 --- /dev/null +++ b/test/illustrator_test.rb @@ -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 diff --git a/test/test_helper.rb b/test/test_helper.rb index 477445c..7e052f1 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,10 +1,8 @@ require 'minitest/autorun' -require 'byebug' - require 'marcel' require 'pathname' -class Marcel::TestCase < MiniTest::Test +class Marcel::TestCase < Minitest::Test class << self def setup(&block) define_method(:setup, &block)