summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/luasrc/util.lua
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/luasrc/util.lua')
-rw-r--r--modules/luci-base/luasrc/util.lua162
1 files changed, 95 insertions, 67 deletions
diff --git a/modules/luci-base/luasrc/util.lua b/modules/luci-base/luasrc/util.lua
index 0e7334be87..10428b0b35 100644
--- a/modules/luci-base/luasrc/util.lua
+++ b/modules/luci-base/luasrc/util.lua
@@ -10,6 +10,7 @@ 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
@@ -99,6 +100,8 @@ end
-- Scope manipulation routines
--
+coxpt = setmetatable({}, { __mode = "kv" })
+
local tl_meta = {
__mode = "k",
@@ -160,10 +163,33 @@ 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
@@ -383,16 +409,6 @@ function clone(object, deep)
end
-function dtable()
- return setmetatable({}, { __index =
- function(tbl, key)
- return rawget(tbl, key)
- or rawget(rawset(tbl, key, dtable()), key)
- end
- })
-end
-
-
-- Serialize the contents of a table value.
function _serialize_table(t, seen)
assert(not seen[t], "Recursion detected.")
@@ -617,6 +633,20 @@ function execl(command)
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"
+}
+
function ubus(object, method, data)
if not _ubus_connection then
_ubus_connection = _ubus.connect()
@@ -627,7 +657,8 @@ function ubus(object, method, data)
if type(data) ~= "table" then
data = { }
end
- return _ubus_connection:call(object, method, data)
+ local rv, err = _ubus_connection:call(object, method, data)
+ return rv, err, ubus_codes[err]
elseif object then
return _ubus_connection:signatures(object)
else
@@ -652,10 +683,11 @@ end
function checklib(fullpathexe, wantedlib)
local fs = require "nixio.fs"
local haveldd = fs.access('/usr/bin/ldd')
- if not haveldd then
+ local haveexe = fs.access(fullpathexe)
+ if not haveldd or not haveexe then
return false
end
- local libs = exec("/usr/bin/ldd " .. fullpathexe)
+ local libs = exec(string.format("/usr/bin/ldd %s", shellquote(fullpathexe)))
if not libs then
return false
end
@@ -667,73 +699,69 @@ function checklib(fullpathexe, wantedlib)
return false
end
+-------------------------------------------------------------------------------
+-- Coroutine safe xpcall and pcall versions
--
--- Coroutine safe xpcall and pcall versions modified for Luci
--- original version:
--- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
+-- 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.
--
--- Copyright © 2005 Kepler Project.
--- 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:
+-- Authors: Roberto Ierusalimschy and Andre Carregal
+-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fabio Mascarenhas
--
--- The above copyright notice and this permission notice shall be
--- included in all copies or substantial portions of the Software.
+-- Copyright 2005 - Kepler Project
--
--- 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.
-
-local performResume, handleReturnValue
-local oldpcall, oldxpcall = pcall, xpcall
-coxpt = {}
-setmetatable(coxpt, {__mode = "kv"})
-
--- Identity function for copcall
-local function copcall_id(trace, ...)
- return ...
-end
-
--- values of either the function or the error handler
-function coxpcall(f, err, ...)
- local res, co = oldpcall(coroutine.create, f)
- if not res then
- local params = {...}
- local newf = function() return f(unpack(params)) end
- co = coroutine.create(newf)
- end
- local c = coroutine.running()
- coxpt[co] = coxpt[c] or c or 0
+-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $
+-------------------------------------------------------------------------------
- return performResume(err, co, ...)
-end
-
--- values of the function or the error object
-function copcall(f, ...)
- return coxpcall(f, copcall_id, ...)
-end
+-------------------------------------------------------------------------------
+-- Implements xpcall with coroutines
+-------------------------------------------------------------------------------
+local coromap = setmetatable({}, { __mode = "k" })
--- Handle return value of protected call
-function handleReturnValue(err, co, status, ...)
+local function handleReturnValue(err, co, status, ...)
if not status then
return false, err(debug.traceback(co, (...)), ...)
end
-
- if coroutine.status(co) ~= 'suspended' then
+ if coroutine.status(co) == 'suspended' then
+ return performResume(err, co, coroutine.yield(...))
+ else
return true, ...
end
-
- return performResume(err, co, coroutine.yield(...))
end
--- Resume execution of protected function call
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