summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxibbar <xibbar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-10 04:29:49 +0000
committerxibbar <xibbar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-10 04:29:49 +0000
commit5c99f241a0e8712e27fae013e2a6be46b136acf8 (patch)
tree1b85a7287b106ac11a445f64d1044451893d1b13
parentf9a5335ed4f84e6e3ed23cb92966a36101d9d149 (diff)
* 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@gmail.com> git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46392 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--lib/cgi/core.rb40
-rw-r--r--test/cgi/test_cgi_multipart.rb27
3 files changed, 58 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ac39d9913..6658fe5557 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Tue Jun 10 13:20:14 2014 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * 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@gmail.com>
+
Tue Jun 10 10:57:07 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/csv.rb (CSV#<<): honor explicity given encoding. based on
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
index b80e036a86..6fb4a8f997 100644
--- a/lib/cgi/core.rb
+++ b/lib/cgi/core.rb
@@ -389,9 +389,6 @@ class CGI
# 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
# 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
# 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
# +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
# "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
# 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
@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
end
end # class CGI
-
-
diff --git a/test/cgi/test_cgi_multipart.rb b/test/cgi/test_cgi_multipart.rb
index 7461faab23..989ac7aba8 100644
--- a/test/cgi/test_cgi_multipart.rb
+++ b/test/cgi/test_cgi_multipart.rb
@@ -145,12 +145,14 @@ class CGIMultipartTest < Test::Unit::TestCase
$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::TestCase
{: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
+ end
+ 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
- _set_const(CGI, :MAX_MULTIPART_LENGTH, original)
end
- end if CGI.const_defined?(:MAX_MULTIPART_LENGTH)
+ end
def test_cgi_multipart_maxmultipartcount