ruby-changes:34311
From: xibbar <ko1@a...>
Date: Tue, 10 Jun 2014 13:30:01 +0900 (JST)
Subject: [ruby-changes:34311] xibbar:r46392 (trunk): * lib/cgi/core.rb: Provide a mechanism to specify the
xibbar 2014-06-10 13:29:49 +0900 (Tue, 10 Jun 2014) New Revision: 46392 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46392 Log: * lib/cgi/core.rb: Provide a mechanism to specify the max_multipart_length of multipart data. [Feature #8370] patch by Leif Eriksen <leif.eriksen.au@g...> Modified files: trunk/ChangeLog trunk/lib/cgi/core.rb trunk/test/cgi/test_cgi_multipart.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 46391) +++ ChangeLog (revision 46392) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Jun 10 13:20:14 2014 Takeyuki FUJIOKA <xibbar@r...> + + * lib/cgi/core.rb: Provide a mechanism to specify the + max_multipart_length of multipart data. + [Feature #8370] patch by Leif Eriksen <leif.eriksen.au@g...> + Tue Jun 10 10:57:07 2014 Nobuyoshi Nakada <nobu@r...> * lib/csv.rb (CSV#<<): honor explicity given encoding. based on Index: lib/cgi/core.rb =================================================================== --- lib/cgi/core.rb (revision 46391) +++ lib/cgi/core.rb (revision 46392) @@ -389,9 +389,6 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L389 # Maximum content length of post data ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024 - # Maximum content length of multipart data - MAX_MULTIPART_LENGTH = 128 * 1024 * 1024 - # Maximum number of request parameters when multipart MAX_MULTIPART_COUNT = 128 @@ -644,8 +641,9 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L641 # Reads query parameters in the @params field, and cookies into @cookies. def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and - %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE']) - raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > MAX_MULTIPART_LENGTH + %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE']) + current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length + raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length boundary = $1.dup @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) @@ -751,6 +749,16 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L749 # Return the accept character set for this CGI instance. attr_reader :accept_charset + # @@max_multipart_length is the maximum length of multipart data. + # The default value is 128 * 1024 * 1024 bytes + # + # The default can be set to something else in the CGI constructor, + # via the :max_multipart_length key in the option hash. + # + # See CGI.new documentation. + # + @@max_multipart_length= 128 * 1024 * 1024 + # Create a new CGI instance. # # :call-seq: @@ -764,7 +772,7 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L772 # +options_hash+ form, since it also allows you specify the charset you # will accept. # <tt>options_hash</tt>:: - # A Hash that recognizes two options: + # A Hash that recognizes three options: # # <tt>:accept_charset</tt>:: # specifies encoding of received query string. If omitted, @@ -793,6 +801,18 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L801 # "html4Fr":: HTML 4.0 with Framesets # "html5":: HTML 5 # + # <tt>:max_multipart_length</tt>:: + # Specifies maximum length of multipart data. Can be an Integer scalar or + # a lambda, that will be evaluated when the request is parsed. This + # allows more complex logic to be set when determining whether to accept + # multipart data (e.g. consult a registered users upload allowance) + # + # Default is 128 * 1024 * 1024 bytes + # + # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar + # + # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda + # # <tt>block</tt>:: # If provided, the block is called when an invalid encoding is # encountered. For example: @@ -810,7 +830,10 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L830 # CGI locations, which varies according to the REQUEST_METHOD. def initialize(options = {}, &block) # :yields: name, value @accept_charset_error_block = block_given? ? block : nil - @options={:accept_charset=>@@accept_charset} + @options={ + :accept_charset=>@@accept_charset, + :max_multipart_length=>@@max_multipart_length + } case options when Hash @options.merge!(options) @@ -818,6 +841,7 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L841 @options[:tag_maker]=options end @accept_charset=@options[:accept_charset] + @max_multipart_length=@options[:max_multipart_length] if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE") Apache.request.setup_cgi_env end @@ -855,5 +879,3 @@ class CGI https://github.com/ruby/ruby/blob/trunk/lib/cgi/core.rb#L879 end end # class CGI - - Index: test/cgi/test_cgi_multipart.rb =================================================================== --- test/cgi/test_cgi_multipart.rb (revision 46391) +++ test/cgi/test_cgi_multipart.rb (revision 46392) @@ -145,12 +145,14 @@ class CGIMultipartTest < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/cgi/test_cgi_multipart.rb#L145 $stdin = tmpfile end - def _test_multipart + def _test_multipart(cgi_options={}) caller(0).find {|s| s =~ /in `test_(.*?)'/ } #testname = $1 #$stderr.puts "*** debug: testname=#{testname.inspect}" _prepare(@data) - cgi = RUBY_VERSION>="1.9" ? CGI.new(:accept_charset=>"UTF-8") : CGI.new + options = {:accept_charset=>"UTF-8"} + options.merge! cgi_options + cgi = RUBY_VERSION>="1.9" ? CGI.new(options) : CGI.new expected_names = @data.collect{|hash| hash[:name] }.sort assert_equal(expected_names, cgi.params.keys.sort) threshold = 1024*10 @@ -243,16 +245,29 @@ class CGIMultipartTest < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/cgi/test_cgi_multipart.rb#L245 {: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() + _test_multipart(:max_multipart_length=>2 * 1024) # set via simple scalar 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) + end + + + def test_cgi_multipart_maxmultipartlength_lambda + @data = [ + {:name=>'image1', :value=>_read('large.png'), + :filename=>'large.png', :content_type=>'image/png'}, # large image + ] + begin + ex = assert_raise(StandardError) do + _test_multipart(:max_multipart_length=>lambda{2*1024}) # set via lambda + end + assert_equal("too large multipart data.", ex.message) + ensure + end + end def test_cgi_multipart_maxmultipartcount -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/