From 0c5dc7bc77a4fd7d7f0d965e3185e2df4c608f05 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Tue, 26 Aug 2008 00:53:28 +0000 Subject: [PATCH] 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 --- libs/core/luasrc/fs.lua | 8 +- libs/json/luasrc/json.lua | 702 +++++++++++------------------- libs/sys/luasrc/sys.lua | 22 +- libs/uci/luasrc/model/uci.lua | 18 +- libs/web/luasrc/dispatcher.lua | 8 +- modules/rpc/luasrc/controller/rpc.lua | 72 ++- modules/rpc/luasrc/controller/rpc/uci.lua | 93 ++++ modules/rpc/luasrc/jsonrpc.lua | 4 +- 8 files changed, 441 insertions(+), 486 deletions(-) create mode 100644 modules/rpc/luasrc/controller/rpc/uci.lua diff --git a/libs/core/luasrc/fs.lua b/libs/core/luasrc/fs.lua index e089d55dd..56108db95 100644 --- a/libs/core/luasrc/fs.lua +++ b/libs/core/luasrc/fs.lua @@ -24,10 +24,12 @@ limitations under the License. ]]-- ---- LuCI filesystem library. -module("luci.fs", package.seeall) +local posix = require "posix" +local io = require "io" +local type = type -require("posix") +--- LuCI filesystem library. +module "luci.fs" --- Test for file access permission on given path. -- @class function diff --git a/libs/json/luasrc/json.lua b/libs/json/luasrc/json.lua index 85b85e1e8..0d38ed479 100644 --- a/libs/json/luasrc/json.lua +++ b/libs/json/luasrc/json.lua @@ -1,519 +1,319 @@ --[[ +LuCI - Lua Configuration Interface - JSON Encoder and Parser for Lua 5.1 - - Copyright � 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 - included in all copies or substantial portions of the Software. - If you find this software useful please give www.chipmunkav.com a mention. - - 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. - - Usage: - - -- Lua script: - local t = { - ["name1"] = "value1", - ["name2"] = {1, false, true, 23.54, "a \021 string"}, - name3 = Json.Null() - } - - local json = Json.Encode (t) - print (json) - --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]} - - local t = Json.Decode(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 - ---]] - -local string = string -local math = math -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 +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich -function StringBuilder:Append(s) - self.buffer[#self.buffer+1] = s -end +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 -function StringBuilder:ToString() - return table.concat(self.buffer) -end +http://www.apache.org/licenses/LICENSE-2.0 -local JsonWriter = { - backslashes = { - ['\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 +$Id$ +]]-- -function JsonWriter:Append(s) - self.writer:Append(s) -end +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local table = require "table" +local coroutine = require "coroutine" + +local assert = assert +local tonumber = tonumber +local error = error -function JsonWriter:ToString() - return self.writer:ToString() +module "luci.json" + +--- Null replacement function +-- @return null +function null() + return null 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) +Decoder = util.class() + +--- Create an LTN12 sink from the decoder object +-- @return LTN12 sink +function Decoder.sink(self) + local sink = coroutine.create(self.dispatch) + return function(...) + return coroutine.resume(sink, self, ...) end end -function JsonWriter:WriteNil() - self:Append("null") -end -function JsonWriter:WriteString(o) - self:Append(tostring(o)) +--- Get the decoded data packets +-- @return Decoded data +function Decoder.get(self) + return self.data end -function JsonWriter:ParseString(s) - self:Append('"') - self:Append(string.gsub(s, "[%z%c\\\"/]", function(n) - local c = self.backslashes[n] - if c then return c end - return string.format("\\u%.4X", string.byte(n)) - 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 +function Decoder.dispatch(self, chunk, src_err, strict) + local robject, object + + while chunk do + if #chunk < 1 then + chunk = self:fetch() end - return false - end - for k,v in pairs(t) do - if not isindex(k) then - return false, '{', '}' - else - count = math.max(count, k) + + assert(not strict or chunk, "Unexpected EOS") + if not chunk then + break 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 + + local parser = nil + local char = chunk:sub(1, 1) + + if char == '"' then + parser = self.parse_string + elseif char == 't' then + parser = self.parse_true + elseif char == 'f' then + parser = self.parse_false + elseif char == 'n' then + parser = self.parse_null + elseif char == '[' then + parser = self.parse_array + elseif char == '{' then + parser = self.parse_object + elseif char:match("%s") then + parser = self.parse_space + elseif char:match("[0-9-]") then + parser = self.parse_number end - else - local first = true; - for k, v in pairs(t) do - if not first then - self:Append(',') + + if parser then + chunk, robject = parser(self, chunk) + + if robject ~= nil then + assert(object == nil, "Scope violation: Too many objects") + object = robject end - first = false; - self:ParseString(k) - self:Append(':') - self:Write(v) + + if strict and object ~= nil then + return chunk, object + end + else + error("Unexpected char '%s'" % char) end end - self:Append(et) + + assert(not src_err, src_err) + assert(object ~= nil, "Unexpected EOS") + + self.data = object + return chunk, object 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 +function Decoder.fetch(self) + local tself, chunk, src_err = coroutine.yield() + assert(chunk or not src_err, src_err) + return chunk 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) +function Decoder.fetch_atleast(self, chunk, bytes) + while #chunk < bytes do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk end - return nil + + return chunk 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 Decoder.fetch_until(self, chunk, pattern) + local start = chunk:find(pattern) -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())) + while not start do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk + start = chunk:find(pattern) end -end - -function JsonReader:ReadTrue() - self:TestReservedWord{'t','r','u','e'} - return true -end -function JsonReader:ReadFalse() - self:TestReservedWord{'f','a','l','s','e'} - return false + return chunk, start 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())) +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 JsonReader:ReadNumber() - local result = self:Next() - local peek = self:Peek() - while peek ~= nil and string.find( - peek, - "[%+%-%d%.eE]") do - result = result .. self:Next() - peek = self:Peek() - end - result = tonumber(result) - if result == nil then - error(string.format( - "Invalid number: '%s'", - result)) - else - return result - 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 JsonReader:ReadString() - local result = "" - assert(self:Next() == '"') - while self:Peek() ~= '"' do - local ch = self:Next() - if ch == '\\' then - ch = self:Next() - if self.escapes[ch] then - ch = self.escapes[ch] - end - end - result = result .. ch - end - assert(self:Next() == '"') - local fromunicode = function(m) - return string.char(tonumber(m, 16)) - end - return string.gsub( - result, - "u%x%x(%x%x)", - fromunicode) + +function Decoder.parse_null(self, chunk) + return self:parse_literal(chunk, "null", null) 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 + +function Decoder.parse_true(self, chunk) + return self:parse_literal(chunk, "true", true) 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() + +function Decoder.parse_false(self, chunk) + return self:parse_literal(chunk, "false", false) end -function JsonReader:ReadSingleLineComment() - local ch = self:Next() - while ch ~= '\r' and ch ~= '\n' do - ch = self:Next() - 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 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)) + +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 - 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 + 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 - 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 - self:Next() - end - p = self: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 -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 == "]" -function JsonReader:Peek() - return self.reader:Peek() + return chunk, array end -function JsonReader:Next() - return self.reader:Next() -end -function JsonReader:All() - return self.reader:All() -end +function Decoder.parse_object(self, chunk) + chunk = chunk:sub(2) + local array = {} + local name -function Encode(o) - local writer = JsonWriter:New() - writer:Write(o) - return writer:ToString() -end + local chunk, object = self:parse_delimiter(chunk, "}") -function Decode(s) - local reader = JsonReader:New(s) - local object = reader:Read() - reader:SkipWhiteSpace() - assert(reader:Peek() == nil, "Invalid characters after JSON body") - return object -end + 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 == "}" -function Null() - return Null + return chunk, array end + + +function Decoder.parse_delimiter(self, chunk, delimiter) + while true do + chunk = self:fetch_atleast(chunk, 1) + local char = chunk:sub(1, 1) + if char:match("%s") then + chunk = self:parse_space(chunk) + assert(chunk, "Unexpected EOS") + elseif char:match("[%s]" % delimiter) then + return chunk:sub(2), char + else + return chunk, nil + end + end +end \ No newline at end of file diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index d0dc5acbd..bce4e8a62 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -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. -module("luci.sys", package.seeall) -require("posix") -require("luci.util") -require("luci.fs") -require("luci.ip") +module "luci.sys" + --- 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 -- @return Return value of os.execute() function flash(image, kpattern) diff --git a/libs/uci/luasrc/model/uci.lua b/libs/uci/luasrc/model/uci.lua index e4c5d5db7..6c4ae6ed8 100644 --- a/libs/uci/luasrc/model/uci.lua +++ b/libs/uci/luasrc/model/uci.lua @@ -23,11 +23,13 @@ See the License for the specific language governing permissions and limitations under the License. ]]-- -local uci = require("uci") -local util = require("luci.util") +local uci = require "uci" +local util = require "luci.util" +local table = require "table" + local setmetatable, rawget, rawset = setmetatable, rawget, rawset local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring -local table = table +local require = require --- LuCI UCI model library. module("luci.model.uci", function(m) setmetatable(m, {__index = uci}) end) @@ -37,6 +39,14 @@ confdir_default = "/etc/config" 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. -- @param config UCI config -- @param type UCI section type @@ -149,7 +159,6 @@ function get_list(config, section, option) end --- 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 section UCI section name -- @param option UCI option @@ -244,7 +253,6 @@ end -- @see unload --- 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 -- @name set -- @param config UCI config diff --git a/libs/web/luasrc/dispatcher.lua b/libs/web/luasrc/dispatcher.lua index 3ee42d72b..3cfa6c704 100644 --- a/libs/web/luasrc/dispatcher.lua +++ b/libs/web/luasrc/dispatcher.lua @@ -187,13 +187,15 @@ function dispatch(request) if not luci.util.contains(accs, user) 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 return else - local sid = luci.sys.uniqueid(16) + local sid = sess or luci.sys.uniqueid(16) luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") - luci.sauth.write(sid, user) + if not sess then + luci.sauth.write(sid, user) + end end else luci.http.status(403, "Forbidden") diff --git a/modules/rpc/luasrc/controller/rpc.lua b/modules/rpc/luasrc/controller/rpc.lua index a004d0dd9..aa77a8f24 100644 --- a/modules/rpc/luasrc/controller/rpc.lua +++ b/modules/rpc/luasrc/controller/rpc.lua @@ -12,15 +12,20 @@ You may obtain a copy of the License at $Id$ ]]-- -module("luci.controller.rpc", package.seeall) + +local require = require +local pairs = pairs +local print = print + +module "luci.controller.rpc" function index() local function authenticator(validator, accs) - local args = luci.dispatcher.context.args - if args and #args > 0 then - local user = luci.sauth.read(args[1]) + local auth = luci.http.formvalue("auth", true) + if auth then + local user = luci.sauth.read(auth) if user and luci.util.contains(accs, user) then - return user + return user, auth end end luci.http.status(403, "Forbidden") @@ -29,16 +34,25 @@ function index() uci = entry({"rpc", "uci"}, call("rpc_uci")) uci.sysauth = "root" 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")) end function rpc_auth() - require "luci.jsonrpc" - require "luci.sauth" + local jsonrpc = require "luci.jsonrpc" + local sauth = require "luci.sauth" + local http = require "luci.http" + local sys = require "luci.sys" - luci.http.setfilehandler() + http.setfilehandler() local loginstat @@ -46,21 +60,45 @@ function rpc_auth() server.login = function(user, pass) local sid - if luci.sys.user.checkpasswd(user, pass) then - sid = luci.sys.uniqueid(16) - luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") - luci.sauth.write(sid, user) + if sys.user.checkpasswd(user, pass) then + sid = sys.uniqueid(16) + http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") + sauth.write(sid, user) end return sid end - luci.http.prepare_content("application/json") - luci.http.write(luci.jsonrpc.handle(server, luci.http.content())) - - return loginstat + http.prepare_content("application/json") + http.write(jsonrpc.handle(server, http.content())) end 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 \ No newline at end of file diff --git a/modules/rpc/luasrc/controller/rpc/uci.lua b/modules/rpc/luasrc/controller/rpc/uci.lua new file mode 100644 index 000000000..2dab4e01a --- /dev/null +++ b/modules/rpc/luasrc/controller/rpc/uci.lua @@ -0,0 +1,93 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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 + diff --git a/modules/rpc/luasrc/jsonrpc.lua b/modules/rpc/luasrc/jsonrpc.lua index 84a7f7056..c4fed2acc 100644 --- a/modules/rpc/luasrc/jsonrpc.lua +++ b/modules/rpc/luasrc/jsonrpc.lua @@ -23,12 +23,12 @@ function resolve(mod, method) if not type(mod) == "table" then break end - mod = mod[path[j]] + mod = rawget(mod, path[j]) if not mod then break 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 return mod end -- 2.11.0