def query_from_multipart( headers, input, boundary, content_length )
params = Hash.new([])
boundary = "--" + boundary
buf = ""
bufsize = 10 * 1024
input.binmode
boundary_size = boundary.size + EOL.size
content_length -= boundary_size
status = input.read boundary_size
if status == nil then
raise EOFError, "no content body"
elsif boundary + EOL != status
raise EOFError, "bad content body"
end
until content_length == -1
head = nil
tmp = nil
if content_length > MEM_CONTENT_LENGTH
require "tempfile"
tmp = Tempfile.new("CGIKit")
tmp.binmode
data = TempfileByteData.new(tmp)
else
data = ByteData.new
end
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
if (not head) and /#{EOL}#{EOL}/n.match(buf)
buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
head = $1.dup
""
end
next
end
if head and ( (EOL + boundary + EOL).size < buf.size )
data << buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
end
if bufsize < content_length then
c = input.read(bufsize) or ''
else
c = input.read(content_length) or ''
end
buf += c
content_length -= c.size
end
buf = buf.sub(/\A((?:.|\n)*?)(?:#{EOL})?#{boundary}(#{EOL}|--)/n) do
data << $1
if "--" == $2
content_length = -1
end
""
end
/Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
filename = ($1 || "").dup
if /Mac/ni.match(headers['HTTP_USER_AGENT']) and
/Mozilla/ni.match(headers['HTTP_USER_AGENT']) and
(not /MSIE/ni.match(headers['HTTP_USER_AGENT']))
filename = Utilities.unescape_url filename
end
data.path = filename
/Content-Type: ([^\r\n]*)/ni.match(head)
if $1 then
data.content_type = $1.dup
else
data = data.to_s
end
/Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
name = $1.dup
if params.has_key? name then
params[name].push data
else
params[name] = [data]
end
end
params
end