class Rack::Multipart::Parser
Rack::Multipart::Parser handles parsing of multipart/form-data requests.
File Parameter Contents
When processing file uploads, the parser returns a hash containing information about uploaded files. For file parameters, the hash includes:
-
:filename- The original filename, already URL decoded by the parser -
:type- The content type of the uploaded file -
:name- The parameter name from the form -
:tempfile- A Tempfile object containing the uploaded data -
:head- The raw header content for this part
Constants
- BUFSIZE
- CHARSET
- CONTENT_DISPOSITION_MAX_BYTES
- CONTENT_DISPOSITION_MAX_PARAMS
- EMPTY
- MultipartInfo
- REENCODE_DUMMY_ENCODINGS
- TEMPFILE_FACTORY
- TEXT_PLAIN
Attributes
Public Class Methods
# File lib/rack/multipart/parser.rb, line 260
def initialize(boundary, tempfile, bufsize, query_parser)
@query_parser = query_parser
@params = query_parser.make_params
@bufsize = bufsize
@state = :FAST_FORWARD
@mime_index = 0
@body_retained = nil
@retained_size = 0
@total_bytes_read = (0 if PARSER_BYTESIZE_LIMIT)
@content_disposition_quoted_escapes = 0
@collector = Collector.new tempfile
@sbuf = StringScanner.new("".b)
@body_regex = /(?:#{EOL}|\A)--#{Regexp.quote(boundary)}(?:#{EOL}|--)/m
@body_regex_at_end = /#{@body_regex}\z/m
@end_boundary_size = boundary.bytesize + 4 # (-- at start, -- at finish)
@rx_max_size = boundary.bytesize + 6 # (\r\n-- at start, either \r\n or -- at finish)
@head_regex = /(.*?#{EOL})#{EOL}/m
end # File lib/rack/multipart/parser.rb, line 137
def self.parse(io, content_length, content_type, tmpfile, bufsize, qp)
return EMPTY if 0 == content_length
boundary = parse_boundary content_type
return EMPTY unless boundary
if PARSER_BYTESIZE_LIMIT && content_length && content_length > PARSER_BYTESIZE_LIMIT
raise Error, "multipart Content-Length #{content_length} exceeds limit of #{PARSER_BYTESIZE_LIMIT} bytes"
end
if boundary.length > 70
# RFC 1521 Section 7.2.1 imposes a 70 character maximum for the boundary.
# Most clients use no more than 55 characters.
raise BoundaryTooLongError, "multipart boundary size too large (#{boundary.length} characters)"
end
io = BoundedIO.new(io, content_length) if content_length
parser = new(boundary, tmpfile, bufsize, qp)
parser.parse(io)
parser.result
end # File lib/rack/multipart/parser.rb, line 122
def self.parse_boundary(content_type)
return unless content_type
data = content_type.match(MULTIPART)
return unless data
unless data[1].empty?
raise Error, "whitespace between boundary parameter name and equal sign"
end
if data.post_match.match?(/boundary\s*=/i)
raise BoundaryTooLongError, "multiple boundary parameters found in multipart content type"
end
data[2]
end Public Instance Methods
# File lib/rack/multipart/parser.rb, line 281
def parse(io)
@total_bytes_read &&= nil if io.is_a?(BoundedIO)
outbuf = String.new
read_data(io, outbuf)
loop do
status =
case @state
when :FAST_FORWARD
handle_fast_forward
when :CONSUME_TOKEN
handle_consume_token
when :MIME_HEAD
handle_mime_head
when :MIME_BODY
handle_mime_body
else # when :DONE
return
end
read_data(io, outbuf) if status == :want_read
end
end # File lib/rack/multipart/parser.rb, line 305
def result
@collector.each do |part|
part.get_data do |data|
tag_multipart_encoding(part.filename, part.content_type, part.name, data)
name, data = handle_dummy_encoding(part.name, data)
@query_parser.normalize_params(@params, name, data)
end
end
MultipartInfo.new @params.to_params_hash, @collector.find_all(&:file?).map(&:body)
end
© 2007-2021 Leah Neukirchen
Licensed under the MIT License.