Module: Tep::Multipart

Defined in:
lib/tep/multipart.rb

Class Method Summary collapse

Class Method Details

.extract_boundary(content_type) ⇒ Object

Extract ‘boundary=…` from a Content-Type value. Handles quoted (`boundary=“x”`) and unquoted (`boundary=x;` or `boundary=x` at end of string).



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/tep/multipart.rb', line 63

def self.extract_boundary(content_type)
  at = Tep.str_find(content_type, "boundary=", 0)
  if at < 0
    return ""
  end
  rest = content_type[at + 9, content_type.length - at - 9]
  if rest.length > 0 && rest[0, 1] == "\""
    end_q = Tep.str_find(rest, "\"", 1)
    if end_q < 0
      return ""
    end
    return rest[1, end_q - 1]
  end
  semi = Tep.str_find(rest, ";", 0)
  if semi >= 0
    return rest[0, semi]
  end
  rest
end

.extract_field_name(headers) ⇒ Object

Extract the ‘name=“…”` value from a part’s headers blob. Returns “” when no name found.



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/tep/multipart.rb', line 85

def self.extract_field_name(headers)
  at = Tep.str_find(headers, "name=\"", 0)
  if at < 0
    return ""
  end
  start = at + 6
  end_q = Tep.str_find(headers, "\"", start)
  if end_q < 0
    return ""
  end
  headers[start, end_q - start]
end

.parse(body, content_type) ⇒ Object

Parse ‘body` against the boundary embedded in `content_type`. Returns an empty hash when the boundary can’t be extracted (defensive: caller already checked ‘req.multipart?`).



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/tep/multipart.rb', line 20

def self.parse(body, content_type)
  h = Tep.str_hash
  bnd = Tep::Multipart.extract_boundary(content_type)
  if bnd.length == 0
    return h
  end
  delim = "--" + bnd
  parts = body.split(delim)
  i = 1   # parts[0] is the prologue before the first delimiter
  while i < parts.length
    part = parts[i]
    # Terminator: a part that starts with "--" is the closing
    # boundary "--<bnd>--<crlf>"; nothing meaningful after it.
    if part.length >= 2 && part[0, 2] == "--"
      return h
    end
    # Strip the CRLF that follows every interior delimiter.
    if part.length >= 2 && part[0, 2] == "\r\n"
      part = part[2, part.length - 2]
    end
    # Strip the CRLF that precedes the next delimiter (every
    # interior part ends with \r\n before the next "--<bnd>").
    if part.length >= 2 && part[part.length - 2, 2] == "\r\n"
      part = part[0, part.length - 2]
    end
    sep = Tep.str_find(part, "\r\n\r\n", 0)
    if sep >= 0
      headers = part[0, sep]
      value   = part[sep + 4, part.length - sep - 4]
      name = Tep::Multipart.extract_field_name(headers)
      has_filename = Tep.str_find(headers, "filename=", 0) >= 0
      if name.length > 0 && !has_filename
        h[name] = value
      end
    end
    i += 1
  end
  h
end