module "luci.http"
-HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size
+HTTP_MAX_CONTENT = 1024*100 -- 100 kB maximum content size
context = util.threadlocal()
-- Content-Type. Stores all extracted data associated with its parameter name
-- in the params table within the given message object. Multiple parameter
-- values are stored as tables, ordinary ones as strings.
--- If an optional file callback function is given then it is feeded with the
+-- If an optional file callback function is given then it is fed with the
-- file contents chunk by chunk and only the extracted file name is stored
-- within the params table. The callback function will be called subsequently
-- with three arguments:
-- o Table containing decoded (name, file) and raw (headers) mime header data
-- o String value containing a chunk of the file data
--- o Boolean which indicates wheather the current chunk is the last one (eof)
+-- o Boolean which indicates whether the current chunk is the last one (eof)
function mimedecode_message_body(src, msg, file_cb)
local parser, header, field
local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil)
then
field.name = lhttp.header_attribute(buffer, "name")
field.file = lhttp.header_attribute(buffer, "filename")
+ field[1] = field.file
end
if field.headers then
field.fd:seek(0, "set")
end
else
- msg.params[field.name] = field.value or ""
+ local val = msg.params[field.name]
+
+ if type(val) == "table" then
+ val[#val+1] = field.value or ""
+ elseif val ~= nil then
+ msg.params[field.name] = { val, field.value or "" }
+ else
+ msg.params[field.name] = field.value or ""
+ end
end
field = nil
end
return true
- end)
+ end, HTTP_MAX_CONTENT)
return ltn12.pump.all(src, function (chunk)
len = len + (chunk and #chunk or 0)
if what == parser.TUPLE then
name, value = nil, nil
elseif what == parser.NAME then
- name = lhttp.urldecode(buffer)
+ name = lhttp.urldecode(buffer, lhttp.DECODE_PLUS)
elseif what == parser.VALUE and name then
- msg.params[name] = lhttp.urldecode(buffer) or ""
+ local val = msg.params[name]
+
+ if type(val) == "table" then
+ val[#val+1] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or ""
+ elseif val ~= nil then
+ msg.params[name] = { val, lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" }
+ else
+ msg.params[name] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or ""
+ end
elseif what == parser.ERROR then
err = buffer
end
return true
- end)
+ end, HTTP_MAX_CONTENT)
return ltn12.pump.all(src, function (chunk)
len = len + (chunk and #chunk or 0)
-- handled then the whole message body will be stored unaltered as "content"
-- property within the given message object.
function parse_message_body(src, msg, filecb)
- local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil)
-
- -- Is it multipart/mime ?
- if msg.env.REQUEST_METHOD == "POST" and
- ctype == "multipart/form-data"
- then
- return mimedecode_message_body(src, msg, filecb)
+ if msg.env.CONTENT_LENGTH or msg.env.REQUEST_METHOD == "POST" then
+ local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil)
- -- Is it application/x-www-form-urlencoded ?
- elseif msg.env.REQUEST_METHOD == "POST" and
- ctype == "application/x-www-form-urlencoded"
- then
- return urldecode_message_body(src, msg)
+ -- Is it multipart/mime ?
+ if ctype == "multipart/form-data" then
+ return mimedecode_message_body(src, msg, filecb)
+ -- Is it application/x-www-form-urlencoded ?
+ elseif ctype == "application/x-www-form-urlencoded" then
+ return urldecode_message_body(src, msg)
- -- Unhandled encoding
- -- If a file callback is given then feed it chunk by chunk, else
- -- store whole buffer in message.content
- else
+ end
+ -- Unhandled encoding
+ -- If a file callback is given then feed it chunk by chunk, else
+ -- store whole buffer in message.content
local sink
-- If we have a file callback then feed it
return true
end
+
+ return false
end