mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* test/cgi/test_cgi_multipart.rb: add test for multipart.
Patch by Takeyuki Fujioka. [ruby-dev:36014] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18890 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									692395b81f
								
							
						
					
					
						commit
						283e57e328
					
				
					 5 changed files with 310 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,8 @@
 | 
			
		|||
Thu Aug 28 09:26:53 2008  NARUSE, Yui  <naruse@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* test/cgi/test_cgi_multipart.rb: add test for multipart.
 | 
			
		||||
	  Patch by Takeyuki Fujioka. [ruby-dev:36014]
 | 
			
		||||
 | 
			
		||||
Thu Aug 28 09:22:01 2008  NARUSE, Yui  <naruse@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* test/cgi/test_cgi_modruby.rb: add test for mod_ruby adaptor.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										295
									
								
								test/cgi/test_cgi_multipart.rb
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										295
									
								
								test/cgi/test_cgi_multipart.rb
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,295 @@
 | 
			
		|||
require 'test/unit'
 | 
			
		||||
require 'cgi'
 | 
			
		||||
require 'tempfile'
 | 
			
		||||
require 'stringio'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## usage:
 | 
			
		||||
##   boundary = 'foobar1234'  # or nil
 | 
			
		||||
##   multipart = MultiPart.new(boundary)
 | 
			
		||||
##   multipart.append('name1', 'value1')
 | 
			
		||||
##   multipart.append('file1', File.read('file1.html'), 'file1.html')
 | 
			
		||||
##   str = multipart.close()
 | 
			
		||||
##   str.each_line {|line| p line }
 | 
			
		||||
##   ## output:
 | 
			
		||||
##   # "--foobar1234\r\n"
 | 
			
		||||
##   # "Content-Disposition: form-data: name=\"name1\"\r\n"
 | 
			
		||||
##   # "\r\n"
 | 
			
		||||
##   # "value1\r\n"
 | 
			
		||||
##   # "--foobar1234\r\n"
 | 
			
		||||
##   # "Content-Disposition: form-data: name=\"file1\"; filename=\"file1.html\"\r\n"
 | 
			
		||||
##   # "Content-Type: text/html\r\n"
 | 
			
		||||
##   # "\r\n"
 | 
			
		||||
##   # "<html>\n"
 | 
			
		||||
##   # "<body><p>Hello</p></body>\n"
 | 
			
		||||
##   # "</html>\n"
 | 
			
		||||
##   # "\r\n"
 | 
			
		||||
##   # "--foobar1234--\r\n"
 | 
			
		||||
##
 | 
			
		||||
