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/mime'
require 'linguist/pathname' require 'linguist/pathname'
require 'escape_utils'
require 'yaml' require 'yaml'
module Linguist module Linguist
@@ -63,12 +62,7 @@ module Linguist
# #
# Returns a content disposition String. # Returns a content disposition String.
def disposition def disposition
case content_type pathname.disposition
when 'application/octet-stream', 'application/java-archive'
"attachment; filename=#{EscapeUtils.escape_url(pathname.basename)}"
else
'inline'
end
end end
# Public: Is the blob text? # 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 and extensions to override when the raw blob is served
# mime types # mime types
application/javascript: text/plain
application/perl: text/plain
application/python: text/plain
application/rdf+xml: text/plain application/rdf+xml: text/plain
application/ruby: text/plain
application/sh: text/plain application/sh: text/plain
application/tex: text/plain application/tex: text/plain
application/xhtml+xml: text/plain application/xhtml+xml: text/plain

View File

@@ -1,11 +1,42 @@
require 'mime/types' require 'mime/types'
require 'yaml' 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 # Register additional mime type extensions
mime_extensions = YAML.load_file(File.expand_path("../mimes.yml", __FILE__)) 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) 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) MIME::Types.index_extensions(mime)
end end
@@ -59,5 +90,49 @@ module Linguist
type type
end 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
end end

View File

@@ -2,13 +2,75 @@
# #
# Review this list if we ever upgrade from mime-types 1.15 to 1.16 # 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: application/octet-stream:
binary: true
extensions:
- dmg - dmg
- dll - dll
application/java-archive: application/java-archive:
binary: true
extensions:
- ear - ear
- war - war
application/x-shockwave-flash: application/x-shockwave-flash:
binary: true
extensions:
- swf - swf
image/gif:
attachment: false
image/jpeg:
attachment: false
image/png:
attachment: false

View File

@@ -1,6 +1,8 @@
require 'linguist/language' require 'linguist/language'
require 'linguist/mime' require 'linguist/mime'
require 'escape_utils'
module Linguist module Linguist
# Similar to ::Pathname, Linguist::Pathname wraps a path string and # Similar to ::Pathname, Linguist::Pathname wraps a path string and
# provides helpful query methods. Its useful when you only have a # provides helpful query methods. Its useful when you only have a
@@ -99,6 +101,30 @@ module Linguist
@content_type ||= Mime.content_type_for(extname) @content_type ||= Mime.content_type_for(extname)
end 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 def to_s
@path.dup @path.dup
end end

View File

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

View File

@@ -8,9 +8,9 @@ class TestMime < Test::Unit::TestCase
def test_mime def test_mime
assert_equal 'text/plain', Mime.mime_for(nil) assert_equal 'text/plain', Mime.mime_for(nil)
assert_equal 'text/plain', Mime.mime_for(".rb") assert_equal 'application/ruby', Mime.mime_for(".rb")
assert_equal 'text/plain', Mime.mime_for(".js") assert_equal 'application/javascript', Mime.mime_for(".js")
assert_equal 'text/plain', Mime.mime_for(".py") assert_equal 'application/python', Mime.mime_for(".py")
assert_equal 'text/plain', Mime.mime_for(".kt") assert_equal 'text/plain', Mime.mime_for(".kt")
assert_equal 'text/html', Mime.mime_for(".html") 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(".ear")
assert_equal 'application/java-archive', Mime.content_type_for(".war") assert_equal 'application/java-archive', Mime.content_type_for(".war")
end 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 end

View File

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