diff options
author | Sven Roederer <freifunk@it-solutions.geroedel.de> | 2019-07-01 21:52:07 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-07-19 20:14:22 +0200 |
commit | 8b8d83e42dd3d10d82e29a8614a7b3e3e94b16c6 (patch) | |
tree | 5e4009d43428da534cb231e91c68dd4eb2b3a258 /modules/luci-base | |
parent | 3b2a1e9e1129e77c4ebd5e7ace35653969f2d515 (diff) |
luci-base: move some generic classes into a separate luci-base-libs package
The new package luci-base-libs provides the modules that not strictly relate
to the web-interface of luci. By separating these libs they can be used by
other packages without having to install the web-components.
This change was inspired by providing a shell-only interface for 4MB-flash
devices, by keeping as much code common with a full install.
Signed-off-by: Sven Roederer <freifunk@it-solutions.geroedel.de>
Diffstat (limited to 'modules/luci-base')
-rw-r--r-- | modules/luci-base/luasrc/debug.lua | 37 | ||||
-rw-r--r-- | modules/luci-base/luasrc/http.lua | 554 | ||||
-rw-r--r-- | modules/luci-base/luasrc/http.luadoc | 260 | ||||
-rw-r--r-- | modules/luci-base/luasrc/ltn12.lua | 316 | ||||
-rw-r--r-- | modules/luci-base/luasrc/util.lua | 776 | ||||
-rw-r--r-- | modules/luci-base/luasrc/util.luadoc | 413 |
6 files changed, 0 insertions, 2356 deletions
diff --git a/modules/luci-base/luasrc/debug.lua b/modules/luci-base/luasrc/debug.lua deleted file mode 100644 index 8ff1bb6981..0000000000 --- a/modules/luci-base/luasrc/debug.lua +++ /dev/null @@ -1,37 +0,0 @@ -local debug = require "debug" -local io = require "io" -local collectgarbage, floor = collectgarbage, math.floor - -module "luci.debug" -__file__ = debug.getinfo(1, 'S').source:sub(2) - --- Enables the memory tracer with given flags and returns a function to disable the tracer again -function trap_memtrace(flags, dest) - flags = flags or "clr" - local tracefile = io.open(dest or "/tmp/memtrace", "w") - local peak = 0 - - local function trap(what, line) - local info = debug.getinfo(2, "Sn") - local size = floor(collectgarbage("count")) - if size > peak then - peak = size - end - if tracefile then - tracefile:write( - "[", what, "] ", info.source, ":", (line or "?"), "\t", - (info.namewhat or ""), "\t", - (info.name or ""), "\t", - size, " (", peak, ")\n" - ) - end - end - - debug.sethook(trap, flags) - - return function() - debug.sethook() - tracefile:close() - end -end - diff --git a/modules/luci-base/luasrc/http.lua b/modules/luci-base/luasrc/http.lua deleted file mode 100644 index 20b55f2854..0000000000 --- a/modules/luci-base/luasrc/http.lua +++ /dev/null @@ -1,554 +0,0 @@ --- Copyright 2008 Steven Barth <steven@midlink.org> --- Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io> --- Licensed to the public under the Apache License 2.0. - -local util = require "luci.util" -local coroutine = require "coroutine" -local table = require "table" -local lhttp = require "lucihttp" -local nixio = require "nixio" -local ltn12 = require "luci.ltn12" - -local table, ipairs, pairs, type, tostring, tonumber, error = - table, ipairs, pairs, type, tostring, tonumber, error - -module "luci.http" - -HTTP_MAX_CONTENT = 1024*100 -- 100 kB maximum content size - -context = util.threadlocal() - -Request = util.class() -function Request.__init__(self, env, sourcein, sinkerr) - self.input = sourcein - self.error = sinkerr - - - -- File handler nil by default to let .content() work - self.filehandler = nil - - -- HTTP-Message table - self.message = { - env = env, - headers = {}, - params = 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) - return lhttp.header_attribute("cookie; " .. (self:getenv("HTTP_COOKIE") or ""), name) -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 - - if not self.parsed_input then - return - end - - -- If input has already been parsed then uploads are stored as unlinked - -- temporary files pointed to by open file handles in the parameter - -- value table. Loop all params, and invoke the file callback for any - -- param with an open file handle. - local name, value - for name, value in pairs(self.message.params) do - if type(value) == "table" then - while value.fd do - local data = value.fd:read(1024) - local eof = (not data or data == "") - - callback(value, data, eof) - - if eof then - value.fd:close() - value.fd = nil - end - end - end - end -end - -function Request._parse_input(self) - parse_message_body( - self.input, - self.message, - self.filehandler - ) - self.parsed_input = true -end - -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 - -function content() - return context.request:content() -end - -function formvalue(name, noparse) - return context.request:formvalue(name, noparse) -end - -function formvaluetable(prefix) - return context.request:formvaluetable(prefix) -end - -function getcookie(name) - return context.request:getcookie(name) -end - --- or the environment table itself. -function getenv(name) - return context.request:getenv(name) -end - -function setfilehandler(callback) - return context.request:setfilehandler(callback) -end - -function header(key, value) - if not context.headers then - context.headers = {} - end - context.headers[key:lower()] = value - coroutine.yield(2, key, value) -end - -function prepare_content(mime) - if not context.headers or not context.headers["content-type"] then - if mime == "application/xhtml+xml" then - if not getenv("HTTP_ACCEPT") or - not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then - mime = "text/html; charset=UTF-8" - end - header("Vary", "Accept") - end - header("Content-Type", mime) - end -end - -function source() - return context.request.input -end - -function status(code, message) - code = code or 200 - message = message or "OK" - context.status = code - coroutine.yield(1, code, message) -end - --- This function is as a valid LTN12 sink. --- If the content chunk is nil this function will automatically invoke close. -function write(content, src_err) - if not content then - if src_err then - error(src_err) - else - close() - end - return true - elseif #content == 0 then - return true - else - if not context.eoh then - if not context.status then - status() - end - if not context.headers or not context.headers["content-type"] then - header("Content-Type", "text/html; charset=utf-8") - end - if not context.headers["cache-control"] then - header("Cache-Control", "no-cache") - header("Expires", "0") - end - if not context.headers["x-frame-options"] then - header("X-Frame-Options", "SAMEORIGIN") - end - if not context.headers["x-xss-protection"] then - header("X-XSS-Protection", "1; mode=block") - end - if not context.headers["x-content-type-options"] then - header("X-Content-Type-Options", "nosniff") - end - - context.eoh = true - coroutine.yield(3) - end - coroutine.yield(4, content) - return true - end -end - -function splice(fd, size) - coroutine.yield(6, fd, size) -end - -function redirect(url) - if url == "" then url = "/" end - status(302, "Found") - header("Location", url) - close() -end - -function build_querystring(q) - local s, n, k, v = {}, 1, nil, nil - - for k, v in pairs(q) do - s[n+0] = (n == 1) and "?" or "&" - s[n+1] = util.urlencode(k) - s[n+2] = "=" - s[n+3] = util.urlencode(v) - n = n + 4 - end - - return table.concat(s, "") -end - -urldecode = util.urldecode - -urlencode = util.urlencode - -function write_json(x) - util.serialize_json(x, write) -end - --- from given url or string. Returns a table with urldecoded values. --- Simple parameters are stored as string values associated with the parameter --- name within the table. Parameters with multiple values are stored as array --- containing the corresponding values. -function urldecode_params(url, tbl) - local parser, name - local params = tbl or { } - - parser = lhttp.urlencoded_parser(function (what, buffer, length) - if what == parser.TUPLE then - name, value = nil, nil - elseif what == parser.NAME then - name = lhttp.urldecode(buffer) - elseif what == parser.VALUE and name then - params[name] = lhttp.urldecode(buffer) or "" - end - - return true - end) - - if parser then - parser:parse((url or ""):match("[^?]*$")) - parser:parse(nil) - end - - return params -end - --- separated by "&". Tables are encoded as parameters with multiple values by --- repeating the parameter name with each value. -function urlencode_params(tbl) - local k, v - local n, enc = 1, {} - for k, v in pairs(tbl) do - if type(v) == "table" then - local i, v2 - for i, v2 in ipairs(v) do - if enc[1] then - enc[n] = "&" - n = n + 1 - end - - enc[n+0] = lhttp.urlencode(k) - enc[n+1] = "=" - enc[n+2] = lhttp.urlencode(v2) - n = n + 3 - end - else - if enc[1] then - enc[n] = "&" - n = n + 1 - end - - enc[n+0] = lhttp.urlencode(k) - enc[n+1] = "=" - enc[n+2] = lhttp.urlencode(v) - n = n + 3 - end - end - - return table.concat(enc, "") -end - --- 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 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 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) - - parser, err = lhttp.multipart_parser(msg.env.CONTENT_TYPE, function (what, buffer, length) - if what == parser.PART_INIT then - field = { } - - elseif what == parser.HEADER_NAME then - header = buffer:lower() - - elseif what == parser.HEADER_VALUE and header then - if header:lower() == "content-disposition" and - lhttp.header_attribute(buffer, nil) == "form-data" - 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.headers[header] = buffer - else - field.headers = { [header] = buffer } - end - - elseif what == parser.PART_BEGIN then - return not field.file - - elseif what == parser.PART_DATA and field.name and length > 0 then - if field.file then - if file_cb then - file_cb(field, buffer, false) - msg.params[field.name] = msg.params[field.name] or field - else - if not field.fd then - field.fd = nixio.mkstemp(field.name) - end - - if field.fd then - field.fd:write(buffer) - msg.params[field.name] = msg.params[field.name] or field - end - end - else - field.value = buffer - end - - elseif what == parser.PART_END and field.name then - if field.file and msg.params[field.name] then - if file_cb then - file_cb(field, "", true) - elseif field.fd then - field.fd:seek(0, "set") - end - else - 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 - - elseif what == parser.ERROR then - err = buffer - end - - return true - end, HTTP_MAX_CONTENT) - - return ltn12.pump.all(src, function (chunk) - len = len + (chunk and #chunk or 0) - - if maxlen and len > maxlen + 2 then - return nil, "Message body size exceeds Content-Length" - end - - if not parser or not parser:parse(chunk) then - return nil, err - end - - return true - end) -end - --- 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. -function urldecode_message_body(src, msg) - local err, name, value, parser - local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil) - - parser = lhttp.urlencoded_parser(function (what, buffer, length) - if what == parser.TUPLE then - name, value = nil, nil - elseif what == parser.NAME then - name = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) - elseif what == parser.VALUE and name then - 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, HTTP_MAX_CONTENT) - - return ltn12.pump.all(src, function (chunk) - len = len + (chunk and #chunk or 0) - - if maxlen and len > maxlen + 2 then - return nil, "Message body size exceeds Content-Length" - elseif len > HTTP_MAX_CONTENT then - return nil, "Message body size exceeds maximum allowed length" - end - - if not parser or not parser:parse(chunk) then - return nil, err - end - - return true - end) -end - --- This function will examine the Content-Type within the given message object --- to select the appropriate content decoder. --- Currently the application/x-www-urlencoded and application/form-data --- mime types are supported. If the encountered content encoding can't be --- 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) - if msg.env.CONTENT_LENGTH or msg.env.REQUEST_METHOD == "POST" then - local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil) - - -- 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) - - 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 - if type(filecb) == "function" then - local meta = { - name = "raw", - encoding = msg.env.CONTENT_TYPE - } - sink = function( chunk ) - if chunk then - return filecb(meta, chunk, false) - else - return filecb(meta, nil, true) - end - end - -- ... else append to .content - else - msg.content = "" - msg.content_length = 0 - - sink = function( chunk ) - if chunk then - if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then - msg.content = msg.content .. chunk - msg.content_length = msg.content_length + #chunk - return true - else - return nil, "POST data exceeds maximum allowed length" - end - end - return true - end - end - - -- Pump data... - while true do - local ok, err = ltn12.pump.step( src, sink ) - - if not ok and err then - return nil, err - elseif not ok then -- eof - return true - end - end - - return true - end - - return false -end diff --git a/modules/luci-base/luasrc/http.luadoc b/modules/luci-base/luasrc/http.luadoc deleted file mode 100644 index 8f6f380d8b..0000000000 --- a/modules/luci-base/luasrc/http.luadoc +++ /dev/null @@ -1,260 +0,0 @@ ----[[ -LuCI Web Framework high-level HTTP functions. -]] -module "luci.http" - ----[[ -Close the HTTP-Connection. - -@class function -@name close -]] - ----[[ -Return the request content if the request was of unknown type. - -@class function -@name content -@return HTTP request body -@return HTTP request body length -]] - ----[[ -Get a certain HTTP input value or a table of all input values. - -@class function -@name formvalue -@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 -]] - ----[[ -Get a table of all HTTP input values with a certain prefix. - -@class function -@name formvaluetable -@param prefix Prefix -@return Table of all HTTP input values with given prefix -]] - ----[[ -Get the value of a certain HTTP-Cookie. - -@class function -@name getcookie -@param name Cookie Name -@return String containing cookie data -]] - ----[[ -Get the value of a certain HTTP environment variable -or the environment table itself. - -@class function -@name getenv -@param name Environment variable -@return HTTP environment value or environment table -]] - ----[[ -Set a handler function for incoming user file uploads. - -@class function -@name setfilehandler -@param callback Handler function -]] - ----[[ -Send a HTTP-Header. - -@class function -@name header -@param key Header key -@param value Header value -]] - ----[[ -Set the mime type of following content data. - -@class function -@name prepare_content -@param mime Mimetype of following content -]] - ----[[ -Get the RAW HTTP input source - -@class function -@name source -@return HTTP LTN12 source -]] - ----[[ -Set the HTTP status code and status message. - -@class function -@name status -@param code Status code -@param message Status message -]] - ----[[ -Send a chunk of content data to the client. - -This function is as a valid LTN12 sink. -If the content chunk is nil this function will automatically invoke close. - -@class function -@name write -@param content Content chunk -@param src_err Error object from source (optional) -@see close -]] - ----[[ -Splice data from a filedescriptor to the client. - -@class function -@name splice -@param fp File descriptor -@param size Bytes to splice (optional) -]] - ----[[ -Redirects the client to a new URL and closes the connection. - -@class function -@name redirect -@param url Target URL -]] - ----[[ -Create a querystring out of a table of key - value pairs. - -@class function -@name build_querystring -@param table Query string source table -@return Encoded HTTP query string -]] - ----[[ -Return the URL-decoded equivalent of a string. - -@class function -@name urldecode -@param str URL-encoded string -@param no_plus Don't decode + to " " -@return URL-decoded string -@see urlencode -]] - ----[[ -Return the URL-encoded equivalent of a string. - -@class function -@name urlencode -@param str Source string -@return URL-encoded string -@see urldecode -]] - ----[[ -Send the given data as JSON encoded string. - -@class function -@name write_json -@param data Data to send -]] - ----[[ -Extract and split urlencoded data pairs, separated bei either "&" or ";" -from given url or string. Returns a table with urldecoded values. - -Simple parameters are stored as string values associated with the parameter -name within the table. Parameters with multiple values are stored as array -containing the corresponding values. - -@class function -@name urldecode_params -@param url The url or string which contains x-www-urlencoded form data -@param tbl Use the given table for storing values (optional) -@return Table containing the urldecoded parameters -@see urlencode_params -]] - ----[[ -Encode each key-value-pair in given table to x-www-urlencoded format, -separated by "&". - -Tables are encoded as parameters with multiple values by repeating the -parameter name with each value. - -@class function -@name urlencode_params -@param tbl Table with the values -@return String containing encoded values -@see urldecode_params -]] - ----[[ -Decode a mime encoded http message body with multipart/form-data 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 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 whether the current chunk is the last one (eof) - -@class function -@name mimedecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File callback function (optional) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Decode an urlencoded http message body with application/x-www-urlencoded -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. - -@class function -@name urldecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Try to extract and decode a http message body from the given ltn12 source. -This function will examine the Content-Type within the given message object -to select the appropriate content decoder. - -Currently the application/x-www-urlencoded and application/form-data -mime types are supported. If the encountered content encoding can't be -handled then the whole message body will be stored unaltered as "content" -property within the given message object. - -@class function -@name parse_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File data callback (optional, see mimedecode_message_body()) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] diff --git a/modules/luci-base/luasrc/ltn12.lua b/modules/luci-base/luasrc/ltn12.lua deleted file mode 100644 index 3a7268ccae..0000000000 --- a/modules/luci-base/luasrc/ltn12.lua +++ /dev/null @@ -1,316 +0,0 @@ ---[[ -LuaSocket 2.0.2 license -Copyright � 2004-2007 Diego Nehab - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -]]-- ---[[ - Changes made by LuCI project: - * Renamed to luci.ltn12 to avoid collisions with luasocket - * Added inline documentation -]]-- ------------------------------------------------------------------------------ --- LTN12 - Filters, sources, sinks and pumps. --- LuaSocket toolkit. --- Author: Diego Nehab --- RCS ID: $Id$ ------------------------------------------------------------------------------ - ------------------------------------------------------------------------------ --- Declare module ------------------------------------------------------------------------------ -local string = require("string") -local table = require("table") -local base = _G - --- See http://lua-users.org/wiki/FiltersSourcesAndSinks for design concepts -module("luci.ltn12") - -filter = {} -source = {} -sink = {} -pump = {} - --- 2048 seems to be better in windows... -BLOCKSIZE = 2048 -_VERSION = "LTN12 1.0.1" - ------------------------------------------------------------------------------ --- Filter stuff ------------------------------------------------------------------------------ - - --- by passing it each chunk and updating a context between calls. -function filter.cycle(low, ctx, extra) - base.assert(low) - return function(chunk) - local ret - ret, ctx = low(ctx, chunk, extra) - return ret - end -end - --- (thanks to Wim Couwenberg) -function filter.chain(...) - local n = table.getn(arg) - local top, index = 1, 1 - local retry = "" - return function(chunk) - retry = chunk and retry - while true do - if index == top then - chunk = arg[index](chunk) - if chunk == "" or top == n then return chunk - elseif chunk then index = index + 1 - else - top = top+1 - index = top - end - else - chunk = arg[index](chunk or "") - if chunk == "" then - index = index - 1 - chunk = retry - elseif chunk then - if index == n then return chunk - else index = index + 1 end - else base.error("filter returned inappropriate nil") end - end - end - end -end - ------------------------------------------------------------------------------ --- Source stuff ------------------------------------------------------------------------------ - - --- create an empty source -local function empty() - return nil -end - -function source.empty() - return empty -end - -function source.error(err) - return function() - return nil, err - end -end - -function source.file(handle, io_err) - if handle then - return function() - local chunk = handle:read(BLOCKSIZE) - if chunk and chunk:len() == 0 then chunk = nil end - if not chunk then handle:close() end - return chunk - end - else return source.error(io_err or "unable to open file") end -end - -function source.simplify(src) - base.assert(src) - return function() - local chunk, err_or_new = src() - src = err_or_new or src - if not chunk then return nil, err_or_new - else return chunk end - end -end - -function source.string(s) - if s then - local i = 1 - return function() - local chunk = string.sub(s, i, i+BLOCKSIZE-1) - i = i + BLOCKSIZE - if chunk ~= "" then return chunk - else return nil end - end - else return source.empty() end -end - -function source.rewind(src) - base.assert(src) - local t = {} - return function(chunk) - if not chunk then - chunk = table.remove(t) - if not chunk then return src() - else return chunk end - else - t[#t+1] = chunk - end - end -end - -function source.chain(src, f) - base.assert(src and f) - local last_in, last_out = "", "" - local state = "feeding" - local err - return function() - if not last_out then - base.error('source is empty!', 2) - end - while true do - if state == "feeding" then - last_in, err = src() - if err then return nil, err end - last_out = f(last_in) - if not last_out then - if last_in then - base.error('filter returned inappropriate nil') - else - return nil - end - elseif last_out ~= "" then - state = "eating" - if last_in then last_in = "" end - return last_out - end - else - last_out = f(last_in) - if last_out == "" then - if last_in == "" then - state = "feeding" - else - base.error('filter returned ""') - end - elseif not last_out then - if last_in then - base.error('filter returned inappropriate nil') - else - return nil - end - else - return last_out - end - end - end - end -end - --- Sources will be used one after the other, as if they were concatenated --- (thanks to Wim Couwenberg) -function source.cat(...) - local src = table.remove(arg, 1) - return function() - while src do - local chunk, err = src() - if chunk then return chunk end - if err then return nil, err end - src = table.remove(arg, 1) - end - end -end - ------------------------------------------------------------------------------ --- Sink stuff ------------------------------------------------------------------------------ - - -function sink.table(t) - t = t or {} - local f = function(chunk, err) - if chunk then t[#t+1] = chunk end - return 1 - end - return f, t -end - -function sink.simplify(snk) - base.assert(snk) - return function(chunk, err) - local ret, err_or_new = snk(chunk, err) - if not ret then return nil, err_or_new end - snk = err_or_new or snk - return 1 - end -end - -function sink.file(handle, io_err) - if handle then - return function(chunk, err) - if not chunk then - handle:close() - return 1 - else return handle:write(chunk) end - end - else return sink.error(io_err or "unable to open file") end -end - --- creates a sink that discards data -local function null() - return 1 -end - -function sink.null() - return null -end - -function sink.error(err) - return function() - return nil, err - end -end - -function sink.chain(f, snk) - base.assert(f and snk) - return function(chunk, err) - if chunk ~= "" then - local filtered = f(chunk) - local done = chunk and "" - while true do - local ret, snkerr = snk(filtered, err) - if not ret then return nil, snkerr end - if filtered == done then return 1 end - filtered = f(done) - end - else return 1 end - end -end - ------------------------------------------------------------------------------ --- Pump stuff ------------------------------------------------------------------------------ - - -function pump.step(src, snk) - local chunk, src_err = src() - local ret, snk_err = snk(chunk, src_err) - if chunk and ret then return 1 - else return nil, src_err or snk_err end -end - -function pump.all(src, snk, step) - base.assert(src and snk) - step = step or pump.step - while true do - local ret, err = step(src, snk) - if not ret then - if err then return nil, err - else return 1 end - end - end -end - diff --git a/modules/luci-base/luasrc/util.lua b/modules/luci-base/luasrc/util.lua deleted file mode 100644 index a30e8b72f3..0000000000 --- a/modules/luci-base/luasrc/util.lua +++ /dev/null @@ -1,776 +0,0 @@ --- Copyright 2008 Steven Barth <steven@midlink.org> --- Licensed to the public under the Apache License 2.0. - -local io = require "io" -local math = require "math" -local table = require "table" -local debug = require "debug" -local ldebug = require "luci.debug" -local string = require "string" -local coroutine = require "coroutine" -local tparser = require "luci.template.parser" -local json = require "luci.jsonc" -local lhttp = require "lucihttp" - -local _ubus = require "ubus" -local _ubus_connection = nil - -local getmetatable, setmetatable = getmetatable, setmetatable -local rawget, rawset, unpack, select = rawget, rawset, unpack, select -local tostring, type, assert, error = tostring, type, assert, error -local ipairs, pairs, next, loadstring = ipairs, pairs, next, loadstring -local require, pcall, xpcall = require, pcall, xpcall -local collectgarbage, get_memory_limit = collectgarbage, get_memory_limit - -module "luci.util" - --- --- Pythonic string formatting extension --- -getmetatable("").__mod = function(a, b) - local ok, res - - if not b then - return a - elseif type(b) == "table" then - local k, _ - for k, _ in pairs(b) do if type(b[k]) == "userdata" then b[k] = tostring(b[k]) end end - - ok, res = pcall(a.format, a, unpack(b)) - if not ok then - error(res, 2) - end - return res - else - if type(b) == "userdata" then b = tostring(b) end - - ok, res = pcall(a.format, a, b) - if not ok then - error(res, 2) - end - return res - end -end - - --- --- Class helper routines --- - --- Instantiates a class -local function _instantiate(class, ...) - local inst = setmetatable({}, {__index = class}) - - if inst.__init__ then - inst:__init__(...) - end - - return inst -end - --- The class object can be instantiated by calling itself. --- Any class functions or shared parameters can be attached to this object. --- Attaching a table to the class object makes this table shared between --- all instances of this class. For object parameters use the __init__ function. --- Classes can inherit member functions and values from a base class. --- Class can be instantiated by calling them. All parameters will be passed --- to the __init__ function of this class - if such a function exists. --- The __init__ function must be used to set any object parameters that are not shared --- with other objects of this class. Any return values will be ignored. -function class(base) - return setmetatable({}, { - __call = _instantiate, - __index = base - }) -end - -function instanceof(object, class) - local meta = getmetatable(object) - while meta and meta.__index do - if meta.__index == class then - return true - end - meta = getmetatable(meta.__index) - end - return false -end - - --- --- Scope manipulation routines --- - -coxpt = setmetatable({}, { __mode = "kv" }) - -local tl_meta = { - __mode = "k", - - __index = function(self, key) - local t = rawget(self, coxpt[coroutine.running()] - or coroutine.running() or 0) - return t and t[key] - end, - - __newindex = function(self, key, value) - local c = coxpt[coroutine.running()] or coroutine.running() or 0 - local r = rawget(self, c) - if not r then - rawset(self, c, { [key] = value }) - else - r[key] = value - end - end -} - --- the current active coroutine. A thread local store is private a table object --- whose values can't be accessed from outside of the running coroutine. -function threadlocal(tbl) - return setmetatable(tbl or {}, tl_meta) -end - - --- --- Debugging routines --- - -function perror(obj) - return io.stderr:write(tostring(obj) .. "\n") -end - -function dumptable(t, maxdepth, i, seen) - i = i or 0 - seen = seen or setmetatable({}, {__mode="k"}) - - for k,v in pairs(t) do - perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v)) - if type(v) == "table" and (not maxdepth or i < maxdepth) then - if not seen[v] then - seen[v] = true - dumptable(v, maxdepth, i+1, seen) - else - perror(string.rep("\t", i) .. "*** RECURSION ***") - end - end - end -end - - --- --- String and data manipulation routines --- - -function pcdata(value) - return value and tparser.pcdata(tostring(value)) -end - -function urlencode(value) - if value ~= nil then - local str = tostring(value) - return lhttp.urlencode(str, lhttp.ENCODE_IF_NEEDED + lhttp.ENCODE_FULL) - or str - end - return nil -end - -function urldecode(value, decode_plus) - if value ~= nil then - local flag = decode_plus and lhttp.DECODE_PLUS or 0 - local str = tostring(value) - return lhttp.urldecode(str, lhttp.DECODE_IF_NEEDED + flag) - or str - end - return nil -end - -function striptags(value) - return value and tparser.striptags(tostring(value)) -end - -function shellquote(value) - return string.format("'%s'", string.gsub(value or "", "'", "'\\''")) -end - --- for bash, ash and similar shells single-quoted strings are taken --- literally except for single quotes (which terminate the string) --- (and the exception noted below for dash (-) at the start of a --- command line parameter). -function shellsqescape(value) - local res - res, _ = string.gsub(value, "'", "'\\''") - return res -end - --- bash, ash and other similar shells interpret a dash (-) at the start --- of a command-line parameters as an option indicator regardless of --- whether it is inside a single-quoted string. It must be backlash --- escaped to resolve this. This requires in some funky special-case --- handling. It may actually be a property of the getopt function --- rather than the shell proper. -function shellstartsqescape(value) - res, _ = string.gsub(value, "^%-", "\\-") - return shellsqescape(res) -end - --- containing the resulting substrings. The optional max parameter specifies --- the number of bytes to process, regardless of the actual length of the given --- string. The optional last parameter, regex, specifies whether the separator --- sequence is interpreted as regular expression. --- pattern as regular expression (optional, default is false) -function split(str, pat, max, regex) - pat = pat or "\n" - max = max or #str - - local t = {} - local c = 1 - - if #str == 0 then - return {""} - end - - if #pat == 0 then - return nil - end - - if max == 0 then - return str - end - - repeat - local s, e = str:find(pat, c, not regex) - max = max - 1 - if s and max < 0 then - t[#t+1] = str:sub(c) - else - t[#t+1] = str:sub(c, s and s - 1) - end - c = e and e + 1 or #str + 1 - until not s or max < 0 - - return t -end - -function trim(str) - return (str:gsub("^%s*(.-)%s*$", "%1")) -end - -function cmatch(str, pat) - local count = 0 - for _ in str:gmatch(pat) do count = count + 1 end - return count -end - --- one token per invocation, the tokens are separated by whitespace. If the --- input value is a table, it is transformed into a string first. A nil value --- will result in a valid iterator which aborts with the first invocation. -function imatch(v) - if type(v) == "table" then - local k = nil - return function() - k = next(v, k) - return v[k] - end - - elseif type(v) == "number" or type(v) == "boolean" then - local x = true - return function() - if x then - x = false - return tostring(v) - end - end - - elseif type(v) == "userdata" or type(v) == "string" then - return tostring(v):gmatch("%S+") - end - - return function() end -end - --- value or 0 if the unit is unknown. Upper- or lower case is irrelevant. --- Recognized units are: --- o "y" - one year (60*60*24*366) --- o "m" - one month (60*60*24*31) --- o "w" - one week (60*60*24*7) --- o "d" - one day (60*60*24) --- o "h" - one hour (60*60) --- o "min" - one minute (60) --- o "kb" - one kilobyte (1024) --- o "mb" - one megabyte (1024*1024) --- o "gb" - one gigabyte (1024*1024*1024) --- o "kib" - one si kilobyte (1000) --- o "mib" - one si megabyte (1000*1000) --- o "gib" - one si gigabyte (1000*1000*1000) -function parse_units(ustr) - - local val = 0 - - -- unit map - local map = { - -- date stuff - y = 60 * 60 * 24 * 366, - m = 60 * 60 * 24 * 31, - w = 60 * 60 * 24 * 7, - d = 60 * 60 * 24, - h = 60 * 60, - min = 60, - - -- storage sizes - kb = 1024, - mb = 1024 * 1024, - gb = 1024 * 1024 * 1024, - - -- storage sizes (si) - kib = 1000, - mib = 1000 * 1000, - gib = 1000 * 1000 * 1000 - } - - -- parse input string - for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do - - local num = spec:gsub("[^0-9%.]+$","") - local spn = spec:gsub("^[0-9%.]+", "") - - if map[spn] or map[spn:sub(1,1)] then - val = val + num * ( map[spn] or map[spn:sub(1,1)] ) - else - val = val + num - end - end - - - return val -end - --- also register functions above in the central string class for convenience -string.pcdata = pcdata -string.striptags = striptags -string.split = split -string.trim = trim -string.cmatch = cmatch -string.parse_units = parse_units - - -function append(src, ...) - for i, a in ipairs({...}) do - if type(a) == "table" then - for j, v in ipairs(a) do - src[#src+1] = v - end - else - src[#src+1] = a - end - end - return src -end - -function combine(...) - return append({}, ...) -end - -function contains(table, value) - for k, v in pairs(table) do - if value == v then - return k - end - end - return false -end - --- Both table are - in fact - merged together. -function update(t, updates) - for k, v in pairs(updates) do - t[k] = v - end -end - -function keys(t) - local keys = { } - if t then - for k, _ in kspairs(t) do - keys[#keys+1] = k - end - end - return keys -end - -function clone(object, deep) - local copy = {} - - for k, v in pairs(object) do - if deep and type(v) == "table" then - v = clone(v, deep) - end - copy[k] = v - end - - return setmetatable(copy, getmetatable(object)) -end - - --- Serialize the contents of a table value. -function _serialize_table(t, seen) - assert(not seen[t], "Recursion detected.") - seen[t] = true - - local data = "" - local idata = "" - local ilen = 0 - - for k, v in pairs(t) do - if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then - k = serialize_data(k, seen) - v = serialize_data(v, seen) - data = data .. ( #data > 0 and ", " or "" ) .. - '[' .. k .. '] = ' .. v - elseif k > ilen then - ilen = k - end - end - - for i = 1, ilen do - local v = serialize_data(t[i], seen) - idata = idata .. ( #idata > 0 and ", " or "" ) .. v - end - - return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data -end - --- with loadstring(). -function serialize_data(val, seen) - seen = seen or setmetatable({}, {__mode="k"}) - - if val == nil then - return "nil" - elseif type(val) == "number" then - return val - elseif type(val) == "string" then - return "%q" % val - elseif type(val) == "boolean" then - return val and "true" or "false" - elseif type(val) == "function" then - return "loadstring(%q)" % get_bytecode(val) - elseif type(val) == "table" then - return "{ " .. _serialize_table(val, seen) .. " }" - else - return '"[unhandled data type:' .. type(val) .. ']"' - end -end - -function restore_data(str) - return loadstring("return " .. str)() -end - - --- --- Byte code manipulation routines --- - --- will be stripped before it is returned. -function get_bytecode(val) - local code - - if type(val) == "function" then - code = string.dump(val) - else - code = string.dump( loadstring( "return " .. serialize_data(val) ) ) - end - - return code -- and strip_bytecode(code) -end - --- numbers and debugging numbers will be discarded. Original version by --- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) -function strip_bytecode(code) - local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12) - local subint - if endian == 1 then - subint = function(code, i, l) - local val = 0 - for n = l, 1, -1 do - val = val * 256 + code:byte(i + n - 1) - end - return val, i + l - end - else - subint = function(code, i, l) - local val = 0 - for n = 1, l, 1 do - val = val * 256 + code:byte(i + n - 1) - end - return val, i + l - end - end - - local function strip_function(code) - local count, offset = subint(code, 1, size) - local stripped = { string.rep("\0", size) } - local dirty = offset + count - offset = offset + count + int * 2 + 4 - offset = offset + int + subint(code, offset, int) * ins - count, offset = subint(code, offset, int) - for n = 1, count do - local t - t, offset = subint(code, offset, 1) - if t == 1 then - offset = offset + 1 - elseif t == 4 then - offset = offset + size + subint(code, offset, size) - elseif t == 3 then - offset = offset + num - elseif t == 254 or t == 9 then - offset = offset + lnum - end - end - count, offset = subint(code, offset, int) - stripped[#stripped+1] = code:sub(dirty, offset - 1) - for n = 1, count do - local proto, off = strip_function(code:sub(offset, -1)) - stripped[#stripped+1] = proto - offset = offset + off - 1 - end - offset = offset + subint(code, offset, int) * int + int - count, offset = subint(code, offset, int) - for n = 1, count do - offset = offset + subint(code, offset, size) + size + int * 2 - end - count, offset = subint(code, offset, int) - for n = 1, count do - offset = offset + subint(code, offset, size) + size - end - stripped[#stripped+1] = string.rep("\0", int * 3) - return table.concat(stripped), offset - end - - return code:sub(1,12) .. strip_function(code:sub(13,-1)) -end - - --- --- Sorting iterator functions --- - -function _sortiter( t, f ) - local keys = { } - - local k, v - for k, v in pairs(t) do - keys[#keys+1] = k - end - - local _pos = 0 - - table.sort( keys, f ) - - return function() - _pos = _pos + 1 - if _pos <= #keys then - return keys[_pos], t[keys[_pos]], _pos - end - end -end - --- the provided callback function. -function spairs(t,f) - return _sortiter( t, f ) -end - --- The table pairs are sorted by key. -function kspairs(t) - return _sortiter( t ) -end - --- The table pairs are sorted by value. -function vspairs(t) - return _sortiter( t, function (a,b) return t[a] < t[b] end ) -end - - --- --- System utility functions --- - -function bigendian() - return string.byte(string.dump(function() end), 7) == 0 -end - -function exec(command) - local pp = io.popen(command) - local data = pp:read("*a") - pp:close() - - return data -end - -function execi(command) - local pp = io.popen(command) - - return pp and function() - local line = pp:read() - - if not line then - pp:close() - end - - return line - end -end - --- Deprecated -function execl(command) - local pp = io.popen(command) - local line = "" - local data = {} - - while true do - line = pp:read() - if (line == nil) then break end - data[#data+1] = line - end - pp:close() - - return data -end - - -local ubus_codes = { - "INVALID_COMMAND", - "INVALID_ARGUMENT", - "METHOD_NOT_FOUND", - "NOT_FOUND", - "NO_DATA", - "PERMISSION_DENIED", - "TIMEOUT", - "NOT_SUPPORTED", - "UNKNOWN_ERROR", - "CONNECTION_FAILED" -} - -local function ubus_return(...) - if select('#', ...) == 2 then - local rv, err = select(1, ...), select(2, ...) - if rv == nil and type(err) == "number" then - return nil, err, ubus_codes[err] - end - end - - return ... -end - -function ubus(object, method, data) - if not _ubus_connection then - _ubus_connection = _ubus.connect() - assert(_ubus_connection, "Unable to establish ubus connection") - end - - if object and method then - if type(data) ~= "table" then - data = { } - end - return ubus_return(_ubus_connection:call(object, method, data)) - elseif object then - return _ubus_connection:signatures(object) - else - return _ubus_connection:objects() - end -end - -function serialize_json(x, cb) - local js = json.stringify(x) - if type(cb) == "function" then - cb(js) - else - return js - end -end - - -function libpath() - return require "nixio.fs".dirname(ldebug.__file__) -end - -function checklib(fullpathexe, wantedlib) - local fs = require "nixio.fs" - local haveldd = fs.access('/usr/bin/ldd') - local haveexe = fs.access(fullpathexe) - if not haveldd or not haveexe then - return false - end - local libs = exec(string.format("/usr/bin/ldd %s", shellquote(fullpathexe))) - if not libs then - return false - end - for k, v in ipairs(split(libs)) do - if v:find(wantedlib) then - return true - end - end - return false -end - -------------------------------------------------------------------------------- --- Coroutine safe xpcall and pcall versions --- --- Encapsulates the protected calls with a coroutine based loop, so errors can --- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines --- yielding inside the call to pcall or xpcall. --- --- Authors: Roberto Ierusalimschy and Andre Carregal --- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fabio Mascarenhas --- --- Copyright 2005 - Kepler Project --- --- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $ -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- --- Implements xpcall with coroutines -------------------------------------------------------------------------------- -local coromap = setmetatable({}, { __mode = "k" }) - -local function handleReturnValue(err, co, status, ...) - if not status then - return false, err(debug.traceback(co, (...)), ...) - end - if coroutine.status(co) == 'suspended' then - return performResume(err, co, coroutine.yield(...)) - else - return true, ... - end -end - -function performResume(err, co, ...) - return handleReturnValue(err, co, coroutine.resume(co, ...)) -end - -local function id(trace, ...) - return trace -end - -function coxpcall(f, err, ...) - local current = coroutine.running() - if not current then - if err == id then - return pcall(f, ...) - else - if select("#", ...) > 0 then - local oldf, params = f, { ... } - f = function() return oldf(unpack(params)) end - end - return xpcall(f, err) - end - else - local res, co = pcall(coroutine.create, f) - if not res then - local newf = function(...) return f(...) end - co = coroutine.create(newf) - end - coromap[co] = current - coxpt[co] = coxpt[current] or current or 0 - return performResume(err, co, ...) - end -end - -function copcall(f, ...) - return coxpcall(f, id, ...) -end diff --git a/modules/luci-base/luasrc/util.luadoc b/modules/luci-base/luasrc/util.luadoc deleted file mode 100644 index 4ec68dd1ef..0000000000 --- a/modules/luci-base/luasrc/util.luadoc +++ /dev/null @@ -1,413 +0,0 @@ ----[[ -LuCI utility functions. -]] -module "luci.util" - ----[[ -Create a Class object (Python-style object model). - -The class object can be instantiated by calling itself. -Any class functions or shared parameters can be attached to this object. -Attaching a table to the class object makes this table shared between -all instances of this class. For object parameters use the __init__ function. -Classes can inherit member functions and values from a base class. -Class can be instantiated by calling them. All parameters will be passed -to the __init__ function of this class - if such a function exists. -The __init__ function must be used to set any object parameters that are not shared -with other objects of this class. Any return values will be ignored. - -@class function -@name class -@param base The base class to inherit from (optional) -@return A class object -@see instanceof -@see clone -]] - ----[[ -Test whether the given object is an instance of the given class. - -@class function -@name instanceof -@param object Object instance -@param class Class object to test against -@return Boolean indicating whether the object is an instance -@see class -@see clone -]] - ----[[ -Create a new or get an already existing thread local store associated with -the current active coroutine. - -A thread local store is private a table object -whose values can't be accessed from outside of the running coroutine. - -@class function -@name threadlocal -@return Table value representing the corresponding thread local store -]] - ----[[ -Write given object to stderr. - -@class function -@name perror -@param obj Value to write to stderr -@return Boolean indicating whether the write operation was successful -]] - ----[[ -Recursively dumps a table to stdout, useful for testing and debugging. - -@class function -@name dumptable -@param t Table value to dump -@param maxdepth Maximum depth -@return Always nil -]] - ----[[ -Create valid XML PCDATA from given string. - -@class function -@name pcdata -@param value String value containing the data to escape -@return String value containing the escaped data -]] - ----[[ -Decode an URL-encoded string - optionally decoding the "+" sign to space. - -@class function -@name urldecode -@param str Input string in x-www-urlencoded format -@param decode_plus Decode "+" signs to spaces if true (optional) -@return The decoded string -@see urlencode -]] - ----[[ -URL-encode given string. - -@class function -@name urlencode -@param str String to encode -@return String containing the encoded data -@see urldecode -]] - ----[[ -Strip HTML tags from given string. - -@class function -@name striptags -@param value String containing the HTML text -@return String with HTML tags stripped of -]] - ----[[ -Safely quote value for use in shell commands. - -@class function -@name shellquote -@param value String containing the value to quote -@return Single-quote enclosed string with embedded quotes escaped -]] - ----[[ -Splits given string on a defined separator sequence and return a table -containing the resulting substrings. - -The optional max parameter specifies the number of bytes to process, -regardless of the actual length of the given string. The optional last -parameter, regex, specifies whether the separator sequence is -nterpreted as regular expression. - -@class function -@name split -@param str String value containing the data to split up -@param pat String with separator pattern (optional, defaults to "\n") -@param max Maximum times to split (optional) -@param regex Boolean indicating whether to interpret the separator --- pattern as regular expression (optional, default is false) -@return Table containing the resulting substrings -]] - ----[[ -Remove leading and trailing whitespace from given string value. - -@class function -@name trim -@param str String value containing whitespace padded data -@return String value with leading and trailing space removed -]] - ----[[ -Count the occurrences of given substring in given string. - -@class function -@name cmatch -@param str String to search in -@param pattern String containing pattern to find -@return Number of found occurrences -]] - ----[[ -Return a matching iterator for the given value. - -The iterator will return one token per invocation, the tokens are separated by -whitespace. If the input value is a table, it is transformed into a string first. -A nil value will result in a valid iterator which aborts with the first invocation. - -@class function -@name imatch -@param val The value to scan (table, string or nil) -@return Iterator which returns one token per call -]] - ----[[ -Parse certain units from the given string and return the canonical integer -value or 0 if the unit is unknown. - -Upper- or lower case is irrelevant. -Recognized units are: - --- o "y" - one year (60*60*24*366) - o "m" - one month (60*60*24*31) - o "w" - one week (60*60*24*7) - o "d" - one day (60*60*24) - o "h" - one hour (60*60) - o "min" - one minute (60) - o "kb" - one kilobyte (1024) - o "mb" - one megabyte (1024*1024) - o "gb" - one gigabyte (1024*1024*1024) - o "kib" - one si kilobyte (1000) - o "mib" - one si megabyte (1000*1000) - o "gib" - one si gigabyte (1000*1000*1000) - -@class function -@name parse_units -@param ustr String containing a numerical value with trailing unit -@return Number containing the canonical value -]] - ----[[ -Appends numerically indexed tables or single objects to a given table. - -@class function -@name append -@param src Target table -@param ... Objects to insert -@return Target table -]] - ----[[ -Combines two or more numerically indexed tables and single objects into one table. - -@class function -@name combine -@param tbl1 Table value to combine -@param tbl2 Table value to combine -@param ... More tables to combine -@return Table value containing all values of given tables -]] - ----[[ -Checks whether the given table contains the given value. - -@class function -@name contains -@param table Table value -@param value Value to search within the given table -@return Number indicating the first index at which the given value occurs --- within table or false. -]] - ----[[ -Update values in given table with the values from the second given table. - -Both table are - in fact - merged together. - -@class function -@name update -@param t Table which should be updated -@param updates Table containing the values to update -@return Always nil -]] - ----[[ -Retrieve all keys of given associative table. - -@class function -@name keys -@param t Table to extract keys from -@return Sorted table containing the keys -]] - ----[[ -Clones the given object and return it's copy. - -@class function -@name clone -@param object Table value to clone -@param deep Boolean indicating whether to do recursive cloning -@return Cloned table value -]] - ----[[ -Recursively serialize given data to lua code, suitable for restoring -with loadstring(). - -@class function -@name serialize_data -@param val Value containing the data to serialize -@return String value containing the serialized code -@see restore_data -@see get_bytecode -]] - ----[[ -Restore data previously serialized with serialize_data(). - -@class function -@name restore_data -@param str String containing the data to restore -@return Value containing the restored data structure -@see serialize_data -@see get_bytecode -]] - ----[[ -Return the current runtime bytecode of the given data. The byte code -will be stripped before it is returned. - -@class function -@name get_bytecode -@param val Value to return as bytecode -@return String value containing the bytecode of the given data -]] - ----[[ -Strips unnecessary lua bytecode from given string. - -Information like line numbers and debugging numbers will be discarded. -Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) - -@class function -@name strip_bytecode -@param code String value containing the original lua byte code -@return String value containing the stripped lua byte code -]] - ----[[ -Return a key, value iterator which returns the values sorted according to -the provided callback function. - -@class function -@name spairs -@param t The table to iterate -@param f A callback function to decide the order of elements -@return Function value containing the corresponding iterator -]] - ----[[ -Return a key, value iterator for the given table. - -The table pairs are sorted by key. - -@class function -@name kspairs -@param t The table to iterate -@return Function value containing the corresponding iterator -]] - ----[[ -Return a key, value iterator for the given table. - -The table pairs are sorted by value. - -@class function -@name vspairs -@param t The table to iterate -@return Function value containing the corresponding iterator -]] - ----[[ -Test whether the current system is operating in big endian mode. - -@class function -@name bigendian -@return Boolean value indicating whether system is big endian -]] - ----[[ -Execute given commandline and gather stdout. - -@class function -@name exec -@param command String containing command to execute -@return String containing the command's stdout -]] - ----[[ -Return a line-buffered iterator over the output of given command. - -@class function -@name execi -@param command String containing the command to execute -@return Iterator -]] - ----[[ -Issue an ubus call. - -@class function -@name ubus -@param object String containing the ubus object to call -@param method String containing the ubus method to call -@param values Table containing the values to pass -@return Table containin the ubus result -]] - ----[[ -Convert data structure to JSON - -@class function -@name serialize_json -@param data The data to serialize -@param writer A function to write a chunk of JSON data (optional) -@return String containing the JSON if called without write callback -]] - ----[[ -Returns the absolute path to LuCI base directory. - -@class function -@name libpath -@return String containing the directory path -]] - ----[[ -This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function - -@class function -@name coxpcall -@param f Lua function to be called protected -@param err Custom error handler -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the return --- values of either the function or the error handler -]] - ----[[ -This is a coroutine-safe drop-in replacement for Lua's "pcall"-function - -@class function -@name copcall -@param f Lua function to be called protected -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the returns --- values of the function or the error object -]] - |