Class: Rack::Multipart::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/multipart/parser.rb

Constant Summary collapse

BUFSIZE =
16384
DUMMY =
Struct.new(:parse).new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(boundary, io, content_length, env, tempfile, bufsize) ⇒ Parser

Returns a new instance of Parser.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rack/multipart/parser.rb', line 28

def initialize(boundary, io, content_length, env, tempfile, bufsize)
  @buf            = ""

  if @buf.respond_to? :force_encoding
    @buf.force_encoding Encoding::ASCII_8BIT
  end

  @params         = Utils::KeySpaceConstrainedParams.new
  @boundary       = "--#{boundary}"
  @io             = io
  @content_length = content_length
  @boundary_size  = Utils.bytesize(@boundary) + EOL.size
  @env = env
  @tempfile       = tempfile
  @bufsize        = bufsize

  if @content_length
    @content_length -= @boundary_size
  end

  @rx = /(?:#{EOL})?#{Regexp.quote(@boundary)}(#{EOL}|--)/n
  @full_boundary = @boundary + EOL
end

Class Method Details

.create(env) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rack/multipart/parser.rb', line 12

def self.create(env)
  return DUMMY unless env['CONTENT_TYPE'] =~ MULTIPART

  io = env['rack.input']
  io.rewind

  content_length = env['CONTENT_LENGTH']
  content_length = content_length.to_i if content_length

  tempfile = env['rack.multipart.tempfile_factory'] ||
    lambda { |filename, content_type| Tempfile.new(["RackMultipart", ::File.extname(filename)]) }
  bufsize = env['rack.multipart.buffer_size'] || BUFSIZE

  new($1, io, content_length, env, tempfile, bufsize)
end

Instance Method Details

#parseObject



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rack/multipart/parser.rb', line 52

def parse
  fast_forward_to_first_boundary

  opened_files = 0
  loop do

    head, filename, content_type, name, body =
      get_current_head_and_filename_and_content_type_and_name_and_body

    if Utils.multipart_part_limit > 0
      opened_files += 1 if filename
      raise MultipartPartLimitError, 'Maximum file multiparts in content reached' if opened_files >= Utils.multipart_part_limit
    end

    # Save the rest.
    if i = @buf.index(rx)
      body << @buf.slice!(0, i)
      @buf.slice!(0, @boundary_size+2)

      @content_length = -1  if $1 == "--"
    end

    get_data(filename, body, content_type, name, head) do |data|
      tag_multipart_encoding(filename, content_type, name, data)

      Utils.normalize_params(@params, name, data)
    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) || @content_length == -1
  end

  @io.rewind

  @params.to_params_hash
end