diff options
-rw-r--r-- | lib/rack/multipart.rb | 31 | ||||
-rw-r--r-- | lib/rack/multipart/generator.rb | 4 | ||||
-rw-r--r-- | lib/rack/multipart/parser.rb | 29 | ||||
-rw-r--r-- | lib/rack/multipart/uploaded_file.rb | 3 |
4 files changed, 35 insertions, 32 deletions
diff --git a/lib/rack/multipart.rb b/lib/rack/multipart.rb index 5f4e3bf4..f88e4fd2 100644 --- a/lib/rack/multipart.rb +++ b/lib/rack/multipart.rb @@ -8,35 +8,7 @@ module Rack # # Usually, Rack::Request#POST takes care of calling this. module Multipart - autoload :UploadedFile, 'rack/multipart/uploaded_file' - autoload :Generator, 'rack/multipart/generator' - - EOL = "\r\n" MULTIPART_BOUNDARY = "AaB03x" - MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni - TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/ - CONDISP = /content-disposition:\s*#{TOKEN}\s*/i - VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/ - BROKEN_QUOTED = /^#{CONDISP}.*;\s*filename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i - BROKEN_UNQUOTED = /^#{CONDISP}.*;\s*filename=(#{TOKEN})/i - MULTIPART_CONTENT_TYPE = /content-type: (.*)#{EOL}/ni - MULTIPART_CONTENT_DISPOSITION = /content-disposition:.*;\s*name=(#{VALUE})/ni - MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni - # Updated definitions from RFC 2231 - ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]} - ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/ - SECTION = /\*[0-9]+/ - REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/ - REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/ - EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/ - EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/ - EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/ - EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/ - EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/ - EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/ - EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/ - DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/ - RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i class << self def parse_multipart(env, params = Rack::Utils.default_query_parser) @@ -60,9 +32,10 @@ module Rack Generator.new(params, first).dump end end - end end require_relative 'request' unless defined?(Rack::Request) require_relative 'multipart/parser' +require_relative 'multipart/uploaded_file' unless defined?(Rack::Multipart::UploadedFile) +require_relative 'multipart/generator' unless defined?(Rack::Multipart::Generator) diff --git a/lib/rack/multipart/generator.rb b/lib/rack/multipart/generator.rb index fdad3406..f871bd36 100644 --- a/lib/rack/multipart/generator.rb +++ b/lib/rack/multipart/generator.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true -require_relative '../multipart' module Rack module Multipart class Generator + + require_relative '../multipart' unless defined?(Rack::Multipart) + def initialize(params, first = true) @params, @first = params, first diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb index 9f2346a6..8c5f0a10 100644 --- a/lib/rack/multipart/parser.rb +++ b/lib/rack/multipart/parser.rb @@ -3,7 +3,6 @@ require 'strscan' require_relative '../utils' -require_relative '../multipart' unless defined?(Rack::Multipart) module Rack module Multipart @@ -13,7 +12,35 @@ module Rack # that ends early. class EmptyContentError < ::EOFError; end + EOL = "\r\n" + MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni + TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/ + CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i + VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/ + BROKEN_QUOTED = /^#{CONDISP}.*;\s*filename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i + BROKEN_UNQUOTED = /^#{CONDISP}.*;\s*filename=(#{TOKEN})/i + MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni + MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni + MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni + # Updated definitions from RFC 2231 + ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]} + ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/ + SECTION = /\*[0-9]+/ + REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/ + REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/ + EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/ + EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/ + EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/ + EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/ + EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/ + EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/ + EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/ + DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/ + RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i + class Parser + require_relative '../multipart' unless defined?(Rack::Multipart) + BUFSIZE = 1_048_576 TEXT_PLAIN = "text/plain" TEMPFILE_FACTORY = lambda { |filename, content_type| diff --git a/lib/rack/multipart/uploaded_file.rb b/lib/rack/multipart/uploaded_file.rb index a8db0931..1134704b 100644 --- a/lib/rack/multipart/uploaded_file.rb +++ b/lib/rack/multipart/uploaded_file.rb @@ -2,11 +2,12 @@ require 'tempfile' require 'fileutils' -require_relative '../multipart' module Rack module Multipart class UploadedFile + require_relative '../multipart' unless defined?(Rack::Multipart) + # The filename, *not* including the path, of the "uploaded" file attr_reader :original_filename |