escape filename in the Content-Disposition header
According the multipart form data spec in WHATWG living standard. Ref: https://html.spec.whatwg.org/#multipart-form-data
This commit is contained in:
parent
c90f203f7a
commit
ea8fc9495a
|
@ -396,13 +396,20 @@ module Sinatra
|
||||||
response['Content-Type'] = mime_type
|
response['Content-Type'] = mime_type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# https://html.spec.whatwg.org/#multipart-form-data
|
||||||
|
MULTIPART_FORM_DATA_REPLACEMENT_TABLE = {
|
||||||
|
'"' => '%22',
|
||||||
|
"\r" => '%0D',
|
||||||
|
"\n" => '%0A'
|
||||||
|
}.freeze
|
||||||
|
|
||||||
# Set the Content-Disposition to "attachment" with the specified filename,
|
# Set the Content-Disposition to "attachment" with the specified filename,
|
||||||
# instructing the user agents to prompt to save.
|
# instructing the user agents to prompt to save.
|
||||||
def attachment(filename = nil, disposition = :attachment)
|
def attachment(filename = nil, disposition = :attachment)
|
||||||
response['Content-Disposition'] = disposition.to_s.dup
|
response['Content-Disposition'] = disposition.to_s.dup
|
||||||
return unless filename
|
return unless filename
|
||||||
|
|
||||||
params = format('; filename="%s"', File.basename(filename))
|
params = format('; filename="%s"', File.basename(filename).gsub(/["\r\n]/, MULTIPART_FORM_DATA_REPLACEMENT_TABLE))
|
||||||
response['Content-Disposition'] << params
|
response['Content-Disposition'] << params
|
||||||
ext = File.extname(filename)
|
ext = File.extname(filename)
|
||||||
content_type(ext) unless response['Content-Type'] || ext.empty?
|
content_type(ext) unless response['Content-Type'] || ext.empty?
|
||||||
|
|
|
@ -781,6 +781,18 @@ class HelpersTest < Minitest::Test
|
||||||
assert_equal '<sinatra></sinatra>', body
|
assert_equal '<sinatra></sinatra>', body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'escapes filename in the Content-Disposition header according to the multipart form data spec in WHATWG living standard' do
|
||||||
|
mock_app do
|
||||||
|
get('/attachment') do
|
||||||
|
attachment "test.xml\";\r\next=.txt"
|
||||||
|
response.write("<sinatra></sinatra>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/attachment'
|
||||||
|
assert_equal 'attachment; filename="test.xml%22;%0D%0Aext=.txt"', response['Content-Disposition']
|
||||||
|
assert_equal '<sinatra></sinatra>', body
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'send_file' do
|
describe 'send_file' do
|
||||||
|
|
Loading…
Reference in New Issue