Class: Hyde::Util::MultipartParser

Inherits:
Object
  • Object
show all
Includes:
ParserSorting
Defined in:
lib/hyde/util/multipart.rb

Overview

A very naive implementation of a Multipart form parser.

Instance Method Summary collapse

Constructor Details

#initialize(io, boundary) ⇒ MultipartParser

Returns a new instance of MultipartParser.



45
46
47
48
49
50
# File 'lib/hyde/util/multipart.rb', line 45

def initialize(io, boundary)
  @input = io.is_a?(String) ? StringIO.new(io) : io
  @boundary = boundary
  @state = :idle
  @data = []
end

Instance Method Details

#parseArray<FormPart, FormFile>

Parse multipart formdata

Returns:



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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/hyde/util/multipart.rb', line 58

def parse
  return @data unless @data.empty?

  while (line = @input.gets)
    case @state
    when :idle # waiting for valid boundary
      if line == "--#{@boundary}\r\n"
        # transition to :headers on valid boundary
        @state = :headers
        @data.append(FormPart.new(*([nil] * 5), {}))
      end
    when :headers # after valid boundary - checking for headers
      if line == "\r\n"
        # prepare form field and transition to :data or :file
        @state = file?(@data[-1].headers) ? :file : :data
        if @state == :data
          setup_data_meta(@data[-1])
        else
          setup_file_meta(@data[-1])
        end
        next
      end
      push_header(line, @data[-1].headers)
    when :data, :file # after headers - processing form data
      if @data[-1].headers.empty?
        # transition to :idle on empty headers
        @state = :idle
        next
      end
      if ["--#{@boundary}\r\n", "--#{@boundary}--\r\n"].include? line
        # finalize and transition to either :headers or :idle
        if @state == :file
          @data[-1].tempfile.truncate(@data[-1].tempfile.size - 2)
          @data[-1].tempfile.close
        else
          @data[-1].data.delete_suffix! "\r\n"
        end
        @state = line == "--#{@boundary}\r\n" ? :headers : :idle
        @data.append(FormPart.new(*([nil] * 5), {}))
        next
      end
      if @state == :data
        @data[-1].data ||= ""
        @data[-1].data << line
      else
        @data[-1].tempfile << line
      end
    end
  end
  @state = :idle
  @data.pop
  @data.freeze
end

#to_hHash

Return a hash of current form. (equivalent to Query.parse but for multipart/form-data)

Returns:

  • (Hash)


116
117
118
# File 'lib/hyde/util/multipart.rb', line 116

def to_h
  flatten(sort(gen_hash(parse)))
end