Separate registry content type and content disposition

This commit is contained in:
Joshua Peek
2011-06-02 12:14:19 -05:00
parent 8fc89d1d4f
commit bcc2042768
8 changed files with 298 additions and 21 deletions

View File

@@ -2,7 +2,6 @@ require 'linguist/language'
require 'linguist/mime'
require 'linguist/pathname'
require 'escape_utils'
require 'yaml'
module Linguist
@@ -63,12 +62,7 @@ module Linguist
#
# Returns a content disposition String.
def disposition
case content_type
when 'application/octet-stream', 'application/java-archive'
"attachment; filename=#{EscapeUtils.escape_url(pathname.basename)}"
else
'inline'
end
pathname.disposition
end
# Public: Is the blob text?

View File

@@ -1,7 +1,11 @@
# MIME types and extensions to override when the raw blob is served
# mime types
application/javascript: text/plain
application/perl: text/plain
application/python: text/plain
application/rdf+xml: text/plain
application/ruby: text/plain
application/sh: text/plain
application/tex: text/plain
application/xhtml+xml: text/plain

View File

@@ -1,11 +1,42 @@
require 'mime/types'
require 'yaml'
module MIME
class Type
attr_accessor :binary
undef_method :binary?
def binary?
if defined? @binary
@binary
else
@encoding == 'base64'
end
end
attr_accessor :attachment
def attachment?
if defined? @attachment
@attachment
else
binary?
end
end
end
end
# Register additional mime type extensions
mime_extensions = YAML.load_file(File.expand_path("../mimes.yml", __FILE__))
mime_extensions.each do |mime_type, exts|
mime_extensions.each do |mime_type, options|
mime = MIME::Types[mime_type].first || MIME::Type.new(mime_type)
exts.each { |ext| mime.extensions << ext }
(options['extensions'] || []).each { |ext| mime.extensions << ext }
mime.binary = options['binary'] if options.key?('binary')
mime.attachment = options['attachment'] if options.key?('attachment')
MIME::Types.add_type_variant(mime)
MIME::Types.index_extensions(mime)
end
@@ -59,5 +90,49 @@ module Linguist
type
end
# Internal: Determine if extension or mime type is binary.
#
# ext_or_mime_type - A file extension ".txt" or mime type "text/plain".
#
# Returns true or false
def self.binary?(ext_or_mime_type)
mime_type = lookup_mime_type_for(ext_or_mime_type)
mime_type.nil? || mime_type.binary?
end
# Internal: Determine if extension or mime type is an attachment.
#
# ext_or_mime_type - A file extension ".txt" or mime type "text/plain".
#
# Attachments are files that should be downloaded rather than be
# displayed in the browser.
#
# This is used to set our Content-Disposition headers.
#
# Attachment files should generally binary files but non-
# attachments do not imply plain text. For an example Images are
# not treated as attachments.
#
# Returns true or false
def self.attachment?(ext_or_mime_type)
mime_type = lookup_mime_type_for(ext_or_mime_type)
mime_type.nil? || mime_type.attachment?
end
# Internal: Lookup mime type for extension or mime type
#
# Returns a MIME::Type
def self.lookup_mime_type_for(ext_or_mime_type)
ext_or_mime_type ||= ''
if ext_or_mime_type =~ /\w+\/\w+/
guesses = ::MIME::Types[ext_or_mime_type]
else
guesses = ::MIME::Types.type_for(ext_or_mime_type)
end
guesses.first
end
end
end

View File

@@ -2,13 +2,75 @@
#
# Review this list if we ever upgrade from mime-types 1.15 to 1.16
application/atom+xml:
binary: false
application/javascript:
binary: false
extensions:
- js
application/json:
binary: false
extensions:
- json
application/rdf+xml:
binary: false
application/sh:
binary: false
application/x-troff-ms:
binary: false
application/netcdf:
binary: false
application/x-perl:
binary: false
extensions:
- pl
- pm
application/x-python:
binary: false
extensions:
- py
application/x-ruby:
binary: false
extensions:
- rb
application/x-wais-source:
binary: false
application/vnd.mozilla.xul+xml:
binary: false
application/octet-stream:
- dmg
- dll
binary: true
extensions:
- dmg
- dll
application/java-archive:
- ear
- war
binary: true
extensions:
- ear
- war
application/x-shockwave-flash:
- swf
binary: true
extensions:
- swf
image/gif:
attachment: false
image/jpeg:
attachment: false
image/png:
attachment: false

