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