libs/core: Reworked some basic libraries to not use package.seeall

libs/json: Implemented own JSON-Decoder (Encoder will follow)
modules/rpc: Preliminary implemented RPC-Exports for luci.fs, luci.sys and luci.model.uci
This commit is contained in:
Steven Barth 2008-08-26 00:53:28 +00:00
parent 8e6d1e682a
commit 0c5dc7bc77
8 changed files with 476 additions and 521 deletions

View file

@ -24,10 +24,12 @@ limitations under the License.
]]-- ]]--
--- LuCI filesystem library. local posix = require "posix"
module("luci.fs", package.seeall) local io = require "io"
local type = type
require("posix") --- LuCI filesystem library.
module "luci.fs"
--- Test for file access permission on given path. --- Test for file access permission on given path.
-- @class function -- @class function

View file

@ -1,519 +1,319 @@
--[[ --[[
LuCI - Lua Configuration Interface
JSON Encoder and Parser for Lua 5.1 Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Copyright <EFBFBD> 2007 Shaun Brown (http://www.chipmunkav.com).
All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this 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 Licensed under the Apache License, Version 2.0 (the "License");
included in all copies or substantial portions of the Software. you may not use this file except in compliance with the License.
If you find this software useful please give www.chipmunkav.com a mention. You may obtain a copy of the License at
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, http://www.apache.org/licenses/LICENSE-2.0
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.
Usage: $Id$
]]--
-- Lua script: local util = require "luci.util"
local t = { local ltn12 = require "luci.ltn12"
["name1"] = "value1", local table = require "table"
["name2"] = {1, false, true, 23.54, "a \021 string"}, local coroutine = require "coroutine"
name3 = Json.Null()
}
local json = Json.Encode (t) local assert = assert
print (json) local tonumber = tonumber
--> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]} local error = error
local t = Json.Decode(json) module "luci.json"
print(t.name2[4])
--> 23.54
Notes:
1) Encodable Lua types: string, number, boolean, table, nil
2) Use Json.Null() to insert a null value into a Json object
3) All control chars are encoded to \uXXXX format eg "\021" encodes to "\u0015"
4) All Json \uXXXX chars are decoded to chars (0-255 byte range only)
5) Json single line // and /* */ block comments are discarded during decoding
6) Numerically indexed Lua arrays are encoded to Json Lists eg [1,2,3]
7) Lua dictionary tables are converted to Json objects eg {"one":1,"two":2}
8) Json nulls are decoded to Lua nil and treated by Lua in the normal way
--]] --- Null replacement function
-- @return null
local string = string function null()
local math = math return null
local table = table
local error = error
local tonumber = tonumber
local tostring = tostring
local type = type
local setmetatable = setmetatable
local pairs = pairs
local ipairs = ipairs
local assert = assert
local Chipmunk = Chipmunk
module("luci.json")
local StringBuilder = {
buffer = {}
}
function StringBuilder:New()
local o = {}
setmetatable(o, self)
self.__index = self
o.buffer = {}
return o
end end
function StringBuilder:Append(s) Decoder = util.class()
self.buffer[#self.buffer+1] = s
end
function StringBuilder:ToString() --- Create an LTN12 sink from the decoder object
return table.concat(self.buffer) -- @return LTN12 sink
end function Decoder.sink(self)
local sink = coroutine.create(self.dispatch)
local JsonWriter = { return function(...)
backslashes = { return coroutine.resume(sink, self, ...)
['\b'] = "\\b",
['\t'] = "\\t",
['\n'] = "\\n",
['\f'] = "\\f",
['\r'] = "\\r",
['"'] = "\\\"",
['\\'] = "\\\\",
['/'] = "\\/"
}
}
function JsonWriter:New()
local o = {}
o.writer = StringBuilder:New()
setmetatable(o, self)
self.__index = self
return o
end
function JsonWriter:Append(s)
self.writer:Append(s)
end
function JsonWriter:ToString()
return self.writer:ToString()
end
function JsonWriter:Write(o)
local t = type(o)
if t == "nil" then
self:WriteNil()
elseif t == "boolean" then
self:WriteString(o)
elseif t == "number" then
self:WriteString(o)
elseif t == "string" then
self:ParseString(o)
elseif t == "table" then
self:WriteTable(o)
elseif t == "function" then
self:WriteFunction(o)
elseif t == "thread" then
self:WriteError(o)
elseif t == "userdata" then
self:WriteError(o)
end end
end end
function JsonWriter:WriteNil()
self:Append("null") --- Get the decoded data packets
-- @return Decoded data
function Decoder.get(self)
return self.data
end end
function JsonWriter:WriteString(o)
self:Append(tostring(o))
end
function JsonWriter:ParseString(s) function Decoder.dispatch(self, chunk, src_err, strict)
self:Append('"') local robject, object
self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
local c = self.backslashes[n] while chunk do
if c then return c end if #chunk < 1 then
return string.format("\\u%.4X", string.byte(n)) chunk = self:fetch()
end))
self:Append('"')
end
function JsonWriter:IsArray(t)
local count = 0
local isindex = function(k)
if type(k) == "number" and k > 0 then
if math.floor(k) == k then
return true
end
end end
return false
end
for k,v in pairs(t) do
if not isindex(k) then
return false, '{', '}'
else
count = math.max(count, k)
end
end
return true, '[', ']', count
end
function JsonWriter:WriteTable(t)
local ba, st, et, n = self:IsArray(t)
self:Append(st)
if ba then
for i = 1, n do
self:Write(t[i])
if i < n then
self:Append(',')
end
end
else
local first = true;
for k, v in pairs(t) do
if not first then
self:Append(',')
end
first = false;
self:ParseString(k)
self:Append(':')
self:Write(v)
end
end
self:Append(et)
end
function JsonWriter:WriteError(o)
error(string.format(
"Encoding of %s unsupported",
tostring(o)))
end
function JsonWriter:WriteFunction(o)
if o == Null then
self:WriteNil()
else
self:WriteError(o)
end
end
local StringReader = {
s = "",
i = 0
}
function StringReader:New(s)
local o = {}
setmetatable(o, self)
self.__index = self
o.s = s or o.s
return o
end
function StringReader:Peek()
local i = self.i + 1
if i <= #self.s then
return string.sub(self.s, i, i)
end
return nil
end
function StringReader:Next()
self.i = self.i+1
if self.i <= #self.s then
return string.sub(self.s, self.i, self.i)
end
return nil
end
function StringReader:All()
return self.s
end
local JsonReader = {
escapes = {
['t'] = '\t',
['n'] = '\n',
['f'] = '\f',
['r'] = '\r',
['b'] = '\b',
}
}
function JsonReader:New(s)
local o = {}
o.reader = StringReader:New(s)
setmetatable(o, self)
self.__index = self
return o;
end
function JsonReader:Read()
self:SkipWhiteSpace()
local peek = self:Peek()
if peek == nil then
error(string.format(
"Nil string: '%s'",
self:All()))
elseif peek == '{' then
return self:ReadObject()
elseif peek == '[' then
return self:ReadArray()
elseif peek == '"' then
return self:ReadString()
elseif string.find(peek, "[%+%-%d]") then
return self:ReadNumber()
elseif peek == 't' then
return self:ReadTrue()
elseif peek == 'f' then
return self:ReadFalse()
elseif peek == 'n' then
return self:ReadNull()
elseif peek == '/' then
self:ReadComment()
return self:Read()
else
error(string.format(
"Invalid input: '%s'",
self:All()))
end
end
function JsonReader:ReadTrue() assert(not strict or chunk, "Unexpected EOS")
self:TestReservedWord{'t','r','u','e'} if not chunk then
return true break
end
function JsonReader:ReadFalse()
self:TestReservedWord{'f','a','l','s','e'}
return false
end
function JsonReader:ReadNull()
self:TestReservedWord{'n','u','l','l'}
return nil
end
function JsonReader:TestReservedWord(t)
for i, v in ipairs(t) do
if self:Next() ~= v then
error(string.format(
"Error reading '%s': %s",
table.concat(t),
self:All()))
end end
end
end local parser = nil
local char = chunk:sub(1, 1)
function JsonReader:ReadNumber()
local result = self:Next() if char == '"' then
local peek = self:Peek() parser = self.parse_string
while peek ~= nil and string.find( elseif char == 't' then
peek, parser = self.parse_true
"[%+%-%d%.eE]") do elseif char == 'f' then
result = result .. self:Next() parser = self.parse_false
peek = self:Peek() elseif char == 'n' then
end parser = self.parse_null
result = tonumber(result) elseif char == '[' then
if result == nil then parser = self.parse_array
error(string.format( elseif char == '{' then
"Invalid number: '%s'", parser = self.parse_object
result)) elseif char:match("%s") then
else parser = self.parse_space
return result elseif char:match("[0-9-]") then
end parser = self.parse_number
end end
function JsonReader:ReadString() if parser then
local result = "" chunk, robject = parser(self, chunk)
assert(self:Next() == '"')
while self:Peek() ~= '"' do if robject ~= nil then
local ch = self:Next() assert(object == nil, "Scope violation: Too many objects")
if ch == '\\' then object = robject
ch = self:Next()
if self.escapes[ch] then
ch = self.escapes[ch]
end end
end
result = result .. ch if strict and object ~= nil then
end return chunk, object
assert(self:Next() == '"')
local fromunicode = function(m)
return string.char(tonumber(m, 16))
end
return string.gsub(
result,
"u%x%x(%x%x)",
fromunicode)
end
function JsonReader:ReadComment()
assert(self:Next() == '/')
local second = self:Next()
if second == '/' then
self:ReadSingleLineComment()
elseif second == '*' then
self:ReadBlockComment()
else
error(string.format(
"Invalid comment: %s",
self:All()))
end
end
function JsonReader:ReadBlockComment()
local done = false
while not done do
local ch = self:Next()
if ch == '*' and self:Peek() == '/' then
done = true
end
if not done and
ch == '/' and
self:Peek() == "*" then
error(string.format(
"Invalid comment: %s, '/*' illegal.",
self:All()))
end
end
self:Next()
end
function JsonReader:ReadSingleLineComment()
local ch = self:Next()
while ch ~= '\r' and ch ~= '\n' do
ch = self:Next()
end
end
function JsonReader:ReadArray()
local result = {}
assert(self:Next() == '[')
self:SkipWhiteSpace()
local done = false
if self:Peek() == ']' then
done = true;
end
while not done do
local item = self:Read()
result[#result+1] = item
self:SkipWhiteSpace()
if self:Peek() == ']' then
done = true
end
if not done then
local ch = self:Next()
if ch ~= ',' then
error(string.format(
"Invalid array: '%s' due to: '%s'",
self:All(), ch))
end end
end
end
assert(']' == self:Next())
return result
end
function JsonReader:ReadObject()
local result = {}
assert(self:Next() == '{')
self:SkipWhiteSpace()
local done = false
if self:Peek() == '}' then
done = true
end
while not done do
local key = self:Read()
if type(key) ~= "string" then
error(string.format(
"Invalid non-string object key: %s",
key))
end
self:SkipWhiteSpace()
local ch = self:Next()
if ch ~= ':' then
error(string.format(
"Invalid object: '%s' due to: '%s'",
self:All(),
ch))
end
self:SkipWhiteSpace()
local val = self:Read()
result[key] = val
self:SkipWhiteSpace()
if self:Peek() == '}' then
done = true
end
if not done then
ch = self:Next()
if ch ~= ',' then
error(string.format(
"Invalid array: '%s' near: '%s'",
self:All(),
ch))
end
end
end
assert(self:Next() == "}")
return result
end
function JsonReader:SkipWhiteSpace()
local p = self:Peek()
while p ~= nil and string.find(p, "[%s/]") do
if p == '/' then
self:ReadComment()
else else
self:Next() error("Unexpected char '%s'" % char)
end end
p = self:Peek() end
assert(not src_err, src_err)
assert(object ~= nil, "Unexpected EOS")
self.data = object
return chunk, object
end
function Decoder.fetch(self)
local tself, chunk, src_err = coroutine.yield()
assert(chunk or not src_err, src_err)
return chunk
end
function Decoder.fetch_atleast(self, chunk, bytes)
while #chunk < bytes do
local nchunk = self:fetch()
assert(nchunk, "Unexpected EOS")
chunk = chunk .. nchunk
end
return chunk
end
function Decoder.fetch_until(self, chunk, pattern)
local start = chunk:find(pattern)
while not start do
local nchunk = self:fetch()
assert(nchunk, "Unexpected EOS")
chunk = chunk .. nchunk
start = chunk:find(pattern)
end
return chunk, start
end
function Decoder.parse_space(self, chunk)
local start = chunk:find("[^%s]")
while not start do
chunk = self:fetch()
if not chunk then
return nil
end
start = chunk:find("[^%s]")
end
return chunk:sub(start)
end
function Decoder.parse_literal(self, chunk, literal, value)
chunk = self:fetch_atleast(chunk, #literal)
assert(chunk:sub(1, #literal) == literal, "Invalid character sequence")
return chunk:sub(#literal + 1), value
end
function Decoder.parse_null(self, chunk)
return self:parse_literal(chunk, "null", null)
end
function Decoder.parse_true(self, chunk)
return self:parse_literal(chunk, "true", true)
end
function Decoder.parse_false(self, chunk)
return self:parse_literal(chunk, "false", false)
end
function Decoder.parse_number(self, chunk)
local chunk, start = self:fetch_until(chunk, "[^0-9eE.+-]")
local number = tonumber(chunk:sub(1, start - 1))
assert(number, "Invalid number specification")
return chunk:sub(start), number
end
function Decoder.parse_string(self, chunk)
local str = ""
local object = nil
assert(chunk:sub(1, 1) == '"', 'Expected "')
chunk = chunk:sub(2)
while true do
local spos = chunk:find('[\\"]')
if spos then
str = str .. chunk:sub(1, spos - 1)
local char = chunk:sub(spos, spos)
if char == '"' then -- String end
chunk = chunk:sub(spos + 1)
break
elseif char == "\\" then -- Escape sequence
chunk, object = self:parse_escape(chunk:sub(spos))
str = str .. object
end
else
str = str .. chunk
chunk = self:fetch()
assert(chunk, "Unexpected EOS while parsing a string")
end
end
return chunk, str
end
function Decoder.parse_escape(self, chunk)
local str = ""
chunk = self:fetch_atleast(chunk:sub(2), 1)
local char = chunk:sub(1, 1)
chunk = chunk:sub(2)
if char == '"' then
return chunk, '"'
elseif char == "\\" then
return chunk, "\\"
elseif char == "/" then
return chunk, "/"
elseif char == "b" then
return chunk, "\b"
elseif char == "f" then
return chunk, "\f"
elseif char == "n" then
return chunk, "\n"
elseif char == "r" then
return chunk, "\r"
elseif char == "t" then
return chunk, "\t"
elseif char == "u" then
chunk = self:fetch_atleast(chunk, 4)
local s1, s2 = chunk:sub(1, 4):match("^([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])$")
assert(s1 and s2, "Invalid Unicode character 'U+%s%s'" % {s1, s2})
s1, s2 = tonumber(s1, 16), tonumber(s2, 16)
-- ToDo: Unicode support
return chunk:sub(5), s1 == 0 and s2 or ""
else
error("Unexpected escaping sequence '\\%s'" % char)
end end
end end
function JsonReader:Peek()
return self.reader:Peek() function Decoder.parse_array(self, chunk)
chunk = chunk:sub(2)
local array = {}
local chunk, object = self:parse_delimiter(chunk, "%]")
if object then
return chunk, array
end
repeat
chunk, object = self:dispatch(chunk, nil, true)
table.insert(array, object)
chunk, object = self:parse_delimiter(chunk, ",%]")
assert(object, "Delimiter expected")
until object == "]"
return chunk, array
end end
function JsonReader:Next()
return self.reader:Next() function Decoder.parse_object(self, chunk)
chunk = chunk:sub(2)
local array = {}
local name
local chunk, object = self:parse_delimiter(chunk, "}")
if object then
return chunk, array
end
repeat
chunk = self:parse_space(chunk)
assert(chunk, "Unexpected EOS")
chunk, name = self:parse_string(chunk)
chunk, object = self:parse_delimiter(chunk, ":")
assert(object, "Separator expected")
chunk, object = self:dispatch(chunk, nil, true)
array[name] = object
chunk, object = self:parse_delimiter(chunk, ",}")
assert(object, "Delimiter expected")
until object == "}"
return chunk, array
end end
function JsonReader:All()
return self.reader:All()
end
function Encode(o) function Decoder.parse_delimiter(self, chunk, delimiter)
local writer = JsonWriter:New() while true do
writer:Write(o) chunk = self:fetch_atleast(chunk, 1)
return writer:ToString() local char = chunk:sub(1, 1)
end if char:match("%s") then
chunk = self:parse_space(chunk)
function Decode(s) assert(chunk, "Unexpected EOS")
local reader = JsonReader:New(s) elseif char:match("[%s]" % delimiter) then
local object = reader:Read() return chunk:sub(2), char
reader:SkipWhiteSpace() else
assert(reader:Peek() == nil, "Invalid characters after JSON body") return chunk, nil
return object end
end end
end
function Null()
return Null
end

View file

@ -24,14 +24,26 @@ limitations under the License.
]]-- ]]--
local io = require "io"
local os = require "os"
local posix = require "posix"
local table = require "table"
local luci = {}
luci.util = require "luci.util"
luci.fs = require "luci.fs"
luci.ip = require "luci.ip"
local tonumber, ipairs, pairs = tonumber, ipairs, pairs
--- LuCI Linux and POSIX system utilities. --- LuCI Linux and POSIX system utilities.
module("luci.sys", package.seeall) module "luci.sys"
require("posix")
require("luci.util")
require("luci.fs")
require("luci.ip")
--- Invoke the luci-flash executable to write an image to the flash memory. --- Invoke the luci-flash executable to write an image to the flash memory.
-- @param image Local path or URL to image file
-- @param kpattern Pattern of files to keep over flash process -- @param kpattern Pattern of files to keep over flash process
-- @return Return value of os.execute() -- @return Return value of os.execute()
function flash(image, kpattern) function flash(image, kpattern)

View file

@ -23,11 +23,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
]]-- ]]--
local uci = require("uci") local uci = require "uci"
local util = require("luci.util") local util = require "luci.util"
local table = require "table"
local setmetatable, rawget, rawset = setmetatable, rawget, rawset local setmetatable, rawget, rawset = setmetatable, rawget, rawset
local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring
local table = table local require = require
--- LuCI UCI model library. --- LuCI UCI model library.
module("luci.model.uci", function(m) setmetatable(m, {__index = uci}) end) module("luci.model.uci", function(m) setmetatable(m, {__index = uci}) end)
@ -37,6 +39,14 @@ confdir_default = "/etc/config"
savedir_state = "/var/state" savedir_state = "/var/state"
--- Applies the new config
-- @param config UCI config
function apply(config)
local conf = require "luci.config"
return conf.uci_oncommit[config] and os.execute(conf.uci_oncommit[config])
end
--- Delete all sections of a given type that match certain criteria. --- Delete all sections of a given type that match certain criteria.
-- @param config UCI config -- @param config UCI config
-- @param type UCI section type -- @param type UCI section type
@ -149,7 +159,6 @@ function get_list(config, section, option)
end end
--- Set given values as list. --- Set given values as list.
-- Warning: This function is unsave! You should use save_config or save_state if possible.
-- @param config UCI config -- @param config UCI config
-- @param section UCI section name -- @param section UCI section name
-- @param option UCI option -- @param option UCI option
@ -244,7 +253,6 @@ end
-- @see unload -- @see unload
--- Set a value or create a named section. --- Set a value or create a named section.
-- Warning: This function is unsave! You should use save_config or save_state if possible.
-- @class function -- @class function
-- @name set -- @name set
-- @param config UCI config -- @param config UCI config

