* luci/libs: add striptags() to luci.util
[project/luci.git] / libs / core / luasrc / util.lua
1 --[[
2 LuCI - Utility library
3
4 Description:
5 Several common useful Lua functions
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
16
17         http://www.apache.org/licenses/LICENSE-2.0
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26
27 --- LuCI utility functions.
28 module("luci.util", package.seeall)
29
30 --
31 -- Class helper routines
32 --
33
34 --- Create a Class object (Python-style object model).
35 -- The class object can be instantiated by calling itself.
36 -- Any class functions or shared parameters can be attached to this object.
37 -- Attaching a table to the class object makes this table shared between
38 -- all instances of this class. For object parameters use the __init__ function.
39 -- Classes can inherit member functions and values from a base class.
40 -- Class can be instantiated by calling them. All parameters will be passed
41 -- to the __init__ function of this class - if such a function exists.
42 -- The __init__ function must be used to set any object parameters that are not shared
43 -- with other objects of this class. Any return values will be ignored.
44 -- @param base  The base class to inherit from (optional)
45 -- @return              A class object
46 -- @see                 instanceof
47 -- @see                 clone
48 function class(base)
49         local class = {}
50
51         local create = function(class, ...)
52                 local inst = {}
53                 setmetatable(inst, {__index = class})
54
55                 if inst.__init__ then
56                         local stat, err = copcall(inst.__init__, inst, ...)
57                         if not stat then
58                                 error(err)
59                         end
60                 end
61
62                 return inst
63         end
64
65         local classmeta = {__call = create}
66
67         if base then
68                 classmeta.__index = base
69         end
70
71         setmetatable(class, classmeta)
72         return class
73 end
74
75 --- Test whether the given object is an instance of the given class.
76 -- @param object        Object instance
77 -- @param class         Class object to test against
78 -- @return                      Boolean indicating whether the object is an instance
79 -- @see                         class
80 -- @see                         clone
81 function instanceof(object, class)
82         local meta = getmetatable(object)
83         while meta and meta.__index do
84                 if meta.__index == class then
85                         return true
86                 end
87                 meta = getmetatable(meta.__index)
88         end
89         return false
90 end
91
92
93 --
94 -- Scope manipulation routines
95 --
96
97 --- Replace a function scope with a shallow copy of itself.
98 -- This is useful if you want to get rid of several unwanted side effects
99 -- while changing the scope of a certain Lua function.
100 -- @param f             Lua function
101 function resfenv(f)
102         setfenv(f, clone(getfenv(f)))
103 end
104
105 --- Store given object associated with given key in the scope of a function.
106 -- @param f             Lua function
107 -- @param key   String value containg the key of the object to store
108 -- @param obj   Object to store in the scope
109 -- @return              Always nil
110 -- @see updfenv
111 -- @see resfenv
112 function extfenv(f, key, obj)
113         local scope = getfenv(f)
114         scope[key] = obj
115 end
116
117 --- Extend the scope of a function with the contents of a table
118 -- @param f             Lua function
119 -- @param key   String value containg the key of the object to store
120 -- @param obj   Object to store in the scope
121 -- @return              Always nil
122 -- @see extfenv
123 -- @see resfenv
124 function updfenv(f, extscope)
125         update(getfenv(f), extscope)
126 end
127
128 --- Create a new or get an already existing thread local store associated with
129 -- the current active coroutine. A thread local store is private a table object
130 -- whose values can't be accessed from outside of the running coroutine.
131 -- @return      Table value representing the corresponding thread local store
132 function threadlocal()
133         local tbl = {}
134
135         local function get(self, key)
136                 local c = coroutine.running()
137                 local thread = coxpt[c] or c or 0
138                 if not rawget(self, thread) then
139                         return nil
140                 end
141                 return rawget(self, thread)[key]
142         end
143
144         local function set(self, key, value)
145                 local c = coroutine.running()
146                 local thread = coxpt[c] or c or 0
147                 if not rawget(self, thread) then
148                         rawset(self, thread, {})
149                 end
150                 rawget(self, thread)[key] = value
151         end
152
153         setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"})
154
155         return tbl
156 end
157
158
159 --
160 -- Debugging routines
161 --
162
163 --- Write given object to stderr.
164 -- @param obj   Value to write to stderr
165 -- @return              Boolean indicating whether the write operation was successful
166 function perror(obj)
167         return io.stderr:write(tostring(obj) .. "\n")
168 end
169
170 --- Recursively dumps a table to stdout, useful for testing and debugging.
171 -- @param t     Table value to dump
172 -- @param i     Number of tabs to prepend to each line
173 -- @return      Always nil
174 function dumptable(t, i)
175         i = i or 0
176         for k,v in pairs(t) do
177                 print(string.rep("\t", i) .. tostring(k), tostring(v))
178                 if type(v) == "table" then
179                         dumptable(v, i+1)
180                 end
181         end
182 end
183
184
185 --
186 -- String and data manipulation routines
187 --
188
189 --- Escapes all occurrences of the given character in given string.
190 -- @param s     String value containing unescaped characters
191 -- @param c     String value with character to escape (optional, defaults to "\")
192 -- @return      String value with each occurrence of character escaped with "\"
193 function escape(s, c)
194         c = c or "\\"
195         return s:gsub(c, "\\" .. c)
196 end
197
198 --- Create valid XML PCDATA from given string.
199 -- @param value String value containing the data to escape
200 -- @return              String value containing the escaped data
201 function pcdata(value)
202         if not value then return end
203         value = tostring(value)
204         value = value:gsub("&", "&amp;")
205         value = value:gsub('"', "&quot;")
206         value = value:gsub("'", "&apos;")
207         value = value:gsub("<", "&lt;")
208         return value:gsub(">", "&gt;")
209 end
210
211 --- Strip HTML tags from given string.
212 -- @param value String containing the HTML text
213 -- @return      String with HTML tags stripped of
214 function striptags(s)
215         return (s:gsub("</?[A-Za-z][A-Za-z0-9:_%-]*[^>]*>", " "):gsub("%s+", " "))
216 end
217
218 --- Splits given string on a defined separator sequence and return a table
219 -- containing the resulting substrings. The optional max parameter specifies
220 -- the number of bytes to process, regardless of the actual length of the given
221 -- string. The optional last parameter, regex, specifies whether the separator
222 -- sequence is interpreted as regular expression.
223 -- @param str           String value containing the data to split up
224 -- @param pat           String with separator pattern (optional, defaults to "\n")
225 -- @param max           Maximum times to split (optional)
226 -- @param regex         Boolean indicating whether to interpret the separator
227 --                                      pattern as regular expression (optional, default is false)
228 -- @return                      Table containing the resulting substrings
229 function split(str, pat, max, regex)
230         pat = pat or "\n"
231         max = max or #str
232
233         local t = {}
234         local c = 1
235
236         if #str == 0 then
237                 return {""}
238         end
239
240         if #pat == 0 then
241                 return nil
242         end
243
244         if max == 0 then
245                 return str
246         end
247
248         repeat
249                 local s, e = str:find(pat, c, not regex)
250                 max = max - 1
251                 if s and max < 0 then
252                         table.insert(t, str:sub(c))
253                 else
254                         table.insert(t, str:sub(c, s and s - 1))
255                 end
256                 c = e and e + 1 or #str + 1
257         until not s or max < 0
258
259         return t
260 end
261
262 --- Remove leading and trailing whitespace from given string value.
263 -- @param str   String value containing whitespace padded data
264 -- @return              String value with leading and trailing space removed
265 function trim(str)
266         local s = str:gsub("^%s*(.-)%s*$", "%1")
267         return s
268 end
269
270 --- Parse certain units from the given string and return the canonical integer
271 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
272 -- Recognized units are:
273 --      o "y"   - one year   (60*60*24*366)
274 --  o "m"       - one month  (60*60*24*31)
275 --  o "w"       - one week   (60*60*24*7)
276 --  o "d"       - one day    (60*60*24)
277 --  o "h"       - one hour       (60*60)
278 --  o "min"     - one minute (60)
279 --  o "kb"  - one kilobyte (1024)
280 --  o "mb"      - one megabyte (1024*1024)
281 --  o "gb"      - one gigabyte (1024*1024*1024)
282 --  o "kib" - one si kilobyte (1000)
283 --  o "mib"     - one si megabyte (1000*1000)
284 --  o "gib"     - one si gigabyte (1000*1000*1000)
285 -- @param ustr  String containing a numerical value with trailing unit
286 -- @return              Number containing the canonical value
287 function parse_units(ustr)
288
289         local val = 0
290
291         -- unit map
292         local map = {
293                 -- date stuff
294                 y   = 60 * 60 * 24 * 366,
295                 m   = 60 * 60 * 24 * 31,
296                 w   = 60 * 60 * 24 * 7,
297                 d   = 60 * 60 * 24,
298                 h   = 60 * 60,
299                 min = 60,
300
301                 -- storage sizes
302                 kb  = 1024,
303                 mb  = 1024 * 1024,
304                 gb  = 1024 * 1024 * 1024,
305
306                 -- storage sizes (si)
307                 kib = 1000,
308                 mib = 1000 * 1000,
309                 gib = 1000 * 1000 * 1000
310         }
311
312         -- parse input string
313         for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
314
315                 local num = spec:gsub("[^0-9%.]+$","")
316                 local spn = spec:gsub("^[0-9%.]+", "")
317
318                 if map[spn] or map[spn:sub(1,1)] then
319                         val = val + num * ( map[spn] or map[spn:sub(1,1)] )
320                 else
321                         val = val + num
322                 end
323         end
324
325
326         return val
327 end
328
329 --- Combines two or more numerically indexed tables into one.
330 -- @param tbl1  Table value to combine
331 -- @param tbl2  Table value to combine
332 -- @param ...   More tables to combine
333 -- @return              Table value containing all values of given tables
334 function combine(...)
335         local result = {}
336         for i, a in ipairs(arg) do
337                 for j, v in ipairs(a) do
338                         table.insert(result, v)
339                 end
340         end
341         return result
342 end
343
344 --- Checks whether the given table contains the given value.
345 -- @param table Table value
346 -- @param value Value to search within the given table
347 -- @return              Boolean indicating whether the given value occurs within table
348 function contains(table, value)
349         for k, v in pairs(table) do
350                 if value == v then
351                         return k
352                 end
353         end
354         return false
355 end
356
357 --- Update values in given table with the values from the second given table.
358 -- Both table are - in fact - merged together.
359 -- @param t                     Table which should be updated
360 -- @param updates       Table containing the values to update
361 -- @return                      Always nil
362 function update(t, updates)
363         for k, v in pairs(updates) do
364                 t[k] = v
365         end
366 end
367
368 --- Retrieve all keys of given associative table.
369 -- @param t     Table to extract keys from
370 -- @return      Sorted table containing the keys
371 function keys(t)
372         local keys = { }
373         if t then
374                 for k, _ in kspairs(t) do
375                         table.insert( keys, k )
376                 end
377         end
378         return keys
379 end
380
381 --- Clones the given object and return it's copy.
382 -- @param object        Table value to clone
383 -- @param deep          Boolean indicating whether to do recursive cloning
384 -- @return                      Cloned table value
385 function clone(object, deep)
386         local copy = {}
387
388         for k, v in pairs(object) do
389                 if deep and type(v) == "table" then
390                         v = clone(v, deep)
391                 end
392                 copy[k] = v
393         end
394
395         setmetatable(copy, getmetatable(object))
396
397         return copy
398 end
399
400
401 --- Create a dynamic table which automatically creates subtables.
402 -- @return      Dynamic Table
403 function dtable()
404         return setmetatable({}, { __index =
405                 function(tbl, key)
406                         return rawget(tbl, key)
407                          or rawget(rawset(tbl, key, dtable()), key)
408                 end
409         })
410 end
411
412
413 -- Serialize the contents of a table value.
414 function _serialize_table(t)
415         local data = ""
416         for k, v in pairs(t) do
417                 k = serialize_data(k)
418                 v = serialize_data(v)
419                 data = data .. ( #data > 0 and ", " or "" ) ..
420                         '[' .. k .. '] = ' .. v
421         end
422         return data
423 end
424
425 --- Recursively serialize given data to lua code, suitable for restoring
426 -- with loadstring().
427 -- @param val   Value containing the data to serialize
428 -- @return              String value containing the serialized code
429 -- @see                 restore_data
430 -- @see                 get_bytecode
431 function serialize_data(val)
432         if val == nil then
433                 return "nil"
434         elseif type(val) == "number" then
435                 return val
436         elseif type(val) == "string" then
437                 return string.format("%q", val)
438         elseif type(val) == "boolean" then
439                 return val and "true" or "false"
440         elseif type(val) == "function" then
441                 return string.format("loadstring(%q)", get_bytecode(val))
442         elseif type(val) == "table" then
443                 return "{ " .. _serialize_table(val) .. " }"
444         else
445                 return '"[unhandled data type:' .. type(val) .. ']"'
446         end
447 end
448
449 --- Restore data previously serialized with serialize_data().
450 -- @param str   String containing the data to restore
451 -- @return              Value containing the restored data structure
452 -- @see                 serialize_data
453 -- @see                 get_bytecode
454 function restore_data(str)
455         return loadstring("return " .. str)()
456 end
457
458
459 --
460 -- Byte code manipulation routines
461 --
462
463 --- Return the current runtime bytecode of the given data. The byte code
464 -- will be stripped before it is returned.
465 -- @param val   Value to return as bytecode
466 -- @return              String value containing the bytecode of the given data
467 function get_bytecode(val)
468         local code
469
470         if type(val) == "function" then
471                 code = string.dump(val)
472         else
473                 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
474         end
475
476         return code and strip_bytecode(code)
477 end
478
479 --- Strips unnescessary lua bytecode from given string. Information like line
480 -- numbers and debugging numbers will be discarded. Original version by
481 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
482 -- @param code  String value containing the original lua byte code
483 -- @return              String value containing the stripped lua byte code
484 function strip_bytecode(code)
485         local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
486         local subint
487         if endian == 1 then
488                 subint = function(code, i, l)
489                         local val = 0
490                         for n = l, 1, -1 do
491                                 val = val * 256 + code:byte(i + n - 1)
492                         end
493                         return val, i + l
494                 end
495         else
496                 subint = function(code, i, l)
497                         local val = 0
498                         for n = 1, l, 1 do
499                                 val = val * 256 + code:byte(i + n - 1)
500                         end
501                         return val, i + l
502                 end
503         end
504
505         local strip_function
506         strip_function = function(code)
507                 local count, offset = subint(code, 1, size)
508                 local stripped, dirty = string.rep("\0", size), offset + count
509                 offset = offset + count + int * 2 + 4
510                 offset = offset + int + subint(code, offset, int) * ins
511                 count, offset = subint(code, offset, int)
512                 for n = 1, count do
513                         local t
514                         t, offset = subint(code, offset, 1)
515                         if t == 1 then
516                                 offset = offset + 1
517                         elseif t == 4 then
518                                 offset = offset + size + subint(code, offset, size)
519                         elseif t == 3 then
520                                 offset = offset + num
521                         elseif t == 254 or t == 9 then
522                                 offset = offset + lnum
523                         end
524                 end
525                 count, offset = subint(code, offset, int)
526                 stripped = stripped .. code:sub(dirty, offset - 1)
527                 for n = 1, count do
528                         local proto, off = strip_function(code:sub(offset, -1))
529                         stripped, offset = stripped .. proto, offset + off - 1
530                 end
531                 offset = offset + subint(code, offset, int) * int + int
532                 count, offset = subint(code, offset, int)
533                 for n = 1, count do
534                         offset = offset + subint(code, offset, size) + size + int * 2
535                 end
536                 count, offset = subint(code, offset, int)
537                 for n = 1, count do
538                         offset = offset + subint(code, offset, size) + size
539                 end
540                 stripped = stripped .. string.rep("\0", int * 3)
541                 return stripped, offset
542         end
543
544         return code:sub(1,12) .. strip_function(code:sub(13,-1))
545 end
546
547
548 --
549 -- Sorting iterator functions
550 --
551
552 function _sortiter( t, f )
553         local keys = { }
554
555         for k, v in pairs(t) do
556                 table.insert( keys, k )
557         end
558
559         local _pos = 0
560         local _len = table.getn( keys )
561
562         table.sort( keys, f )
563
564         return function()
565                 _pos = _pos + 1
566                 if _pos <= _len then
567                         return keys[_pos], t[keys[_pos]]
568                 end
569         end
570 end
571
572 --- Return a key, value iterator which returns the values sorted according to
573 -- the provided callback function.
574 -- @param t     The table to iterate
575 -- @param f A callback function to decide the order of elements
576 -- @return      Function value containing the corresponding iterator
577 function spairs(t,f)
578         return _sortiter( t, f )
579 end
580
581 --- Return a key, value iterator for the given table.
582 -- The table pairs are sorted by key.
583 -- @param t     The table to iterate
584 -- @return      Function value containing the corresponding iterator
585 function kspairs(t)
586         return _sortiter( t )
587 end
588
589 --- Return a key, value iterator for the given table.
590 -- The table pairs are sorted by value.
591 -- @param t     The table to iterate
592 -- @return      Function value containing the corresponding iterator
593 function vspairs(t)
594         return _sortiter( t, function (a,b) return t[a] < t[b] end )
595 end
596
597
598 --
599 -- System utility functions
600 --
601
602 --- Test whether the current system is operating in big endian mode.
603 -- @return      Boolean value indicating whether system is big endian
604 function bigendian()
605         return string.byte(string.dump(function() end), 7) == 0
606 end
607
608 --- Execute given commandline and gather stdout.
609 -- @param command       String containing command to execute
610 -- @return                      String containing the command's stdout
611 function exec(command)
612         local pp   = io.popen(command)
613         local data = pp:read("*a")
614         pp:close()
615
616         return data
617 end
618
619 --- Return a line-buffered iterator over the output of given command.
620 -- @param command       String containing the command to execute
621 -- @return                      Iterator
622 function execi(command)
623         local pp = io.popen(command)
624
625         return pp and function()
626                 local line = pp:read()
627                 
628                 if not line then
629                         pp:close()
630                 end
631                 
632                 return line
633         end
634 end
635
636 -- Deprecated
637 function execl(command)
638         local pp   = io.popen(command)
639         local line = ""
640         local data = {}
641
642         while true do
643                 line = pp:read()
644                 if (line == nil) then break end
645                 table.insert(data, line)
646         end
647         pp:close()
648
649         return data
650 end
651
652 --- Returns the absolute path to LuCI base directory.
653 -- @return              String containing the directory path
654 function libpath()
655         return luci.fs.dirname(require("luci.debug").__file__)
656 end
657
658
659 --
660 -- Coroutine safe xpcall and pcall versions modified for Luci
661 -- original version:
662 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
663 --
664 -- Copyright © 2005 Kepler Project.
665 -- Permission is hereby granted, free of charge, to any person obtaining a
666 -- copy of this software and associated documentation files (the "Software"),
667 -- to deal in the Software without restriction, including without limitation
668 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
669 -- and/or sell copies of the Software, and to permit persons to whom the
670 -- Software is furnished to do so, subject to the following conditions:
671 --
672 -- The above copyright notice and this permission notice shall be
673 -- included in all copies or substantial portions of the Software.
674 --
675 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
676 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
677 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
678 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
679 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
680 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
681 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
682
683 local performResume, handleReturnValue
684 local oldpcall, oldxpcall = pcall, xpcall
685 coxpt = {}
686 setmetatable(coxpt, {__mode = "kv"})
687
688 -- Identity function for copcall
689 local function copcall_id(trace, ...)
690   return ...
691 end
692
693 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
694 -- @param f             Lua function to be called protected
695 -- @param err   Custom error handler
696 -- @param ...   Parameters passed to the function
697 -- @return              A boolean whether the function call succeeded and the return
698 --                              values of either the function or the error handler
699 function coxpcall(f, err, ...)
700         local res, co = oldpcall(coroutine.create, f)
701         if not res then
702                 local params = {...}
703                 local newf = function() return f(unpack(params)) end
704                 co = coroutine.create(newf)
705         end
706         local c = coroutine.running()
707         coxpt[co] = coxpt[c] or c or 0
708
709         return performResume(err, co, ...)
710 end
711
712 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
713 -- @param f             Lua function to be called protected
714 -- @param ...   Parameters passed to the function
715 -- @return              A boolean whether the function call succeeded and the returns
716 --                              values of the function or the error object
717 function copcall(f, ...)
718         return coxpcall(f, copcall_id, ...)
719 end
720
721 -- Handle return value of protected call
722 function handleReturnValue(err, co, status, ...)
723         if not status then
724                 return false, err(debug.traceback(co, (...)), ...)
725         end
726         if coroutine.status(co) == 'suspended' then
727                 return performResume(err, co, coroutine.yield(...))
728         else
729                 return true, ...
730         end
731 end
732
733 -- Resume execution of protected function call
734 function performResume(err, co, ...)
735         return handleReturnValue(err, co, coroutine.resume(co, ...))
736 end