1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Licensed to the public under the Apache License 2.0.
4 local io = require "io"
5 local math = require "math"
6 local table = require "table"
7 local debug = require "debug"
8 local ldebug = require "luci.debug"
9 local string = require "string"
10 local coroutine = require "coroutine"
11 local tparser = require "luci.template.parser"
13 local _ubus = require "ubus"
14 local _ubus_connection = nil
16 local getmetatable, setmetatable = getmetatable, setmetatable
17 local rawget, rawset, unpack = rawget, rawset, unpack
18 local tostring, type, assert = tostring, type, assert
19 local ipairs, pairs, next, loadstring = ipairs, pairs, next, loadstring
20 local require, pcall, xpcall = require, pcall, xpcall
21 local collectgarbage, get_memory_limit = collectgarbage, get_memory_limit
23 --- LuCI utility functions.
27 -- Pythonic string formatting extension
29 getmetatable("").__mod = function(a, b)
32 elseif type(b) == "table" then
33 for k, _ in pairs(b) do if type(b[k]) == "userdata" then b[k] = tostring(b[k]) end end
34 return a:format(unpack(b))
36 if type(b) == "userdata" then b = tostring(b) end
43 -- Class helper routines
46 -- Instantiates a class
47 local function _instantiate(class, ...)
48 local inst = setmetatable({}, {__index = class})
57 --- Create a Class object (Python-style object model).
58 -- The class object can be instantiated by calling itself.
59 -- Any class functions or shared parameters can be attached to this object.
60 -- Attaching a table to the class object makes this table shared between
61 -- all instances of this class. For object parameters use the __init__ function.
62 -- Classes can inherit member functions and values from a base class.
63 -- Class can be instantiated by calling them. All parameters will be passed
64 -- to the __init__ function of this class - if such a function exists.
65 -- The __init__ function must be used to set any object parameters that are not shared
66 -- with other objects of this class. Any return values will be ignored.
67 -- @param base The base class to inherit from (optional)
68 -- @return A class object
72 return setmetatable({}, {
73 __call = _instantiate,
78 --- Test whether the given object is an instance of the given class.
79 -- @param object Object instance
80 -- @param class Class object to test against
81 -- @return Boolean indicating whether the object is an instance
84 function instanceof(object, class)
85 local meta = getmetatable(object)
86 while meta and meta.__index do
87 if meta.__index == class then
90 meta = getmetatable(meta.__index)
97 -- Scope manipulation routines
103 __index = function(self, key)
104 local t = rawget(self, coxpt[coroutine.running()]
105 or coroutine.running() or 0)
109 __newindex = function(self, key, value)
110 local c = coxpt[coroutine.running()] or coroutine.running() or 0
111 local r = rawget(self, c)
113 rawset(self, c, { [key] = value })
120 --- Create a new or get an already existing thread local store associated with
121 -- the current active coroutine. A thread local store is private a table object
122 -- whose values can't be accessed from outside of the running coroutine.
123 -- @return Table value representing the corresponding thread local store
124 function threadlocal(tbl)
125 return setmetatable(tbl or {}, tl_meta)
130 -- Debugging routines
133 --- Write given object to stderr.
134 -- @param obj Value to write to stderr
135 -- @return Boolean indicating whether the write operation was successful
137 return io.stderr:write(tostring(obj) .. "\n")
140 --- Recursively dumps a table to stdout, useful for testing and debugging.
141 -- @param t Table value to dump
142 -- @param maxdepth Maximum depth
143 -- @return Always nil
144 function dumptable(t, maxdepth, i, seen)
146 seen = seen or setmetatable({}, {__mode="k"})
148 for k,v in pairs(t) do
149 perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
150 if type(v) == "table" and (not maxdepth or i < maxdepth) then
153 dumptable(v, maxdepth, i+1, seen)
155 perror(string.rep("\t", i) .. "*** RECURSION ***")
163 -- String and data manipulation routines
166 --- Create valid XML PCDATA from given string.
167 -- @param value String value containing the data to escape
168 -- @return String value containing the escaped data
169 function pcdata(value)
170 return value and tparser.pcdata(tostring(value))
173 --- Strip HTML tags from given string.
174 -- @param value String containing the HTML text
175 -- @return String with HTML tags stripped of
176 function striptags(value)
177 return value and tparser.striptags(tostring(value))
180 --- Splits given string on a defined separator sequence and return a table
181 -- containing the resulting substrings. The optional max parameter specifies
182 -- the number of bytes to process, regardless of the actual length of the given
183 -- string. The optional last parameter, regex, specifies whether the separator
184 -- sequence is interpreted as regular expression.
185 -- @param str String value containing the data to split up
186 -- @param pat String with separator pattern (optional, defaults to "\n")
187 -- @param max Maximum times to split (optional)
188 -- @param regex Boolean indicating whether to interpret the separator
189 -- pattern as regular expression (optional, default is false)
190 -- @return Table containing the resulting substrings
191 function split(str, pat, max, regex)
211 local s, e = str:find(pat, c, not regex)
213 if s and max < 0 then
216 t[#t+1] = str:sub(c, s and s - 1)
218 c = e and e + 1 or #str + 1
219 until not s or max < 0
224 --- Remove leading and trailing whitespace from given string value.
225 -- @param str String value containing whitespace padded data
226 -- @return String value with leading and trailing space removed
228 return (str:gsub("^%s*(.-)%s*$", "%1"))
231 --- Count the occurences of given substring in given string.
232 -- @param str String to search in
233 -- @param pattern String containing pattern to find
234 -- @return Number of found occurences
235 function cmatch(str, pat)
237 for _ in str:gmatch(pat) do count = count + 1 end
241 --- Return a matching iterator for the given value. The iterator will return
242 -- one token per invocation, the tokens are separated by whitespace. If the
243 -- input value is a table, it is transformed into a string first. A nil value
244 -- will result in a valid interator which aborts with the first invocation.
245 -- @param val The value to scan (table, string or nil)
246 -- @return Iterator which returns one token per call
248 if type(v) == "table" then
255 elseif type(v) == "number" or type(v) == "boolean" then
264 elseif type(v) == "userdata" or type(v) == "string" then
265 return tostring(v):gmatch("%S+")
268 return function() end
271 --- Parse certain units from the given string and return the canonical integer
272 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
273 -- Recognized units are:
274 -- o "y" - one year (60*60*24*366)
275 -- o "m" - one month (60*60*24*31)
276 -- o "w" - one week (60*60*24*7)
277 -- o "d" - one day (60*60*24)
278 -- o "h" - one hour (60*60)
279 -- o "min" - one minute (60)
280 -- o "kb" - one kilobyte (1024)
281 -- o "mb" - one megabyte (1024*1024)
282 -- o "gb" - one gigabyte (1024*1024*1024)
283 -- o "kib" - one si kilobyte (1000)
284 -- o "mib" - one si megabyte (1000*1000)
285 -- o "gib" - one si gigabyte (1000*1000*1000)
286 -- @param ustr String containing a numerical value with trailing unit
287 -- @return Number containing the canonical value
288 function parse_units(ustr)
295 y = 60 * 60 * 24 * 366,
296 m = 60 * 60 * 24 * 31,
297 w = 60 * 60 * 24 * 7,
305 gb = 1024 * 1024 * 1024,
307 -- storage sizes (si)
310 gib = 1000 * 1000 * 1000
313 -- parse input string
314 for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
316 local num = spec:gsub("[^0-9%.]+$","")
317 local spn = spec:gsub("^[0-9%.]+", "")
319 if map[spn] or map[spn:sub(1,1)] then
320 val = val + num * ( map[spn] or map[spn:sub(1,1)] )
330 -- also register functions above in the central string class for convenience
331 string.pcdata = pcdata
332 string.striptags = striptags
335 string.cmatch = cmatch
336 string.parse_units = parse_units
339 --- Appends numerically indexed tables or single objects to a given table.
340 -- @param src Target table
341 -- @param ... Objects to insert
342 -- @return Target table
343 function append(src, ...)
344 for i, a in ipairs({...}) do
345 if type(a) == "table" then
346 for j, v in ipairs(a) do
356 --- Combines two or more numerically indexed tables and single objects into one table.
357 -- @param tbl1 Table value to combine
358 -- @param tbl2 Table value to combine
359 -- @param ... More tables to combine
360 -- @return Table value containing all values of given tables
361 function combine(...)
362 return append({}, ...)
365 --- Checks whether the given table contains the given value.
366 -- @param table Table value
367 -- @param value Value to search within the given table
368 -- @return Boolean indicating whether the given value occurs within table
369 function contains(table, value)
370 for k, v in pairs(table) do
378 --- Update values in given table with the values from the second given table.
379 -- Both table are - in fact - merged together.
380 -- @param t Table which should be updated
381 -- @param updates Table containing the values to update
382 -- @return Always nil
383 function update(t, updates)
384 for k, v in pairs(updates) do
389 --- Retrieve all keys of given associative table.
390 -- @param t Table to extract keys from
391 -- @return Sorted table containing the keys
395 for k, _ in kspairs(t) do
402 --- Clones the given object and return it's copy.
403 -- @param object Table value to clone
404 -- @param deep Boolean indicating whether to do recursive cloning
405 -- @return Cloned table value
406 function clone(object, deep)
409 for k, v in pairs(object) do
410 if deep and type(v) == "table" then
416 return setmetatable(copy, getmetatable(object))
420 --- Create a dynamic table which automatically creates subtables.
421 -- @return Dynamic Table
423 return setmetatable({}, { __index =
425 return rawget(tbl, key)
426 or rawget(rawset(tbl, key, dtable()), key)
432 -- Serialize the contents of a table value.
433 function _serialize_table(t, seen)
434 assert(not seen[t], "Recursion detected.")
441 for k, v in pairs(t) do
442 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
443 k = serialize_data(k, seen)
444 v = serialize_data(v, seen)
445 data = data .. ( #data > 0 and ", " or "" ) ..
446 '[' .. k .. '] = ' .. v
453 local v = serialize_data(t[i], seen)
454 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
457 return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
460 --- Recursively serialize given data to lua code, suitable for restoring
461 -- with loadstring().
462 -- @param val Value containing the data to serialize
463 -- @return String value containing the serialized code
466 function serialize_data(val, seen)
467 seen = seen or setmetatable({}, {__mode="k"})
471 elseif type(val) == "number" then
473 elseif type(val) == "string" then
475 elseif type(val) == "boolean" then
476 return val and "true" or "false"
477 elseif type(val) == "function" then
478 return "loadstring(%q)" % get_bytecode(val)
479 elseif type(val) == "table" then
480 return "{ " .. _serialize_table(val, seen) .. " }"
482 return '"[unhandled data type:' .. type(val) .. ']"'
486 --- Restore data previously serialized with serialize_data().
487 -- @param str String containing the data to restore
488 -- @return Value containing the restored data structure
489 -- @see serialize_data
491 function restore_data(str)
492 return loadstring("return " .. str)()
497 -- Byte code manipulation routines
500 --- Return the current runtime bytecode of the given data. The byte code
501 -- will be stripped before it is returned.
502 -- @param val Value to return as bytecode
503 -- @return String value containing the bytecode of the given data
504 function get_bytecode(val)
507 if type(val) == "function" then
508 code = string.dump(val)
510 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
513 return code -- and strip_bytecode(code)
516 --- Strips unnescessary lua bytecode from given string. Information like line
517 -- numbers and debugging numbers will be discarded. Original version by
518 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
519 -- @param code String value containing the original lua byte code
520 -- @return String value containing the stripped lua byte code
521 function strip_bytecode(code)
522 local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
525 subint = function(code, i, l)
528 val = val * 256 + code:byte(i + n - 1)
533 subint = function(code, i, l)
536 val = val * 256 + code:byte(i + n - 1)
542 local function strip_function(code)
543 local count, offset = subint(code, 1, size)
544 local stripped = { string.rep("\0", size) }
545 local dirty = offset + count
546 offset = offset + count + int * 2 + 4
547 offset = offset + int + subint(code, offset, int) * ins
548 count, offset = subint(code, offset, int)
551 t, offset = subint(code, offset, 1)
555 offset = offset + size + subint(code, offset, size)
557 offset = offset + num
558 elseif t == 254 or t == 9 then
559 offset = offset + lnum
562 count, offset = subint(code, offset, int)
563 stripped[#stripped+1] = code:sub(dirty, offset - 1)
565 local proto, off = strip_function(code:sub(offset, -1))
566 stripped[#stripped+1] = proto
567 offset = offset + off - 1
569 offset = offset + subint(code, offset, int) * int + int
570 count, offset = subint(code, offset, int)
572 offset = offset + subint(code, offset, size) + size + int * 2
574 count, offset = subint(code, offset, int)
576 offset = offset + subint(code, offset, size) + size
578 stripped[#stripped+1] = string.rep("\0", int * 3)
579 return table.concat(stripped), offset
582 return code:sub(1,12) .. strip_function(code:sub(13,-1))
587 -- Sorting iterator functions
590 function _sortiter( t, f )
594 for k, v in pairs(t) do
600 table.sort( keys, f )
604 if _pos <= #keys then
605 return keys[_pos], t[keys[_pos]], _pos
610 --- Return a key, value iterator which returns the values sorted according to
611 -- the provided callback function.
612 -- @param t The table to iterate
613 -- @param f A callback function to decide the order of elements
614 -- @return Function value containing the corresponding iterator
616 return _sortiter( t, f )
619 --- Return a key, value iterator for the given table.
620 -- The table pairs are sorted by key.
621 -- @param t The table to iterate
622 -- @return Function value containing the corresponding iterator
624 return _sortiter( t )
627 --- Return a key, value iterator for the given table.
628 -- The table pairs are sorted by value.
629 -- @param t The table to iterate
630 -- @return Function value containing the corresponding iterator
632 return _sortiter( t, function (a,b) return t[a] < t[b] end )
637 -- System utility functions
640 --- Test whether the current system is operating in big endian mode.
641 -- @return Boolean value indicating whether system is big endian
643 return string.byte(string.dump(function() end), 7) == 0
646 --- Execute given commandline and gather stdout.
647 -- @param command String containing command to execute
648 -- @return String containing the command's stdout
649 function exec(command)
650 local pp = io.popen(command)
651 local data = pp:read("*a")
657 --- Return a line-buffered iterator over the output of given command.
658 -- @param command String containing the command to execute
660 function execi(command)
661 local pp = io.popen(command)
663 return pp and function()
664 local line = pp:read()
675 function execl(command)
676 local pp = io.popen(command)
682 if (line == nil) then break end
690 --- Issue an ubus call.
691 -- @param object String containing the ubus object to call
692 -- @param method String containing the ubus method to call
693 -- @param values Table containing the values to pass
694 -- @return Table containin the ubus result
695 function ubus(object, method, data)
696 if not _ubus_connection then
697 _ubus_connection = _ubus.connect()
698 assert(_ubus_connection, "Unable to establish ubus connection")
701 if object and method then
702 if type(data) ~= "table" then
705 return _ubus_connection:call(object, method, data)
707 return _ubus_connection:signatures(object)
709 return _ubus_connection:objects()
713 --- Returns the absolute path to LuCI base directory.
714 -- @return String containing the directory path
716 return require "nixio.fs".dirname(ldebug.__file__)
721 -- Coroutine safe xpcall and pcall versions modified for Luci
723 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
725 -- Copyright © 2005 Kepler Project.
726 -- Permission is hereby granted, free of charge, to any person obtaining a
727 -- copy of this software and associated documentation files (the "Software"),
728 -- to deal in the Software without restriction, including without limitation
729 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
730 -- and/or sell copies of the Software, and to permit persons to whom the
731 -- Software is furnished to do so, subject to the following conditions:
733 -- The above copyright notice and this permission notice shall be
734 -- included in all copies or substantial portions of the Software.
736 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
737 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
738 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
739 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
740 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
741 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
742 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
744 local performResume, handleReturnValue
745 local oldpcall, oldxpcall = pcall, xpcall
747 setmetatable(coxpt, {__mode = "kv"})
749 -- Identity function for copcall
750 local function copcall_id(trace, ...)
754 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
755 -- @param f Lua function to be called protected
756 -- @param err Custom error handler
757 -- @param ... Parameters passed to the function
758 -- @return A boolean whether the function call succeeded and the return
759 -- values of either the function or the error handler
760 function coxpcall(f, err, ...)
761 local res, co = oldpcall(coroutine.create, f)
764 local newf = function() return f(unpack(params)) end
765 co = coroutine.create(newf)
767 local c = coroutine.running()
768 coxpt[co] = coxpt[c] or c or 0
770 return performResume(err, co, ...)
773 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
774 -- @param f Lua function to be called protected
775 -- @param ... Parameters passed to the function
776 -- @return A boolean whether the function call succeeded and the returns
777 -- values of the function or the error object
778 function copcall(f, ...)
779 return coxpcall(f, copcall_id, ...)
782 -- Handle return value of protected call
783 function handleReturnValue(err, co, status, ...)
785 return false, err(debug.traceback(co, (...)), ...)
788 if coroutine.status(co) ~= 'suspended' then
792 return performResume(err, co, coroutine.yield(...))
795 -- Resume execution of protected function call
796 function performResume(err, co, ...)
797 return handleReturnValue(err, co, coroutine.resume(co, ...))