[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]