Class Index [+]

Quicksearch

Rack::Utils::Multipart

A multipart form data parser, adapted from IOWA.

Usually, Rack::Request#POST takes care of calling this.

Constants

EOL
(Not documented)

Public Class Methods

parse_multipart(env) click to toggle source

(Not documented)

     # File lib/rack/utils.rb, line 294
294:       def self.parse_multipart(env)
295:         unless env['CONTENT_TYPE'] =~
296:             %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
297:           nil
298:         else
299:           boundary = "--#{$1}"
300: 
301:           params = {}
302:           buf = ""
303:           content_length = env['CONTENT_LENGTH'].to_i
304:           input = env['rack.input']
305:           input.rewind
306: 
307:           boundary_size = boundary.size + EOL.size
308:           bufsize = 16384
309: 
310:           content_length -= boundary_size
311: 
312:           read_buffer = ''
313: 
314:           status = input.read(boundary_size, read_buffer)
315:           raise EOFError, "bad content body"  unless status == boundary + EOL
316: 
317:           rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n
318: 
319:           loop {
320:             head = nil
321:             body = ''
322:             filename = content_type = name = nil
323: 
324:             until head && buf =~ rx
325:               if !head && i = buf.index(EOL+EOL)
326:                 head = buf.slice!(0, i+2) # First \r\n
327:                 buf.slice!(0, 2)          # Second \r\n
328: 
329:                 filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
330:                 content_type = head[/Content-Type: (.*)#{EOL}/ni, 1]
331:                 name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
332: 
333:                 if content_type || filename
334:                   body = Tempfile.new("RackMultipart")
335:                   body.binmode  if body.respond_to?(:binmode)
336:                 end
337: 
338:                 next
339:               end
340: 
341:               # Save the read body part.
342:               if head && (boundary_size+4 < buf.size)
343:                 body << buf.slice!(0, buf.size - (boundary_size+4))
344:               end
345: 
346:               c = input.read(bufsize < content_length ? bufsize : content_length, read_buffer)
347:               raise EOFError, "bad content body"  if c.nil? || c.empty?
348:               buf << c
349:               content_length -= c.size
350:             end
351: 
352:             # Save the rest.
353:             if i = buf.index(rx)
354:               body << buf.slice!(0, i)
355:               buf.slice!(0, boundary_size+2)
356: 
357:               content_length = -1  if $1 == "--"
358:             end
359: 
360:             if filename == ""
361:               # filename is blank which means no file has been selected
362:               data = nil
363:             elsif filename
364:               body.rewind
365: 
366:               # Take the basename of the upload's original filename.
367:               # This handles the full Windows paths given by Internet Explorer
368:               # (and perhaps other broken user agents) without affecting
369:               # those which give the lone filename.
370:               filename =~ /^(?:.*[:\\\/])?(.*)/m
371:               filename = $1
372: 
373:               data = {:filename => filename, :type => content_type,
374:                       :name => name, :tempfile => body, :head => head}
375:             elsif !filename && content_type
376:               body.rewind
377:               
378:               # Generic multipart cases, not coming from a form
379:               data = {:type => content_type,
380:                       :name => name, :tempfile => body, :head => head}
381:             else
382:               data = body
383:             end
384: 
385:             Utils.normalize_params(params, name, data) unless data.nil?
386: 
387:             break  if buf.empty? || content_length == -1
388:           }
389: 
390:           input.rewind
391: 
392:           params
393:         end
394:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.