View file

@ -187,13 +187,15 @@ function dispatch(request)
if not luci.util.contains(accs, user) then if not luci.util.contains(accs, user) then
if authen then if authen then
local user = authen(luci.sys.user.checkpasswd, accs, def) local user, sess = authen(luci.sys.user.checkpasswd, accs, def)
if not user or not luci.util.contains(accs, user) then if not user or not luci.util.contains(accs, user) then
return return
else else
local sid = luci.sys.uniqueid(16) local sid = sess or luci.sys.uniqueid(16)
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
luci.sauth.write(sid, user) if not sess then
luci.sauth.write(sid, user)
end
end end
else else
luci.http.status(403, "Forbidden") luci.http.status(403, "Forbidden")

View file

@ -12,15 +12,20 @@ You may obtain a copy of the License at
$Id$ $Id$
]]-- ]]--
module("luci.controller.rpc", package.seeall)
local require = require
local pairs = pairs
local print = print
module "luci.controller.rpc"
function index() function index()
local function authenticator(validator, accs) local function authenticator(validator, accs)
local args = luci.dispatcher.context.args local auth = luci.http.formvalue("auth", true)
if args and #args > 0 then if auth then
local user = luci.sauth.read(args[1]) local user = luci.sauth.read(auth)
if user and luci.util.contains(accs, user) then if user and luci.util.contains(accs, user) then
return user return user, auth
end end
end end
luci.http.status(403, "Forbidden") luci.http.status(403, "Forbidden")
@ -29,16 +34,25 @@ function index()
uci = entry({"rpc", "uci"}, call("rpc_uci")) uci = entry({"rpc", "uci"}, call("rpc_uci"))
uci.sysauth = "root" uci.sysauth = "root"
uci.sysauth_authenticator = authenticator uci.sysauth_authenticator = authenticator
uci.leaf = true
fs = entry({"rpc", "fs"}, call("rpc_fs"))
fs.sysauth = "root"
fs.sysauth_authenticator = authenticator
fs = entry({"rpc", "sys"}, call("rpc_sys"))
fs.sysauth = "root"
fs.sysauth_authenticator = authenticator
uci = entry({"rpc", "auth"}, call("rpc_auth")) uci = entry({"rpc", "auth"}, call("rpc_auth"))
end end
function rpc_auth() function rpc_auth()
require "luci.jsonrpc" local jsonrpc = require "luci.jsonrpc"
require "luci.sauth" local sauth = require "luci.sauth"
local http = require "luci.http"
local sys = require "luci.sys"
luci.http.setfilehandler() http.setfilehandler()
local loginstat local loginstat
@ -46,21 +60,45 @@ function rpc_auth()
server.login = function(user, pass) server.login = function(user, pass)
local sid local sid
if luci.sys.user.checkpasswd(user, pass) then if sys.user.checkpasswd(user, pass) then
sid = luci.sys.uniqueid(16) sid = sys.uniqueid(16)
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
luci.sauth.write(sid, user) sauth.write(sid, user)
end end
return sid return sid
end end
luci.http.prepare_content("application/json") http.prepare_content("application/json")
luci.http.write(luci.jsonrpc.handle(server, luci.http.content())) http.write(jsonrpc.handle(server, http.content()))
return loginstat
end end
function rpc_uci() function rpc_uci()
local uci = require "luci.controller.rpc.uci"
local jsonrpc = require "luci.jsonrpc"
local http = require "luci.http"
http.setfilehandler()
http.prepare_content("application/json")
http.write(jsonrpc.handle(uci, http.content()))
end
function rpc_fs()
local fs = require "luci.fs"
local jsonrpc = require "luci.jsonrpc"
local http = require "luci.http"
http.setfilehandler()
http.prepare_content("application/json")
http.write(jsonrpc.handle(fs, http.content()))
end
function rpc_sys()
local sys = require "luci.sys"
local jsonrpc = require "luci.jsonrpc"
local http = require "luci.http"
http.setfilehandler()
http.prepare_content("application/json")
http.write(jsonrpc.handle(sys, http.content()))
end end

