| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 | -- Some basic checksif mg.request_info.request_method ~= "POST" or mg.request_info.content_type:lower():sub(1,19) ~= 'multipart/form-data' then  mg.write("HTTP/1.0 400 OK\r\n")  mg.write("Connection: close\r\n")  mg.write("Content-Type: text/plain; charset=utf-8\r\n")  mg.write("Cache-Control: max-age=0, must-revalidate\r\n")  mg.write("\r\n")  mg.write("Bad request\r\n\r\n")  returnend-- HTTP headersmg.write("HTTP/1.0 200 OK\r\n")mg.write("Connection: close\r\n")mg.write("Content-Type: text/plain; charset=utf-8\r\n")mg.write("Cache-Control: max-age=0, must-revalidate\r\n")mg.write("\r\n")-- Which form sent the data?mg.write("Read POST data from " .. mg.request_info.http_headers.Referer .. ":\r\n\r\n")-- Count some data fieldslocal fields = 0local datasize = 0-- Read the entire body data (POST content) into "bdata" variable.-- Use a string builder pattern for performance reasonsstringtab = {}bdata = ""repeat  local add_data = mg.read()  if add_data then    stringtab[#stringtab+1] = add_data  enduntil (add_data == nil);bdata = table.concat(stringtab)stringtab = nil-- Get the boundary string.bs = "--" .. ((mg.request_info.content_type):upper():match("BOUNDARY=(.*)"));-- The POST data has to start with the boundary string.-- Check this and remove the starting boundary.if bdata:sub(1, #bs) ~= bs then  error "invalid format of POST data"endbdata = bdata:sub(#bs)-- The boundary now starts with CR LF.bs = "\r\n" .. bs-- Now loop through all the partswhile #bdata>4 do   -- Find the header of new part.   part_header_end = bdata:find("\r\n\r\n", 1, true)   -- Parse the header.   local form_field_name, file_name   h = bdata:sub(1, part_header_end+2)   for key,val in h:gmatch("([^%:\r\n]*)%s*%:%s*([^\r\n]*)\r\n") do      if key:upper() == "CONTENT-DISPOSITION" then          form_field_name = val:match('name=%"([^%"]*)%"')          file_name = val:match('filename=%"([^%"]*)%"')      end   end   -- Remove the header from "bdata".   bdata = bdata:sub(part_header_end+4)   -- Find the end of the body by locating the boundary string.   local part_body_end = bdata:find(bs, 1, true)   -- Isolate the content, and drop it from "bdata".   local form_field_value = bdata:sub(1,part_body_end-1)   bdata = bdata:sub(part_body_end+#bs)   -- Now the data (file content or field value) is isolated: We know form_field_name and form_field_value.   -- Here the script should do something useful with the data. This example just sends it back to the client.   if form_field_name then     mg.write("Field name: " .. form_field_name .. "\r\n")   end   local len = #form_field_value   mg.write("Field data length: " .. len .. "\r\n")   if file_name then     mg.write("File name: " .. file_name .. "\r\n")     mg.write("File content:\r\n")     local maxlen     if len>320 then maxlen=320 else maxlen=len end     for l=0,maxlen,16 do       for m=1,16 do         local b = form_field_value:byte(l+m)         if (b) then           mg.write(string.format("%02x ", b))         else           mg.write("   ")         end       end       mg.write(" -  " .. form_field_value:sub(l+1,l+16):gsub("[%c%z%s]", " ") .. "\r\n")     end     if maxlen<len then       mg.write(string.format("... (+ %u bytes)\r\n", len-maxlen))     end   else     -- not a file     if len<50 then       mg.write("Field value: " .. form_field_value .. "\r\n")     else       mg.write("Field value: " .. form_field_value:sub(1, 40) .. " .. (" .. len .. " bytes)\r\n")     end   end   mg.write("\r\n")   fields = fields + 1   datasize = datasize + lenendmg.write("Got " .. fields .. " input fields with " .. datasize .. " bytes total\r\n");
 |