View File

@@ -1,6 +1,8 @@
require 'linguist/language'
require 'linguist/mime'
require 'escape_utils'
module Linguist
# Similar to ::Pathname, Linguist::Pathname wraps a path string and
# provides helpful query methods. Its useful when you only have a
@@ -99,6 +101,30 @@ module Linguist
@content_type ||= Mime.content_type_for(extname)
end
# Public: Determine if the Pathname should be served as an
# attachment.
#
# Returns true or false.
def attachment?
@attachment ||= Mime.attachment?(extname)
end
# Public: Get the Content-Disposition header value
#
# This value is used when serving raw blobs.
#
# # => "attachment; filename=file.tar"
# # => "inline"
#
# Returns a content disposition String.
def disposition
if attachment?
"attachment; filename=#{EscapeUtils.escape_url(basename)}"
else
'inline'
end
end
def to_s
@path.dup
end

View File

@@ -23,7 +23,7 @@ class TestBlob < Test::Unit::TestCase
end
def test_mime_type
assert_equal "text/plain", blob("grit.rb").mime_type
assert_equal "application/ruby", blob("grit.rb").mime_type
assert_equal "application/xml", blob("bar.xml").mime_type
assert_equal "text/plain", blob("dog.o").mime_type
assert_equal "application/sh", blob("script.sh").mime_type
@@ -31,6 +31,7 @@ class TestBlob < Test::Unit::TestCase
def test_content_type
assert_equal "text/plain; charset=utf-8", blob("grit.rb").content_type
assert_equal "text/plain; charset=utf-8", blob("foo.pl").content_type
assert_equal "text/plain; charset=utf-8", blob("bar.xml").content_type
assert_equal "application/octet-stream", blob("dog.o").content_type
assert_equal "text/plain; charset=utf-8", blob("script.sh").content_type
@@ -69,7 +70,9 @@ class TestBlob < Test::Unit::TestCase
assert blob("git.deb").binary?
assert blob("git.exe").binary?
assert !blob("file.txt").binary?
assert !blob("foo.rb").binary?
assert !blob("octocat.png").binary?
assert !blob("script.pl").binary?
end
def test_text
@@ -88,6 +91,7 @@ class TestBlob < Test::Unit::TestCase
def test_viewable
assert blob("foo.rb").viewable?
assert blob("script.pl").viewable?
assert !blob("octocat.png").viewable?
assert !blob("linguist.gem").viewable?
end

View File

