handle_form.lua 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. -- Some basic checks
  2. if mg.request_info.request_method ~= "POST" or mg.request_info.content_type:lower():sub(1,19) ~= 'multipart/form-data' then
  3. mg.write("HTTP/1.0 400 OK\r\n")
  4. mg.write("Connection: close\r\n")
  5. mg.write("Content-Type: text/plain; charset=utf-8\r\n")
  6. mg.write("Cache-Control: max-age=0, must-revalidate\r\n")
  7. mg.write("\r\n")
  8. mg.write("Bad request\r\n\r\n")
  9. return
  10. end
  11. -- HTTP headers
  12. mg.write("HTTP/1.0 200 OK\r\n")
  13. mg.write("Connection: close\r\n")
  14. mg.write("Content-Type: text/plain; charset=utf-8\r\n")
  15. mg.write("Cache-Control: max-age=0, must-revalidate\r\n")
  16. mg.write("\r\n")
  17. -- Which form sent the data?
  18. mg.write("Read POST data from " .. mg.request_info.http_headers.Referer .. ":\r\n\r\n")
  19. -- Count some data fields
  20. local fields = 0
  21. local datasize = 0
  22. -- Read the entire body data (POST content) into "bdata" variable.
  23. -- Use a string builder pattern for performance reasons
  24. stringtab = {}
  25. bdata = ""
  26. repeat
  27. local add_data = mg.read()
  28. if add_data then
  29. stringtab[#stringtab+1] = add_data
  30. end
  31. until (add_data == nil);
  32. bdata = table.concat(stringtab)
  33. stringtab = nil
  34. -- Get the boundary string.
  35. bs = "--" .. ((mg.request_info.content_type):match("boundary=(.*)"));
  36. -- The POST data has to start with the boundary string.
  37. -- Check this and remove the starting boundary.
  38. if bdata:sub(1, #bs) ~= bs then
  39. error "invalid format of POST data"
  40. end
  41. bdata = bdata:sub(#bs)
  42. -- The boundary now starts with CR LF.
  43. bs = "\r\n" .. bs
  44. -- Now loop through all the parts
  45. while #bdata>4 do
  46. -- Find the header of new part.
  47. part_header_end = bdata:find("\r\n\r\n", 1, true)
  48. -- Parse the header.
  49. local form_field_name, file_name
  50. h = bdata:sub(1, part_header_end+2)
  51. for key,val in h:gmatch("([^%:\r\n]*)%s*%:%s*([^\r\n]*)\r\n") do
  52. if key:upper() == "CONTENT-DISPOSITION" then
  53. form_field_name = val:match('name=%"([^%"]*)%"')
  54. file_name = val:match('filename=%"([^%"]*)%"')
  55. end
  56. end
  57. -- Remove the header from "bdata".
  58. bdata = bdata:sub(part_header_end+4)
  59. -- Find the end of the body by locating the boundary string.
  60. local part_body_end = bdata:find(bs, 1, true)
  61. -- Isolate the content, and drop it from "bdata".
  62. local form_field_value = bdata:sub(1,part_body_end-1)
  63. bdata = bdata:sub(part_body_end+#bs)
  64. -- Now the data (file content or field value) is isolated: We know form_field_name and form_field_value.
  65. -- Here the script should do something useful with the data. This example just sends it back to the client.
  66. if form_field_name then
  67. mg.write("Field name: " .. form_field_name .. "\r\n")
  68. end
  69. if file_name then
  70. mg.write("File name: " .. file_name .. "\r\n")
  71. end
  72. local len = #form_field_value
  73. if len<50 then
  74. mg.write("Field value: " .. form_field_value .. "\r\n")
  75. else
  76. mg.write("Field value: " .. form_field_value:sub(1, 40) .. " .. (" .. len .. " bytes)\r\n")
  77. end
  78. mg.write("\r\n")
  79. fields = fields + 1
  80. datasize = datasize + len
  81. end
  82. mg.write("Got " .. fields .. " input fields with " .. datasize .. " bytes total\r\n");