diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index d8ba20306d..de5c32b033 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Shorten IE file upload path to filename only to match other browsers. #1507 [court3nay@gmail.com] + * Fix open/save dialog in IE not opening files send with send_file/send_data, #2279 [Thomas Fuchs] * Fixed that auto_discovery_link_tag couldn't take a string as the URL [DHH] diff --git a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb index 3a14311acf..ac2dae9989 100755 --- a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb +++ b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb @@ -88,9 +88,30 @@ class CGIMethods #:nodoc: # test most frequent case first if value.is_a?(String) value - elsif value.respond_to?(:content_type) && !value.content_type.empty? + elsif value.respond_to?(:content_type) # Uploaded file + unless value.respond_to?(:full_original_filename) + class << value + alias_method :full_original_filename, :original_filename + + # Take the basename of the upload's original filename. + # This handles the full Windows paths given by Internet Explorer + # (and perhaps other broken user agents) without affecting + # those which give the lone filename. + # The Windows regexp is adapted from Perl's File::Basename. + def original_filename + if md = /^(?:.*[:\\\/])?(.*)/m.match(full_original_filename) + md.captures.first + else + File.basename full_original_filename + end + end + end + end + + # Return the same value after overriding original_filename. value + elsif value.respond_to?(:read) # Value as part of a multipart request value.read diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 8be3d3589c..cafed43aed 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -301,7 +301,7 @@ module ActionView (?:\#\w*)? # trailing anchor ) ([[:punct:]]|\s|<|$) # trailing text - /x + /x unless const_defined?(:AUTO_LINK_RE) # Turns all urls into clickable links. def auto_link_urls(text, href_options = {}) diff --git a/actionpack/test/controller/cgi_test.rb b/actionpack/test/controller/cgi_test.rb index 74f4fc9e8b..a896128168 100755 --- a/actionpack/test/controller/cgi_test.rb +++ b/actionpack/test/controller/cgi_test.rb @@ -4,16 +4,6 @@ require 'test/unit' require 'action_controller/cgi_ext/cgi_methods' require 'stringio' -class MockUploadedFile < StringIO - def content_type - "img/jpeg" - end - - def original_filename - "my_file.doc" - end -end - class CGITest < Test::Unit::TestCase def setup @query_string = "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1" @@ -116,15 +106,20 @@ class CGITest < Test::Unit::TestCase end def test_parse_params_from_multipart_upload - mock_file = MockUploadedFile.new + mockup = Struct.new(:content_type, :original_filename) + file = mockup.new('img/jpeg', 'foo.jpg') + ie_file = mockup.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg') input = { "something" => [ StringIO.new("") ], "array_of_stringios" => [[ StringIO.new("One"), StringIO.new("Two") ]], "mixed_types_array" => [[ StringIO.new("Three"), "NotStringIO" ]], - "mixed_types_as_checkboxes[strings][nested]" => [[ mock_file, "String", StringIO.new("StringIO")]], + "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", StringIO.new("StringIO")]], + "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", StringIO.new("StringIO")]], "products[string]" => [ StringIO.new("Apple Computer") ], - "products[file]" => [ mock_file ] + "products[file]" => [ file ], + "ie_products[string]" => [ StringIO.new("Microsoft") ], + "ie_products[file]" => [ ie_file ] } expected_output = { @@ -132,17 +127,35 @@ class CGITest < Test::Unit::TestCase "array_of_stringios" => ["One", "Two"], "mixed_types_array" => [ "Three", "NotStringIO" ], "mixed_types_as_checkboxes" => { - "strings"=> { - "nested"=>[ mock_file, "String", "StringIO" ] + "strings" => { + "nested" => [ file, "String", "StringIO" ] }, }, - "products" => { - "string" => "Apple Computer", - "file" => mock_file + "ie_mixed_types_as_checkboxes" => { + "strings" => { + "nested" => [ ie_file, "String", "StringIO" ] + }, + }, + "products" => { + "string" => "Apple Computer", + "file" => file + }, + "ie_products" => { + "string" => "Microsoft", + "file" => ie_file } } - assert_equal expected_output, CGIMethods.parse_request_parameters(input) + params = CGIMethods.parse_request_parameters(input) + assert_equal expected_output, params + + # Lone filenames are preserved. + assert_equal 'foo.jpg', params['mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'foo.jpg', params['products']['file'].original_filename + + # But full Windows paths are reduced to their basename. + assert_equal 'bar.jpg', params['ie_mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'bar.jpg', params['ie_products']['file'].original_filename end def test_parse_params_with_file