@@ -8,9 +8,9 @@ class TestMime < Test::Unit::TestCase
def test_mime
assert_equal 'text/plain', Mime.mime_for(nil)
assert_equal 'text/plain', Mime.mime_for(".rb")
assert_equal 'text/plain', Mime.mime_for(".js")
assert_equal 'text/plain', Mime.mime_for(".py")
assert_equal 'application/ruby', Mime.mime_for(".rb")
assert_equal 'application/javascript', Mime.mime_for(".js")
assert_equal 'application/python', Mime.mime_for(".py")
assert_equal 'text/plain', Mime.mime_for(".kt")
assert_equal 'text/html', Mime.mime_for(".html")
@@ -49,4 +49,116 @@ class TestMime < Test::Unit::TestCase
assert_equal 'application/java-archive', Mime.content_type_for(".ear")
assert_equal 'application/java-archive', Mime.content_type_for(".war")
end
def test_binary
assert Mime.binary?("application/octet-stream")
assert !Mime.binary?("text/plain")
assert Mime.binary?("image/gif")
assert Mime.binary?("image/jpeg")
assert Mime.binary?("image/png")
assert Mime.binary?("java-archive")
assert Mime.binary?("x-shockwave-flash")
assert !Mime.binary?("application/atom+xml")
assert !Mime.binary?("application/javascript")
assert !Mime.binary?("application/json")
assert !Mime.binary?("application/rdf+xml")
assert !Mime.binary?("application/sh")
assert !Mime.binary?("application/x-perl")
assert !Mime.binary?("application/x-python")
assert !Mime.binary?("application/x-ruby")
assert !Mime.binary?(".ms")
assert !Mime.binary?(".nc")
assert !Mime.binary?(".src")
assert !Mime.binary?(".xul")
end
def test_attachment
assert Mime.attachment?("application/octet-stream")
assert !Mime.attachment?("text/plain")
assert Mime.attachment?("application/java-archive")
assert Mime.attachment?("application/ogg")
assert Mime.attachment?("application/pdf")
assert Mime.attachment?("application/x-gzip")
assert Mime.attachment?("application/zip")
assert Mime.attachment?("audio/mp4")
assert Mime.attachment?(".a")
assert Mime.attachment?(".air")
assert Mime.attachment?(".blend")
assert Mime.attachment?(".crx")
assert Mime.attachment?(".deb")
assert Mime.attachment?(".dmg")
assert Mime.attachment?(".exe")
assert Mime.attachment?(".gem")
assert Mime.attachment?(".graffle")
assert Mime.attachment?(".gz")
assert Mime.attachment?(".icns")
assert Mime.attachment?(".ipa")
assert Mime.attachment?(".lib")
assert Mime.attachment?(".mcz")
assert Mime.attachment?(".mov")
assert Mime.attachment?(".mp3")
assert Mime.attachment?(".nib")
assert Mime.attachment?(".o")
assert Mime.attachment?(".odp")
assert Mime.attachment?(".ods")
assert Mime.attachment?(".odt")
assert Mime.attachment?(".ogg")
assert Mime.attachment?(".ogv")
assert Mime.attachment?(".otf")
assert Mime.attachment?(".pfx")
assert Mime.attachment?(".pigx")
assert Mime.attachment?(".plgx")
assert Mime.attachment?(".pptx")
assert Mime.attachment?(".psd")
assert Mime.attachment?(".sib")
assert Mime.attachment?(".so")
assert Mime.attachment?(".spl")
assert Mime.attachment?(".sqlite3")
assert Mime.attachment?(".swc")
assert Mime.attachment?(".swf")
assert Mime.attachment?(".tar")
assert Mime.attachment?(".ucode")
assert Mime.attachment?(".xpi")
assert Mime.attachment?(".zip")
assert !Mime.attachment?("application/atom+xml")
assert !Mime.attachment?("application/javascript")
assert !Mime.attachment?("application/json")
assert !Mime.attachment?("application/rdf+xml")
assert !Mime.attachment?("application/sh")
assert !Mime.attachment?("application/xhtml+xml")
assert !Mime.attachment?("application/xml")
assert !Mime.attachment?("image/gif")
assert !Mime.attachment?("image/jpeg")
assert !Mime.attachment?("image/png")
assert !Mime.attachment?("text/css")
assert !Mime.attachment?("text/csv")
assert !Mime.attachment?("text/html")
assert !Mime.attachment?("text/javascript")
assert !Mime.attachment?("text/plain")
assert !Mime.attachment?(".gif")
assert !Mime.attachment?(".jpeg")
assert !Mime.attachment?(".jpg")
assert !Mime.attachment?(".js")
assert !Mime.attachment?(".latex")
assert !Mime.attachment?(".ms")
assert !Mime.attachment?(".nc")
assert !Mime.attachment?(".pl")
assert !Mime.attachment?(".png")
assert !Mime.attachment?(".ps")
assert !Mime.attachment?(".py")
assert !Mime.attachment?(".rb")
assert !Mime.attachment?(".sh")
assert !Mime.attachment?(".src")
assert !Mime.attachment?(".tcl")
assert !Mime.attachment?(".texi")
assert !Mime.attachment?(".texinfo")
assert !Mime.attachment?(".xul")
end
end

View File

@@ -52,9 +52,9 @@ class TestPathname < Test::Unit::TestCase
end
def test_mime_type
assert_equal 'text/plain', Pathname.new("file.rb").mime_type
assert_equal 'text/plain', Pathname.new("file.js").mime_type
assert_equal 'text/plain', Pathname.new("itty.py").mime_type
assert_equal 'application/ruby', Pathname.new("file.rb").mime_type
assert_equal 'application/javascript', Pathname.new("file.js").mime_type
assert_equal 'application/python', Pathname.new("itty.py").mime_type
assert_equal 'text/plain', Pathname.new("defun.kt").mime_type
end