@@ -57,12 +57,18 @@ def unescape(s, encoding = nil)
5757 end
5858 module_function :unescape
5959
60- DEFAULT_SEP = /[&;] */n
60+ DEFAULT_SEP = /& */n
6161
6262 class << self
6363 attr_accessor :key_space_limit
6464 attr_accessor :param_depth_limit
65- attr_accessor :multipart_part_limit
65+ attr_accessor :multipart_total_part_limit
66+ attr_accessor :multipart_file_limit
67+
68+ # multipart_part_limit is the original name of multipart_file_limit, but
69+ # the limit only counts parts with filenames.
70+ alias multipart_part_limit multipart_file_limit
71+ alias multipart_part_limit = multipart_file_limit =
6672 end
6773
6874 # The default number of bytes to allow parameter keys to take up.
@@ -73,11 +79,15 @@ class << self
7379 # being too deep. This helps prevent SystemStackErrors
7480 self . param_depth_limit = 100
7581
76- # The maximum number of parts a request can contain. Accepting too many part
82+ # The maximum number of file parts a request can contain. Accepting too many parts
7783 # can lead to the server running out of file handles.
7884 # Set to `0` for no limit.
7985 # FIXME: RACK_MULTIPART_LIMIT was introduced by mistake and it will be removed in 1.7.0
80- self . multipart_part_limit = ( ENV [ 'RACK_MULTIPART_PART_LIMIT' ] || ENV [ 'RACK_MULTIPART_LIMIT' ] || 128 ) . to_i
86+ self . multipart_file_limit = ( ENV [ 'RACK_MULTIPART_FILE_LIMIT' ] || ENV [ 'RACK_MULTIPART_PART_LIMIT' ] || ENV [ 'RACK_MULTIPART_LIMIT' ] || 128 ) . to_i
87+
88+ # The maximum total number of parts a request can contain. Accepting too
89+ # many can lead to excessive memory use and parsing time.
90+ self . multipart_total_part_limit = ( ENV [ 'RACK_MULTIPART_TOTAL_PART_LIMIT' ] || 4096 ) . to_i
8191
8292 # Stolen from Mongrel, with some small modifications:
8393 # Parses a query string by breaking it up at the '&'
@@ -203,7 +213,7 @@ def build_nested_query(value, prefix = nil)
203213 module_function :build_nested_query
204214
205215 def q_values ( q_value_header )
206- q_value_header . to_s . split ( / \s *, \s */ ) . map do |part |
216+ q_value_header . to_s . split ( "," ) . each ( & :strip! ) . map do |part |
207217 value , parameters = part . split ( /\s *;\s */ , 2 )
208218 quality = 1.0
209219 if md = /\A q=([\d .]+)/ . match ( parameters )
@@ -393,6 +403,9 @@ def rfc2822(time)
393403 end
394404 module_function :rfc2822
395405
406+ RFC2822_DAY_NAME = defined? ( Time ::RFC2822_DAY_NAME ) ? Time ::RFC2822_DAY_NAME : [ "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" ]
407+ RFC2822_MONTH_NAME = defined? ( Time ::RFC2822_MONTH_NAME ) ? Time ::RFC2822_MONTH_NAME : [ "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" ]
408+
396409 # Modified version of stdlib time.rb Time#rfc2822 to use '%d-%b-%Y' instead
397410 # of '% %b %Y'.
398411 # It assumes that the time is in GMT to comply to the RFC 2109.
@@ -401,10 +414,9 @@ def rfc2822(time)
401414 # that I'm certain someone implemented only that option.
402415 # Do not use %a and %b from Time.strptime, it would use localized names for
403416 # weekday and month.
404- #
405417 def rfc2109 ( time )
406- wday = Time :: RFC2822_DAY_NAME [ time . wday ]
407- mon = Time :: RFC2822_MONTH_NAME [ time . mon - 1 ]
418+ wday = RFC2822_DAY_NAME [ time . wday ]
419+ mon = RFC2822_MONTH_NAME [ time . mon - 1 ]
408420 time . strftime ( "#{ wday } , %d-#{ mon } -%Y %H:%M:%S GMT" )
409421 end
410422 module_function :rfc2109
@@ -418,17 +430,18 @@ def byte_ranges(env, size)
418430 return nil unless http_range && http_range =~ /bytes=([^;]+)/
419431 ranges = [ ]
420432 $1. split ( /,\s */ ) . each do |range_spec |
421- return nil unless range_spec =~ /(\d *)-(\d *)/
422- r0 , r1 = $1, $2
423- if r0 . empty?
424- return nil if r1 . empty?
433+ return nil unless range_spec . include? ( '-' )
434+ range = range_spec . split ( '-' )
435+ r0 , r1 = range [ 0 ] , range [ 1 ]
436+ if r0 . nil? || r0 . empty?
437+ return nil if r1 . nil?
425438 # suffix-byte-range-spec, represents trailing suffix of file
426439 r0 = size - r1 . to_i
427440 r0 = 0 if r0 < 0
428441 r1 = size - 1
429442 else
430443 r0 = r0 . to_i
431- if r1 . empty ?
444+ if r1 . nil ?
432445 r1 = size - 1
433446 else
434447 r1 = r1 . to_i
@@ -438,6 +451,10 @@ def byte_ranges(env, size)
438451 end
439452 ranges << ( r0 ..r1 ) if r0 <= r1
440453 end
454+
455+ total_size = ranges . reduce ( 0 ) { |sum , range | sum + range . size }
456+ return [ ] if total_size > size
457+
441458 ranges
442459 end
443460 module_function :byte_ranges
0 commit comments