Changeset 7759
- Timestamp:
- 10/06/07 11:40:13 (2 years ago)
- Files:
-
- trunk/actionpack/lib/action_controller/request.rb (modified) (4 diffs)
- trunk/actionpack/test/controller/request_test.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/lib/action_controller/request.rb
r7758 r7759 460 460 value.map { |v| get_typed_value(v) } 461 461 else 462 # This is an uploaded file. 463 if value.respond_to?(:original_filename) && !value.original_filename.blank? 464 unless value.respond_to?(:full_original_filename) 465 class << value 466 alias_method :full_original_filename, :original_filename 467 468 # Take the basename of the upload's original filename. 469 # This handles the full Windows paths given by Internet Explorer 470 # (and perhaps other broken user agents) without affecting 471 # those which give the lone filename. 472 # The Windows regexp is adapted from Perl's File::Basename. 473 def original_filename 474 if md = /^(?:.*[:\\\/])?(.*)/m.match(full_original_filename) 475 md.captures.first 476 else 477 File.basename full_original_filename 478 end 479 end 480 end 462 if value.is_a?(UploadedFile) 463 # Uploaded file 464 if value.original_filename 465 value 466 # Multipart param 467 else 468 result = value.read 469 value.rewind 470 result 481 471 end 482 483 # Return the same value after overriding original_filename.484 value485 486 # Multipart values may have content type, but no filename.487 elsif value.respond_to?(:read)488 result = value.read489 value.rewind490 result491 492 472 # Unknown value, neither string nor multipart. 493 473 else … … 525 505 content = 526 506 if 10240 < content_length 527 Tempfile.new("CGI")507 UploadedTempfile.new("CGI") 528 508 else 529 StringIO.new509 UploadedStringIO.new 530 510 end 531 511 content.binmode if defined? content.binmode … … 569 549 content.rewind 570 550 571 /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni.match(head) 572 filename = ($1 or $2 or "") 573 if /Mac/ni.match(env['HTTP_USER_AGENT']) and 574 /Mozilla/ni.match(env['HTTP_USER_AGENT']) and 575 (not /MSIE/ni.match(env['HTTP_USER_AGENT'])) 576 filename = CGI.unescape(filename) 551 head =~ /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni 552 if filename = $1 || $2 553 if /Mac/ni.match(env['HTTP_USER_AGENT']) and 554 /Mozilla/ni.match(env['HTTP_USER_AGENT']) and 555 (not /MSIE/ni.match(env['HTTP_USER_AGENT'])) 556 filename = CGI.unescape(filename) 557 end 558 content.original_path = filename.dup 577 559 end 578 560 579 /Content-Type: ([^\r]*)/ni.match(head) 580 content_type = ($1 or "") 581 582 (class << content; self; end).class_eval do 583 alias local_path path 584 define_method(:original_filename) {filename.dup.taint} 585 define_method(:content_type) {content_type.dup.taint} 586 end 587 588 /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head) 589 name = $1.dup 561 head =~ /Content-Type: ([^\r]*)/ni 562 content.content_type = $1.dup if $1 563 564 head =~ /Content-Disposition:.* name="?([^\";]*)"?/ni 565 name = $1.dup if $1 590 566 591 567 if params.has_key?(name) … … 696 672 end 697 673 end 674 675 module UploadedFile 676 def self.included(base) 677 base.class_eval do 678 attr_accessor :original_path, :content_type 679 alias_method :local_path, :path 680 end 681 end 682 683 # Take the basename of the upload's original filename. 684 # This handles the full Windows paths given by Internet Explorer 685 # (and perhaps other broken user agents) without affecting 686 # those which give the lone filename. 687 # The Windows regexp is adapted from Perl's File::Basename. 688 def original_filename 689 unless defined? @original_filename 690 @original_filename = 691 unless original_path.blank? 692 if original_path =~ /^(?:.*[:\\\/])?(.*)/m 693 $1 694 else 695 File.basename original_path 696 end 697 end 698 end 699 @original_filename 700 end 701 end 702 703 class UploadedStringIO < StringIO 704 include UploadedFile 705 end 706 707 class UploadedTempfile < Tempfile 708 include UploadedFile 709 end 698 710 end trunk/actionpack/test/controller/request_test.rb
r7758 r7759 528 528 end 529 529 530 UploadedStringIO = ActionController::UploadedStringIO 531 class MockUpload < UploadedStringIO 532 def initialize(content_type, original_path, *args) 533 self.content_type = content_type 534 self.original_path = original_path 535 super *args 536 end 537 end 538 530 539 def test_parse_params_from_multipart_upload 531 mockup = Struct.new(:content_type, :original_filename, :read, :rewind) 532 file = mockup.new('img/jpeg', 'foo.jpg') 533 ie_file = mockup.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg') 534 non_file_text_part = mockup.new('text/plain', '', 'abc') 540 file = MockUpload.new('img/jpeg', 'foo.jpg') 541 ie_file = MockUpload.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg') 542 non_file_text_part = MockUpload.new('text/plain', '', 'abc') 535 543 536 544 input = { 537 "something" => [ StringIO.new("") ],538 "array_of_stringios" => [[ StringIO.new("One"),StringIO.new("Two") ]],539 "mixed_types_array" => [[ StringIO.new("Three"), "NotStringIO" ]],540 "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", StringIO.new("StringIO")]],541 "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", StringIO.new("StringIO")]],542 "products[string]" => [ StringIO.new("Apple Computer") ],545 "something" => [ UploadedStringIO.new("") ], 546 "array_of_stringios" => [[ UploadedStringIO.new("One"), UploadedStringIO.new("Two") ]], 547 "mixed_types_array" => [[ UploadedStringIO.new("Three"), "NotStringIO" ]], 548 "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", UploadedStringIO.new("StringIO")]], 549 "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", UploadedStringIO.new("StringIO")]], 550 "products[string]" => [ UploadedStringIO.new("Apple Computer") ], 543 551 "products[file]" => [ file ], 544 "ie_products[string]" => [ StringIO.new("Microsoft") ],552 "ie_products[string]" => [ UploadedStringIO.new("Microsoft") ], 545 553 "ie_products[file]" => [ ie_file ], 546 554 "text_part" => [non_file_text_part] … … 696 704 assert_kind_of StringIO, file 697 705 assert_equal 'file.csv', file.original_filename 698 assert_ equal '',file.content_type706 assert_nil file.content_type 699 707 assert_equal 'contents', file.read 700 708