View file

@ -0,0 +1,93 @@
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
local uci = require "luci.model.uci"
local table = require "table"
module "luci.controller.rpc.uci"
_M, _PACKAGE, _NAME = nil, nil, nil
function add(config, ...)
uci.load_config(config)
local stat = uci.add(config, ...)
return uci.save_config(config) and stat
end
function apply(config)
return uci.apply(config)
end
function changes(...)
return uci.changes(...)
end
function commit(config)
return uci.load(config) and uci.commit(config)
end
function delete(config, ...)
uci.load(config)
return uci.delete(config, ...) and uci.save(config)
end
function delete_all(config, ...)
uci.load(config)
return uci.delete_all(config, ...) and uci.save(config)
end
function foreach(config, stype)
uci.load_config(config)
local sections = {}
return uci.foreach(config, stype, function(section)
table.insert(sections, section)
end) and sections
end
function get(config, ...)
uci.load_config(config)
return uci.get(config, ...)
end
function get_all(config, ...)
uci.load_config(config)
return uci.get_all(config, ...)
end
function get_state(config, ...)
uci.load_state(config)
return uci.get(config, ...)
end
function revert(config)
return uci.load(config) and uci.revert(config)
end
function section(config, ...)
uci.load_config(config)
return uci.section(config, ...) and uci.save_config(config)
end
function set(config, ...)
uci.load_config(config)
return uci.set(config, ...) and uci.save_config(config)
end
function tset(config, ...)
uci.load_config(config)
return uci.tset(config, ...) and uci.save_config(config)
end

View file

@ -23,12 +23,12 @@ function resolve(mod, method)
if not type(mod) == "table" then if not type(mod) == "table" then
break break
end end
mod = mod[path[j]] mod = rawget(mod, path[j])
if not mod then if not mod then
break break
end end
end end
mod = type(mod) == "table" and mod[path[#path]] or nil mod = type(mod) == "table" and rawget(mod, path[#path]) or nil
if type(mod) == "function" then if type(mod) == "function" then
return mod return mod
end end