summary refs log tree commit
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2015-08-28 14:28:52 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2015-08-28 14:28:52 -0700
commit360d374ab1a263fcf81a18d6e5ac74cccccbc7e9 (patch)
tree1bc52d596c25c5947f4317122959bb7f53154934
parent0f8ecc34faddab06bb4a5eb5dfa84cf3be565dcd (diff)
downloadrack-360d374ab1a263fcf81a18d6e5ac74cccccbc7e9.tar.gz
pull up one loop
-rw-r--r--lib/rack/multipart/parser.rb82
1 files changed, 49 insertions, 33 deletions
diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb
index dbe18e4c..a357a857 100644
--- a/lib/rack/multipart/parser.rb
+++ b/lib/rack/multipart/parser.rb
@@ -79,44 +79,51 @@ module Rack
         @bufsize        = bufsize
 
         @rx = /(?:#{EOL})?#{Regexp.quote(@boundary)}(#{EOL}|--)/n
-        @full_boundary = @boundary + EOL
+        @full_boundary = @boundary
+        @end_boundary = @boundary + '--'
       end
 
       def parse
-        fast_forward_to_first_boundary
+        state = :ff
 
         opened_files = []
+        tok = nil
         loop do
+          if state == :ff
+            tok = fast_forward_to_first_boundary
+            state = :not_ff if tok
+          else
+            break if tok == :END_BOUNDARY
+
+            # break if we're at the end of a buffer, but not if it is the end of a field
+            break if (@buf.empty? && tok != :BOUNDARY)
 
-          head, filename, content_type, name, body, file =
-            get_current_head_and_filename_and_content_type_and_name_and_body
+            head, filename, content_type, name, body, file =
+              get_current_head_and_filename_and_content_type_and_name_and_body
 
-          opened_files << file if file
+            opened_files << file if file
 
-          if Utils.multipart_part_limit > 0
-            if opened_files.length >= Utils.multipart_part_limit
-              opened_files.each(&:close)
-              raise MultipartPartLimitError, 'Maximum file multiparts in content reached'
+            if Utils.multipart_part_limit > 0
+              if opened_files.length >= Utils.multipart_part_limit
+                opened_files.each(&:close)
+                raise MultipartPartLimitError, 'Maximum file multiparts in content reached'
+              end
             end
-          end
 
-          should_break = false
-          # Save the rest.
-          if i = @buf.index(rx)
-            body << @buf.slice!(0, i)
-            @buf.slice!(0, @boundary_size+2)
+            # Save the rest.
+            if i = @buf.index(rx)
+              body << @buf.slice!(0, i)
+              @buf.slice!(0, 2) # Remove \r\n after the content
+            end
 
-            should_break = true if $1 == "--"
-          end
+            get_data(filename, body, content_type, name, head) do |data|
+              tag_multipart_encoding(filename, content_type, name, data)
 
-          get_data(filename, body, content_type, name, head) do |data|
-            tag_multipart_encoding(filename, content_type, name, data)
+              @query_parser.normalize_params(@params, name, data, @query_parser.param_depth_limit)
+            end
 
-            @query_parser.normalize_params(@params, name, data, @query_parser.param_depth_limit)
+            tok = consume_boundary
           end
-
-          # break if we're at the end of a buffer, but not if it is the end of a field
-          break if (@buf.empty? && $1 != EOL) || should_break
         end
 
         @io.rewind
@@ -129,20 +136,29 @@ module Rack
 
       def rx; @rx; end
 
+      def consume_boundary
+        while @buf.gsub!(/\A([^\n]*(?:\n|\Z))/, '')
+          read_buffer = $1
+          case read_buffer.strip
+          when full_boundary then return :BOUNDARY
+          when @end_boundary then return :END_BOUNDARY
+          end
+          return if @buf.empty?
+        end
+      end
+
       def fast_forward_to_first_boundary
-        loop do
-          content = @io.read(@bufsize)
-          handle_empty_content!(content) and return ""
+        content = @io.read(@bufsize)
+        handle_empty_content!(content) and return ""
 
-          @buf << content
+        @buf << content
 
-          while @buf.gsub!(/\A([^\n]*\n)/, '')
-            read_buffer = $1
-            return if read_buffer == full_boundary
-          end
+        tok = consume_boundary
+        return tok if tok
 
-          raise EOFError, "bad content body" if @buf.bytesize >= @bufsize
-        end
+        raise EOFError, "bad content body" if @buf.bytesize >= @bufsize
+
+        nil
       end
 
       def get_current_head_and_filename_and_content_type_and_name_and_body