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

  1. local _m = {}
  2. local bit = require("bit")
  3. --- @param path string
  4. --- @return string? data
  5. --- @return string? err
  6. _m.readfile = function(path)
  7. local f = io.open(path, "rb")
  8. if not f then
  9. return nil, "Couldn't open file"
  10. end
  11. local data = f:read("*all")
  12. f:close()
  13. return data
  14. end
  15. --- @param entry string
  16. --- @return string name the name of the form field.
  17. --- @return string? content_type the content type of the attached file, or nil if entry is not a file.
  18. --- @return string data the value of the entry.
  19. --- We are doing some severe assumptions here.
  20. --- - Firstly we assume that in the headers, any `CR` is always gonna be
  21. --- followed by a `LF` thus we only check for CR and advance by 2 when found
  22. --- - Secondly we assume that the only headers that can matter are
  23. --- `Content-Disposition` (for the field name) and `Content-Type` (if this is a
  24. --- file upload for the type of the uploaded file.
  25. --- - Thirdly we assume a field name can't contain a double quote, even escaped
  26. ---
  27. --- Additionaly if the entry is bogus or something goes wrong the function may
  28. --- abort and return `"", nil, ""` instead.
  29. _m.parse_form_entry = function(entry)
  30. -- If an entry is less than 32 bytes, it's bogus, skip
  31. if #entry < 32 then return "", nil, "" end
  32. local cursor = 3
  33. local name, ctype
  34. while true do
  35. local oldcursor = cursor
  36. if entry:sub(cursor, cursor) == "\r" then
  37. cursor = cursor + 2
  38. break
  39. elseif entry:sub(cursor, cursor+18) == 'Content-Disposition' then
  40. cursor = cursor + 38
  41. name = string.match(entry:sub(cursor), "^(.-)\"")
  42. cursor = cursor + #name + 1 --[[ the closing quote ]]
  43. -- Find the end of line
  44. while entry:sub(cursor, cursor) ~= "\r" do cursor = cursor + 1 end
  45. cursor = cursor + 2
  46. elseif entry:sub(cursor, cursor+11) == 'Content-Type' then
  47. cursor = cursor + 14
  48. ctype = string.match(entry:sub(cursor), "^(.-)\r")
  49. cursor = cursor + #ctype
  50. while entry:sub(cursor, cursor) ~= "\r" do cursor = cursor + 1 end
  51. cursor = cursor + 2 --[[ CRLF ]]
  52. end
  53. -- If we didn't advance the cursor, something went very wrong, skip
  54. if cursor == oldcursor then print(entry) return "", nil, "" end
  55. end
  56. return name, ctype, entry:sub(cursor, -1)
  57. end
  58. return _m