|
@ -67,20 +67,33 @@ end |
|
|
--- @return string name the name of the form field. |
|
|
--- @return string name the name of the form field. |
|
|
--- @return string? content_type the content type of the attached file, or nil if entry is not a file. |
|
|
--- @return string? content_type the content type of the attached file, or nil if entry is not a file. |
|
|
--- @return string data the value of the entry. |
|
|
--- @return string data the value of the entry. |
|
|
|
|
|
--- We are doing some severe assumptions here. |
|
|
|
|
|
--- - Firstly we assume that if the first line of a header doesn't start with |
|
|
|
|
|
--- `Content-Disposition`, it is invalid and we can ignore it. |
|
|
|
|
|
--- - Secondly we assume that in the headers, any `CR` is always gonna be |
|
|
|
|
|
--- followed by a `LF` thus we only check for CR and advance by 2 when found |
|
|
|
|
|
--- - Thirdly we assume that the only headers that can matter are |
|
|
|
|
|
--- `Content-Disposition` (for the field name) and `Content-Type` (if this is a |
|
|
|
|
|
--- file upload for the type of the uploaded file. |
|
|
|
|
|
--- - Fourthly we assume a field name can't contain a double quote |
|
|
_m.parse_form_entry = function(entry) |
|
|
_m.parse_form_entry = function(entry) |
|
|
local name, content_type, data |
|
|
|
|
|
local _, end_of_header = entry:find("\r\n\r\n") |
|
|
|
|
|
for dataline in entry:gmatch("(.-)\r\n") do |
|
|
|
|
|
if dataline:sub(1, 19) == "Content-Disposition" then |
|
|
|
|
|
name = dataline:match("name=\"(.*)\"") |
|
|
|
|
|
|
|
|
local cursor = 3 |
|
|
|
|
|
local name, ctype |
|
|
|
|
|
while true do |
|
|
|
|
|
if entry:sub(cursor, cursor) == "\r" then |
|
|
|
|
|
cursor = cursor + 2 |
|
|
|
|
|
break |
|
|
|
|
|
elseif entry:sub(cursor, cursor+18) == 'Content-Disposition' then |
|
|
|
|
|
cursor = cursor + 38 |
|
|
|
|
|
name = string.match(entry, "(.*)\"", cursor) |
|
|
|
|
|
cursor = cursor + #name + 1 --[[ the closing quote ]] + 2 --[[ CRLF ]] |
|
|
|
|
|
elseif entry:sub(cursor, cursor+11) == 'Content-Type' then |
|
|
|
|
|
cursor = cursor + 14 |
|
|
|
|
|
ctype = string.match(entry, "(.*)\r", cursor) |
|
|
|
|
|
cursor = cursor + #ctype + 2 --[[ CRLF ]] |
|
|
end |
|
|
end |
|
|
if dataline:sub(1, 12) == "Content-Type" then |
|
|
|
|
|
content_type = dataline:match("Content-Type: (.*)\r\n") |
|
|
|
|
|
end |
|
|
end |
|
|
if dataline == "" then break end |
|
|
|
|
|
end |
|
|
|
|
|
data = entry:sub(end_of_header + 1) |
|
|
|
|
|
return name, content_type, data |
|
|
|
|
|
|
|
|
return name, ctype, entry:sub(cursor, -1) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
return _m |
|
|
return _m |