You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.2 KiB

local _m = {}
local bit = require("bit")
--- @param path string
--- @return string? data
--- @return string? err
_m.readfile = function(path)
local f = io.open(path, "rb")
if not f then
return nil, "Couldn't open file"
end
local data = f:read("*all")
f:close()
return data
end
--- @param entry string
--- @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 data the value of the entry.
--- We are doing some severe assumptions here.
--- - Firstly 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
--- - Secondly 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.
--- - Thirdly we assume a field name can't contain a double quote, even escaped
---
--- Additionaly if the entry is bogus or something goes wrong the function may
--- abort and return `"", nil, ""` instead.
_m.parse_form_entry = function(entry)
-- If an entry is less than 32 bytes, it's bogus, skip
if #entry < 32 then return "", nil, "" end
local cursor = 3
local name, ctype
while true do
local oldcursor = cursor
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:sub(cursor), "^(.-)\"")
cursor = cursor + #name + 1 --[[ the closing quote ]]
-- Find the end of line
while entry:sub(cursor, cursor) ~= "\r" do cursor = cursor + 1 end
cursor = cursor + 2
elseif entry:sub(cursor, cursor+11) == 'Content-Type' then
cursor = cursor + 14
ctype = string.match(entry:sub(cursor), "^(.-)\r")
cursor = cursor + #ctype
while entry:sub(cursor, cursor) ~= "\r" do cursor = cursor + 1 end
cursor = cursor + 2 --[[ CRLF ]]
end
-- If we didn't advance the cursor, something went very wrong, skip
if cursor == oldcursor then print(entry) return "", nil, "" end
end
return name, ctype, entry:sub(cursor, -1)
end
return _m