class MultiPart
 | 
			
		||||
 | 
			
		||||
  def initialize(boundary=nil)
 | 
			
		||||
    @boundary = boundary || create_boundary()
 | 
			
		||||
    @buf = ''
 | 
			
		||||
  end
 | 
			
		||||
  attr_reader :boundary
 | 
			
		||||
 | 
			
		||||
  def append(name, value, filename=nil, content_type=nil)
 | 
			
		||||
    value.force_encoding("ASCII-8BIT") if RUBY_VERSION>="1.9"
 | 
			
		||||
    content_type = detect_content_type(filename) if filename && content_type.nil?
 | 
			
		||||
    s = filename ? "; filename=\"#{filename}\"" : ''
 | 
			
		||||
    buf = @buf
 | 
			
		||||
    buf << "--#{boundary}\r\n"
 | 
			
		||||
    buf << "Content-Disposition: form-data: name=\"#{name}\"#{s}\r\n"
 | 
			
		||||
    buf << "Content-Type: #{content_type}\r\n" if content_type
 | 
			
		||||
    buf << "\r\n"
 | 
			
		||||
    buf << value
 | 
			
		||||
    buf << "\r\n"
 | 
			
		||||
    return self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def close
 | 
			
		||||
    buf = @buf
 | 
			
		||||
    @buf = ''
 | 
			
		||||
    return buf << "--#{boundary}--\r\n"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def create_boundary()  #:nodoc:
 | 
			
		||||
    return "--boundary#{rand().to_s[2..-1]}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def detect_content_type(filename)   #:nodoc:
 | 
			
		||||
    filename =~ /\.(\w+)\z/
 | 
			
		||||
    return MIME_TYPES[$1] || 'application/octet-stream'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  MIME_TYPES = {
 | 
			
		||||
    'gif'      =>  'image/gif',
 | 
			
		||||
    'jpg'      =>  'image/jpeg',
 | 
			
		||||
    'jpeg'     =>  'image/jpeg',
 | 
			
		||||
    'png'      =>  'image/png',
 | 
			
		||||
    'bmp'      =>  'image/bmp',
 | 
			
		||||
    'tif'      =>  'image/tiff',
 | 
			
		||||
    'tiff'     =>  'image/tiff',
 | 
			
		||||
    'htm'      =>  'text/html',
 | 
			
		||||
    'html'     =>  'text/html',
 | 
			
		||||
    'xml'      =>  'text/xml',
 | 
			
		||||
    'txt'      =>  'text/plain',
 | 
			
		||||
    'text'     =>  'text/plain',
 | 
			
		||||
    'css'      =>  'text/css',
 | 
			
		||||
    'mpg'      =>  'video/mpeg',
 | 
			
		||||
    'mpeg'     =>  'video/mpeg',
 | 
			
		||||
    'mov'      =>  'video/quicktime',
 | 
			
		||||
    'avi'      =>  'video/x-msvideo',
 | 
			
		||||
    'mp3'      =>  'audio/mpeg',
 | 
			
		||||
    'mid'      =>  'audio/midi',
 | 
			
		||||
    'wav'      =>  'audio/x-wav',
 | 
			
		||||
    'zip'      =>  'application/zip',
 | 
			
		||||
    #'tar.gz'   =>  'application/gtar',
 | 
			
		||||
    'gz'       =>  'application/gzip',
 | 
			
		||||
    'bz2'      =>  'application/bzip2',
 | 
			
		||||
    'rtf'      =>  'application/rtf',
 | 
			
		||||
    'pdf'      =>  'application/pdf',
 | 
			
		||||
    'ps'       =>  'application/postscript',
 | 
			
		||||
    'js'       =>  'application/x-javascript',
 | 
			
		||||
    'xls'      =>  'application/vnd.ms-excel',
 | 
			
		||||
    'doc'      =>  'application/msword',
 | 
			
		||||
    'ppt'      =>  'application/vnd.ms-powerpoint',
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CGIMultipartTest < Test::Unit::TestCase
 | 
			
		||||
 | 
			
		||||
  def setup
 | 
			
		||||
    ENV['REQUEST_METHOD'] = 'POST'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def teardown
 | 
			
		||||
    %w[ REQUEST_METHOD CONTENT_TYPE CONTENT_LENGTH REQUEST_METHOD ].each do |name|
 | 
			
		||||
      ENV.delete(name)
 | 
			
		||||
    end
 | 
			
		||||
    $stdin.close() if $stdin.is_a?(Tempfile)
 | 
			
		||||
    $stdin = STDIN
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def _prepare(data)
 | 
			
		||||
    ## create multipart input
 | 
			
		||||
    multipart = MultiPart.new(@boundary)
 | 
			
		||||
    data.each do |hash|
 | 
			
		||||
      multipart.append(hash[:name], hash[:value], hash[:filename])
 | 
			
		||||
    end
 | 
			
		||||
    input = multipart.close()
 | 
			
		||||
    input = yield(input) if block_given?
 | 
			
		||||
    #$stderr.puts "*** debug: input=\n#{input.collect{|line| line.inspect}.join("\n")}"
 | 
			
		||||
    @boundary ||= multipart.boundary
 | 
			
		||||
    ## set environment
 | 
			
		||||
    ENV['CONTENT_TYPE'] = "multipart/form-data; boundary=#{@boundary}"
 | 
			
		||||
    ENV['CONTENT_LENGTH'] = input.length.to_s
 | 
			
		||||
    ENV['REQUEST_METHOD'] = 'POST'
 | 
			
		||||
    ## set $stdin
 | 
			
		||||
    tmpfile = Tempfile.new(self.name)
 | 
			
		||||
    tmpfile << input
 | 
			
		||||
    tmpfile.rewind()
 | 
			
		||||
    $stdin = tmpfile
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def _test_multipart
 | 
			
		||||
    caller(0).find {|s| s =~ /in `test_(.*?)'/ }
 | 
			
		||||
    testname = $1
 | 
			
		||||
    #$stderr.puts "*** debug: testname=#{testname.inspect}"
 | 
			
		||||
    _prepare(@data)
 | 
			
		||||
    cgi = CGI.new
 | 
			
		||||
    expected_names = @data.collect{|hash| hash[:name] }.sort
 | 
			
		||||
    assert_equal(expected_names, cgi.params.keys.sort)
 | 
			
		||||
    threshold = 1024*10
 | 
			
		||||
    @data.each do |hash|
 | 
			
		||||
      name = hash[:name]
 | 
			
		||||
      expected = hash[:value]
 | 
			
		||||
      expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
 | 
			
		||||
      assert_kind_of(expected_class, cgi[name]) if RUBY_VERSION<"1.9"
 | 
			
		||||
      assert_equal(expected, cgi[name].read()) if RUBY_VERSION<"1.9"
 | 
			
		||||
      assert_equal(hash[:filename] || '', cgi[name].original_filename) #if hash[:filename]
 | 
			
		||||
      assert_equal(hash[:content_type] || '', cgi[name].content_type)  #if hash[:content_type]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def _read(basename)
 | 
			
		||||
    filename = File.join(File.dirname(__FILE__), 'testdata', basename)
 | 
			
		||||
    s = File.open(filename, 'rb') {|f| f.read() }
 | 
			
		||||
    return s
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_stringio
 | 
			
		||||
    @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'hidden1', :value=>'foobar'},
 | 
			
		||||
      {:name=>'text1',   :value=>"\202\240\202\242\202\244\202\246\202\250"},
 | 
			
		||||
      {:name=>'file1',   :value=>_read('file1.html'),
 | 
			
		||||
       :filename=>'file1.html', :content_type=>'text/html'},
 | 
			
		||||
      {:name=>'image1',  :value=>_read('small.png'),
 | 
			
		||||
       :filename=>'small.png',  :content_type=>'image/png'},  # small image
 | 
			
		||||
    ]
 | 
			
		||||
    @expected_class = StringIO
 | 
			
		||||
    _test_multipart()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_tempfile
 | 
			
		||||
    @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'hidden1', :value=>'foobar'},
 | 
			
		||||
      {:name=>'text1',   :value=>"\202\240\202\242\202\244\202\246\202\250"},
 | 
			
		||||
      {:name=>'file1',   :value=>_read('file1.html'),
 | 
			
		||||
       :filename=>'file1.html', :content_type=>'text/html'},
 | 
			
		||||
      {:name=>'image1',  :value=>_read('large.png'),
 | 
			
		||||
       :filename=>'large.png',  :content_type=>'image/png'},  # large image
 | 
			
		||||
    ]
 | 
			
		||||
    @expected_class = Tempfile
 | 
			
		||||
    _test_multipart()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def _set_const(klass, name, value)
 | 
			
		||||
    old = nil
 | 
			
		||||
    klass.class_eval do
 | 
			
		||||
      old = const_get(name)
 | 
			
		||||
      remove_const(name)
 | 
			
		||||
      const_set(name, value)
 | 
			
		||||
    end
 | 
			
		||||
    return old
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_maxmultipartlength
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'image1', :value=>_read('large.png'),
 | 
			
		||||
       :filename=>'large.png', :content_type=>'image/png'},  # large image
 | 
			
		||||
    ]
 | 
			
		||||
    original = _set_const(CGI, :MAX_MULTIPART_LENGTH, 2 * 1024)
 | 
			
		||||
    begin
 | 
			
		||||
      ex = assert_raise(StandardError) do
 | 
			
		||||
        _test_multipart()
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal("too large multipart data.", ex.message)
 | 
			
		||||
    ensure
 | 
			
		||||
      _set_const(CGI, :MAX_MULTIPART_LENGTH, original)
 | 
			
		||||
    end
 | 
			
		||||
  end if CGI.const_defined?(:MAX_MULTIPART_LENGTH)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_maxmultipartcount
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'file1', :value=>_read('file1.html'),
 | 
			
		||||
       :filename=>'file1.html', :content_type=>'text/html'},
 | 
			
		||||
    ]
 | 
			
		||||
    item = @data.first
 | 
			
		||||
    500.times { @data << item }
 | 
			
		||||
    #original = _set_const(CGI, :MAX_MULTIPART_COUNT, 128)
 | 
			
		||||
    begin
 | 
			
		||||
      ex = assert_raise(StandardError) do
 | 
			
		||||
        _test_multipart()
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal("too many parameters.", ex.message)
 | 
			
		||||
    ensure
 | 
			
		||||
      #_set_const(CGI, :MAX_MULTIPART_COUNT, original)
 | 
			
		||||
    end
 | 
			
		||||
  end if CGI.const_defined?(:MAX_MULTIPART_COUNT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_badbody   ## [ruby-dev:28470]
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'file1', :value=>_read('file1.html'),
 | 
			
		||||
       :filename=>'file1.html', :content_type=>'text/html'},
 | 
			
		||||
    ]
 | 
			
		||||
    _prepare(@data) do |input|
 | 
			
		||||
      input2 = input.sub(/--(\r\n)?\z/, "\r\n")
 | 
			
		||||
      assert input2 != input
 | 
			
		||||
      #p input2
 | 
			
		||||
      input2
 | 
			
		||||
    end
 | 
			
		||||
    ex = assert_raise(EOFError) do
 | 
			
		||||
      cgi = CGI.new
 | 
			
		||||
    end
 | 
			
		||||
    assert_equal("bad boundary end of body part", ex.message)
 | 
			
		||||
    #
 | 
			
		||||
    _prepare(@data) do |input|
 | 
			
		||||
      input2 = input.sub(/--(\r\n)?\z/, "")
 | 
			
		||||
      assert input2 != input
 | 
			
		||||
      #p input2
 | 
			
		||||
      input2
 | 
			
		||||
    end
 | 
			
		||||
    ex = assert_raise(EOFError) do
 | 
			
		||||
      cgi = CGI.new
 | 
			
		||||
    end
 | 
			
		||||
    assert_equal("bad content body", ex.message)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def test_cgi_multipart_quoteboundary  ## [JVN#84798830]
 | 
			
		||||
    @boundary = '(.|\n)*'
 | 
			
		||||
    @data = [
 | 
			
		||||
      {:name=>'hidden1', :value=>'foobar'},
 | 
			
		||||
      {:name=>'text1',   :value=>"\202\240\202\242\202\244\202\246\202\250"},
 | 
			
		||||
      {:name=>'file1',   :value=>_read('file1.html'),
 | 
			
		||||
       :filename=>'file1.html', :content_type=>'text/html'},
 | 
			
		||||
      {:name=>'image1',  :value=>_read('small.png'),
 | 
			
		||||
       :filename=>'small.png',  :content_type=>'image/png'},  # small image
 | 
			
		||||
    ]
 | 
			
		||||
    _prepare(@data)
 | 
			
		||||
    cgi = CGI.new
 | 
			
		||||
    assert_equal('file1.html', cgi['file1'].original_filename)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
 | 
			
		||||
  self.instance_methods.each do |method|
 | 
			
		||||
    private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
 | 
			
		||||
  end if ENV['TEST']
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										10
									
								
								test/cgi/testdata/file1.html
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								test/cgi/testdata/file1.html
									
										
									
									
										vendored
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <title>ムスカ大佐のひとりごと</title>
 | 
			
		||||
    <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <p>バカどもにはちょうどいい目くらましだ。</p>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								test/cgi/testdata/large.png
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/cgi/testdata/large.png
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								test/cgi/testdata/small.png
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/cgi/testdata/small.png
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue