Class: Praxis::MultipartParser

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

Constant Summary collapse

EOL =
"\r\n"
MULTIPART_BOUNDARY =
"AaB03x"
MULTIPART =
%r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
TOKEN =
/[^\s()<>,;:\\"\/\[\]?=]+/
CONDISP =
/Content-Disposition:\s*#{TOKEN}\s*/i
DISPPARM =
/;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN})/
RFC2183 =
/^#{CONDISP}(#{DISPPARM})+$/i
BROKEN_QUOTED =
/^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
BROKEN_UNQUOTED =
/^#{CONDISP}.*;\sfilename=(#{TOKEN})/i
MULTIPART_CONTENT_TYPE =
/Content-Type: (.*)#{EOL}/ni
MULTIPART_CONTENT_DISPOSITION =
/Content-Disposition:.*\s+name="?([^\";]*)"?/ni
MULTIPART_CONTENT_ID =
/Content-ID:\s*([^#{EOL}]*)/ni
BUFSIZE =
16384

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(headers, body) ⇒ MultipartParser

Returns a new instance of MultipartParser.



26
27
28
29
30
31
32
33
34
# File 'lib/praxis/multipart/parser.rb', line 26

def initialize(headers, body)
  @headers = headers
  @io = StringIO.new
  Array(body).each do |chunk|
    @io << chunk
  end
  @io.rewind
  @parts = Hash.new
end

Class Method Details

.parse(headers, body) ⇒ Object



22
23
24
# File 'lib/praxis/multipart/parser.rb', line 22

def self.parse(headers,body)
  self.new(headers,body).parse
end

Instance Method Details

#parseObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/praxis/multipart/parser.rb', line 36

def parse
  return nil unless setup_parse

  @preamble = fast_forward_to_first_boundary

  loop do
    head, filename, content_type, name, body =
      get_current_head_and_filename_and_content_type_and_name_and_body

    # 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

    filename, data = get_data(filename, body, content_type, name, head)

    parsed_headers = head.split(EOL).each_with_object(Hash.new) do |line, hash|
      match = /(?<k>[^:]+): (?<v>.*)/.match(line)
      k = match[:k]
      v = match[:v]
      hash[k] = v
    end

    @parts[name] = MultipartPart.new(data, parsed_headers, filename: filename)

    # 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

  [@preamble, @parts]
end