3 local uci = require("uci")
4 local u_c = uci.cursor()
5 local tmppath = u_c.get("filemanager","config","tmpdir")
13 [206] = "Partial Content",
14 [301] = "Moved Permanently",
16 [304] = "Not Modified",
17 [400] = "Bad Request",
20 [405] = "Method Not Allowed",
21 [408] = "Request Time-out",
22 [411] = "Length Required",
23 [412] = "Precondition Failed",
24 [416] = "Requested range not satisfiable",
25 [500] = "Internal Server Error",
26 [503] = "Server Unavailable",
29 -- call this function passing an empy table. use that table for successive calls.
31 req.content_length = os.getenv("CONTENT_LENGTH")
32 req.request_method = os.getenv("REQUEST_METHOD")
33 if req.request_method == "POST" then
34 req.content_type, req.boundary = string.match(os.getenv("CONTENT_TYPE"),"^(multipart/form%-data); boundary=\"?(.+)\"?$")
35 req.boundary = "--" .. req.boundary
37 -- this is useful only if you have /tmp on tmpfs like in openwrt. otherwise can be set to ""
42 -- this function is needed to clean temp file since and hide implementation details
43 function _M.cleanup(req)
44 for k, v in pairs(req.post) do
45 for j, v in pairs(req.post[k]) do
46 if req.post[k][j].tempname then
47 os.remove(req.post[k][j].tempname) -- if file unused
48 os.remove("/tmp/" .. string.match(req.post[k][j].tempname,"^" .. req.tempdir .. "(.+)"))
55 -- return chunk (string), found (boolean)
56 local function chunkread(del)
58 local del = del or "\r\n"
60 buf = io.read(math.max(0,blocksize + #del - #prevbuf))
61 if prevbuf ~= "" then buf = prevbuf .. ( buf or "" ); prevbuf = "" end
62 if not buf then return end
64 s, e = string.find(buf,del,1,true)
67 prevbuf = string.sub(buf,e+1)
68 buf = string.sub(buf,1,s-1)
70 prevbuf = string.sub(buf,math.min(blocksize,#buf)+1)
71 buf = string.sub(buf,1,math.min(blocksize,#buf))
78 function _M.parse_request_body (req)
79 local chunk, found, type, tempname, tempfile
82 -- read first boundary line
83 chunk, found = chunkread(req.boundary)
84 chunk, found = chunkread("\r\n")
86 -- read part headers and get parameters value
88 chunk, found = chunkread("\r\n")
89 if not found then return 400, "Malformed POST. Missing Part Header or Part Header too long." end
90 string.gsub(chunk, ';%s*([^%s=]+)="(.-[^\\])"', function(k, v) param[k] = v end)
91 param.type = param.type or string.match(chunk, "^Content%-Type: (.+)$")
94 -- prepare file data read
95 if not param.name then return 400, "Malformed POST. Check Header parameters." end
97 param.tempname = req.tempdir .. string.match(os.tmpname(), "^/tmp(.+)")
98 tempfile = io.open(param.tempname, "w")
100 -- read part body content until boundary
102 chunk, found = chunkread("\r\n" .. req.boundary)
103 if not chunk then return 400, "Malformed POST. Incomplete Part received." end
104 tempfile:write(chunk)
105 param.size = param.size + #chunk
108 req.post[param.name] = req.post[param.name] or {}
109 table.insert(req.post[param.name], 1, param)
112 -- read after boundary. if CRLF ("") repeat. if "--" end POST processing
113 chunk, found = chunkread("\r\n")
116 if found and chunk == "--" then return 0, "OK" end
117 return 400, "Malformed POST. Boundary not properly ended with CRLF or --."