+local ltn12 = require "luci.ltn12"
+local protocol = require "luci.http.protocol"
+local util = require "luci.util"
+local string = require "string"
+local coroutine = require "coroutine"
+
+local pairs, tostring, error = pairs, tostring, error
+
+--- LuCI Web Framework high-level HTTP functions.
+module "luci.http"
+
+context = util.threadlocal()
+
+Request = util.class()
+function Request.__init__(self, env, sourcein, sinkerr)
+ self.input = sourcein
+ self.error = sinkerr
+
+
+ -- File handler
+ self.filehandler = function() end
+
+ -- HTTP-Message table
+ self.message = {
+ env = env,
+ headers = {},
+ params = protocol.urldecode_params(env.QUERY_STRING or ""),
+ }
+
+ self.parsed_input = false
+end
+
+function Request.formvalue(self, name, noparse)
+ if not noparse and not self.parsed_input then
+ self:_parse_input()
+ end
+
+ if name then
+ return self.message.params[name]
+ else
+ return self.message.params
+ end
+end
+
+function Request.formvaluetable(self, prefix)
+ local vals = {}
+ prefix = prefix and prefix .. "." or "."
+
+ if not self.parsed_input then
+ self:_parse_input()
+ end
+
+ local void = self.message.params[nil]
+ for k, v in pairs(self.message.params) do
+ if k:find(prefix, 1, true) == 1 then
+ vals[k:sub(#prefix + 1)] = tostring(v)
+ end
+ end
+
+ return vals
+end
+
+function Request.content(self)
+ if not self.parsed_input then
+ self:_parse_input()
+ end
+
+ return self.message.content, self.message.content_length
+end
+
+function Request.getcookie(self, name)
+ local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";")
+ local p = ";" .. name .. "=(.-);"
+ local i, j, value = c:find(p)
+ return value and urldecode(value)
+end
+
+function Request.getenv(self, name)
+ if name then
+ return self.message.env[name]
+ else
+ return self.message.env
+ end
+end
+
+function Request.setfilehandler(self, callback)
+ self.filehandler = callback
+end
+
+function Request._parse_input(self)
+ protocol.parse_message_body(
+ self.input,
+ self.message,
+ self.filehandler
+ )
+ self.parsed_input = true
+end
+
+--- Close the HTTP-Connection.
+function close()
+ if not context.eoh then
+ context.eoh = true
+ coroutine.yield(3)
+ end
+
+ if not context.closed then
+ context.closed = true
+ coroutine.yield(5)
+ end
+end
+
+--- Return the request content if the request was of unknown type.
+-- @return HTTP request body
+-- @return HTTP request body length
+function content()
+ return context.request:content()
+end
+
+--- Get a certain HTTP input value or a table of all input values.
+-- @param name Name of the GET or POST variable to fetch
+-- @param noparse Don't parse POST data before getting the value
+-- @return HTTP input value or table of all input value
+function formvalue(name, noparse)
+ return context.request:formvalue(name, noparse)
+end
+
+--- Get a table of all HTTP input values with a certain prefix.
+-- @param prefix Prefix
+-- @return Table of all HTTP input values with given prefix
+function formvaluetable(prefix)
+ return context.request:formvaluetable(prefix)
+end