diff options
Diffstat (limited to 'core/src/ffluci')
-rw-r--r-- | core/src/ffluci/cbi.lua | 33 | ||||
-rw-r--r-- | core/src/ffluci/config.lua | 6 | ||||
-rw-r--r-- | core/src/ffluci/dispatcher.lua | 24 | ||||
-rw-r--r-- | core/src/ffluci/http.lua | 84 | ||||
-rw-r--r-- | core/src/ffluci/init.lua | 2 | ||||
-rw-r--r-- | core/src/ffluci/model/uci.lua | 146 | ||||
-rw-r--r-- | core/src/ffluci/model/uci/libuci.lua | 162 | ||||
-rw-r--r-- | core/src/ffluci/model/uci/wrapper.lua | 165 | ||||
-rw-r--r-- | core/src/ffluci/sgi/haserl.lua | 89 | ||||
-rw-r--r-- | core/src/ffluci/template.lua | 2 | ||||
-rw-r--r-- | core/src/ffluci/view/header.htm | 2 |
11 files changed, 464 insertions, 251 deletions
diff --git a/core/src/ffluci/cbi.lua b/core/src/ffluci/cbi.lua index f653e457d..99d742b99 100644 --- a/core/src/ffluci/cbi.lua +++ b/core/src/ffluci/cbi.lua @@ -119,15 +119,10 @@ function Map.__init__(self, config, ...) self.config = config self.template = "cbi/map" self.uci = ffluci.model.uci.Session() - self.ucidata = self.uci:show(self.config) + self.ucidata = self.uci:sections(self.config) if not self.ucidata then error("Unable to read UCI data: " .. self.config) - else - if not self.ucidata[self.config] then - self.ucidata[self.config] = {} - end - self.ucidata = self.ucidata[self.config] - end + end end -- Creates a child section @@ -249,7 +244,7 @@ function AbstractSection.parse_optionals(self, section) end end - if field and field:len() > 0 and self.dynamic then + if field and #field > 0 and self.dynamic then self:add_dynamic(field) end end @@ -267,12 +262,10 @@ function AbstractSection.parse_dynamic(self, section) end local arr = ffluci.util.clone(self:cfgvalue(section)) - local form = ffluci.http.formvalue("cbid."..self.config.."."..section) - if type(form) == "table" then - for k,v in pairs(form) do - arr[k] = v - end - end + local form = ffluci.http.formvaluetable("cbid."..self.config.."."..section) + for k, v in pairs(form) do + arr[k] = v + end for key,val in pairs(arr) do local create = true @@ -440,14 +433,12 @@ function TypedSection.parse(self) -- Remove crval = "cbi.rts." .. self.config - name = ffluci.http.formvalue(crval) - if type(name) == "table" then - for k,v in pairs(name) do - if self:cfgvalue(k) and self:checkscope(k) then - self:remove(k) - end + name = ffluci.http.formvaluetable(crval) + for k,v in pairs(name) do + if self:cfgvalue(k) and self:checkscope(k) then + self:remove(k) end - end + end end for i, k in ipairs(self:cfgsections()) do diff --git a/core/src/ffluci/config.lua b/core/src/ffluci/config.lua index 8b1a73dc7..90fa6b1c9 100644 --- a/core/src/ffluci/config.lua +++ b/core/src/ffluci/config.lua @@ -45,7 +45,7 @@ main.lang = "de" -- Now overwrite with UCI values -local ucidata = ffluci.model.uci.show("luci") -if ucidata and ucidata.luci then - ffluci.util.update(ffluci.config, ucidata.luci) +local ucidata = ffluci.model.uci.sections("luci") +if ucidata then + ffluci.util.update(ffluci.config, ucidata) end
\ No newline at end of file diff --git a/core/src/ffluci/dispatcher.lua b/core/src/ffluci/dispatcher.lua index 34e6a9d6d..15ac3c7b3 100644 --- a/core/src/ffluci/dispatcher.lua +++ b/core/src/ffluci/dispatcher.lua @@ -87,9 +87,6 @@ require("ffluci.template") require("ffluci.config") require("ffluci.sys") - -local tree = {} - -- Sets privilege for given category function assign_privileges(category) local cp = ffluci.config.category_privileges @@ -100,6 +97,18 @@ function assign_privileges(category) end end + +-- Builds a URL from a triple of category, module and action +function build_url(category, module, action) + category = category or "public" + module = module or "index" + action = action or "index" + + local pattern = ffluci.http.get_script_name() .. "/%s/%s/%s" + return pattern:format(category, module, action) +end + + -- Dispatches the "request" function dispatch(req) request = req @@ -117,10 +126,11 @@ end -- Sends a 404 error code and renders the "error404" template if available function error404(message) + ffluci.http.set_status(404, "Not Found") message = message or "Not Found" if not pcall(ffluci.template.render, "error404") then - ffluci.http.textheader() + ffluci.http.set_content_type("text/plain") print(message) end return false @@ -128,10 +138,10 @@ end -- Sends a 500 error code and renders the "error500" template if available function error500(message) - ffluci.http.status(500, "Internal Server Error") + ffluci.http.set_status(500, "Internal Server Error") if not pcall(ffluci.template.render, "error500", {message=message}) then - ffluci.http.textheader() + ffluci.http.set_content_type("text/plain") print(message) end return false @@ -212,7 +222,7 @@ end -- Internal Dispatcher Functions -- function _action(request) - local action = getfenv()["action_" .. request.action:gsub("-", "_")] + local action = getfenv(2)["action_" .. request.action:gsub("-", "_")] local i18n = require("ffluci.i18n") if action then diff --git a/core/src/ffluci/http.lua b/core/src/ffluci/http.lua index 62b9da113..a2c524ed6 100644 --- a/core/src/ffluci/http.lua +++ b/core/src/ffluci/http.lua @@ -27,86 +27,8 @@ limitations under the License. ]]-- -ENV = ENV or {} -FORM = FORM or {} module("ffluci.http", package.seeall) -require("ffluci.util") - --- Sets HTTP-Status-Header -function status(code, message) - print("Status: " .. tostring(code) .. " " .. message) -end - - --- Asks the browser to redirect to "url" -function redirect(url, qs) - if qs then - url = url .. "?" .. qs - end - - status(302, "Found") - print("Location: " .. url .. "\n") -end - - --- Same as redirect but accepts category, module and action for internal use -function request_redirect(category, module, action, ...) - category = category or "public" - module = module or "index" - action = action or "index" - - local pattern = script_name() .. "/%s/%s/%s" - redirect(pattern:format(category, module, action), ...) -end - - --- Returns the User's IP -function remote_addr() - return ENV.REMOTE_ADDR -end - - --- Returns the script name -function script_name() - return ENV.SCRIPT_NAME -end - - --- Gets form value from key -function formvalue(key, default) - local c = formvalues() - - for match in key:gmatch("[%w-_]+") do - c = c[match] - if c == nil then - return default - end - end - - return c -end - - --- Returns a table of all COOKIE, GET and POST Parameters -function formvalues() - return FORM -end - - --- Prints plaintext content-type header -function textheader() - print("Content-Type: text/plain\n") -end - - --- Prints html content-type header -function htmlheader() - print("Content-Type: text/html\n") -end - - --- Prints xml content-type header -function xmlheader() - print("Content-Type: text/xml\n") -end +if ENV and ENV.HASERLVER then + require("ffluci.sgi.haserl") +end
\ No newline at end of file diff --git a/core/src/ffluci/init.lua b/core/src/ffluci/init.lua index 7269087c1..8d4cea2e9 100644 --- a/core/src/ffluci/init.lua +++ b/core/src/ffluci/init.lua @@ -25,5 +25,5 @@ limitations under the License. ]]-- module("ffluci", package.seeall) -__version__ = "0.3" +__version__ = "0.4" __appname__ = "FFLuCI" diff --git a/core/src/ffluci/model/uci.lua b/core/src/ffluci/model/uci.lua index 75a898acb..511c97433 100644 --- a/core/src/ffluci/model/uci.lua +++ b/core/src/ffluci/model/uci.lua @@ -1,14 +1,8 @@ --[[ -FFLuCI - UCI wrapper library +FFLuCI - UCI mpdel Description: -Wrapper for the /sbin/uci application, syntax of implemented functions -is comparable to the syntax of the uci application - -Any return value of false or nil can be interpreted as an error - - -ToDo: Reimplement in Lua +Generalized UCI model FileId: $Id$ @@ -30,24 +24,12 @@ limitations under the License. ]]-- module("ffluci.model.uci", package.seeall) -require("ffluci.util") -require("ffluci.fs") -require("ffluci.sys") - --- The OS uci command -ucicmd = "uci" - --- Session class -Session = ffluci.util.class() - --- Session constructor -function Session.__init__(self, path, uci) - uci = uci or ucicmd - if path then - self.ucicmd = uci .. " -P " .. path - else - self.ucicmd = uci - end + +-- Test whether to load libuci-Wrapper or /sbin/uci-Wrapper +if pcall(require, "uci") then + Session = require("ffluci.model.uci.libuci").Session +else + Session = require("ffluci.model.uci.wrapper").Session end -- The default Session @@ -61,156 +43,48 @@ end -- Wrapper for "uci add" -function Session.add(self, config, section_type) - return self:_uci("add " .. _path(config) .. " " .. _path(section_type)) -end - function add(...) return default:add(...) end -- Wrapper for "uci changes" -function Session.changes(self, config) - return self:_uci("changes " .. _path(config)) -end - function changes(...) return default:changes(...) end -- Wrapper for "uci commit" -function Session.commit(self, config) - return self:_uci2("commit " .. _path(config)) -end - function commit(...) return default:commit(...) end -- Wrapper for "uci del" -function Session.del(self, config, section, option) - return self:_uci2("del " .. _path(config, section, option)) -end - function del(...) return default:del(...) end -- Wrapper for "uci get" -function Session.get(self, config, section, option) - return self:_uci("get " .. _path(config, section, option)) -end - function get(...) return default:get(...) end -- Wrapper for "uci revert" -function Session.revert(self, config) - return self:_uci2("revert " .. _path(config)) -end - function revert(...) return default:revert(...) end -- Wrapper for "uci show" -function Session.show(self, config, ...) - return self:_uci3("show " .. _path(config), ...) -end - -function show(...) - return default:show(...) +function sections(...) + return default:sections(...) end -- Wrapper for "uci set" -function Session.set(self, config, section, option, value) - return self:_uci2("set " .. _path(config, section, option, value)) -end - function set(...) return default:set(...) -end - - --- Internal functions -- - -function Session._uci(self, cmd) - local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd) - - if res:len() == 0 then - return nil - else - return res:sub(1, res:len()-1) - end -end - -function Session._uci2(self, cmd) - local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd) - - if res:len() > 0 then - return false, res - else - return true - end -end - -function Session._uci3(self, cmd, raw) - local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd) - if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then - return nil, res[1] - end - - if raw then - return table.concat(res, "\n") - end - - tbl = {} - - for k,line in pairs(res) do - c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$") - if c then - tbl[c] = tbl[c] or {} - tbl[c][".order"] = tbl[c][".order"] or {} - - tbl[c][s] = {} - table.insert(tbl[c][".order"], s) - tbl[c][s][".type"] = t - end - - c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$") - if c then - tbl[c][s][o] = v - end - end - - return tbl -end - --- Build path (config.section.option=value) and prevent command injection -function _path(...) - local result = "" - - -- Not using ipairs because it is not reliable in case of nil arguments - arg.n = nil - for k,v in pairs(arg) do - if v then - v = tostring(v) - if k == 1 then - result = "'" .. v:gsub("['.]", "") .. "'" - elseif k < 4 then - result = result .. ".'" .. v:gsub("['.]", "") .. "'" - elseif k == 4 then - result = result .. "='" .. v:gsub("'", "") .. "'" - end - end - end - return result end
\ No newline at end of file diff --git a/core/src/ffluci/model/uci/libuci.lua b/core/src/ffluci/model/uci/libuci.lua new file mode 100644 index 000000000..8414fadc4 --- /dev/null +++ b/core/src/ffluci/model/uci/libuci.lua @@ -0,0 +1,162 @@ +--[[ +FFLuCI - UCI libuci wrapper + +Description: +Wrapper for the libuci Lua bindings + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +module("ffluci.model.uci.libuci", package.seeall) + +require("ffluci.util") +require("ffluci.fs") +require("ffluci.sys") + +-- The OS uci command +ucicmd = "uci" + +-- Session class +Session = ffluci.util.class() + +-- Session constructor +function Session.__init__(self, path, uci) + uci = uci or ucicmd + if path then + self.ucicmd = uci .. " -P " .. path + else + self.ucicmd = uci + end +end + +function Session.add(self, config, section_type) + return self:_uci("add " .. _path(config) .. " " .. _path(section_type)) +end + +function Session.changes(self, config) + return self:_uci("changes " .. _path(config)) +end + +function Session.commit(self, config) + return self:_uci2("commit " .. _path(config)) +end + +function Session.del(self, config, section, option) + return self:_uci2("del " .. _path(config, section, option)) +end + +function Session.get(self, config, section, option) + return self:_uci("get " .. _path(config, section, option)) +end + +function Session.revert(self, config) + return self:_uci2("revert " .. _path(config)) +end + +function Session.sections(self, config) + if not config then + return nil + end + + local r1, r2 = self:_uci3("show " .. _path(config)) + if type(r1) == "table" then + return r1[config] + else + return nil, r2 + end +end + +function Session.set(self, config, section, option, value) + return self:_uci2("set " .. _path(config, section, option, value)) +end + + + +-- Internal functions -- + + +function Session._uci(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd) + + if res:len() == 0 then + return nil + else + return res:sub(1, res:len()-1) + end +end + +function Session._uci2(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd) + + if res:len() > 0 then + return false, res + else + return true + end +end + +function Session._uci3(self, cmd) + local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd) + if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then + return nil, res[1] + end + + tbl = {} + + for k,line in pairs(res) do + c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[c] = tbl[c] or {} + tbl[c][".order"] = tbl[c][".order"] or {} + + tbl[c][s] = {} + table.insert(tbl[c][".order"], s) + tbl[c][s][".type"] = t + end + + c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[c][s][o] = v + end + end + + return tbl +end + +-- Build path (config.section.option=value) and prevent command injection +function _path(...) + local result = "" + + -- Not using ipairs because it is not reliable in case of nil arguments + arg.n = nil + for k,v in pairs(arg) do + if v then + v = tostring(v) + if k == 1 then + result = "'" .. v:gsub("['.]", "") .. "'" + elseif k < 4 then + result = result .. ".'" .. v:gsub("['.]", "") .. "'" + elseif k == 4 then + result = result .. "='" .. v:gsub("'", "") .. "'" + end + end + end + return result +end
\ No newline at end of file diff --git a/core/src/ffluci/model/uci/wrapper.lua b/core/src/ffluci/model/uci/wrapper.lua new file mode 100644 index 000000000..142e71958 --- /dev/null +++ b/core/src/ffluci/model/uci/wrapper.lua @@ -0,0 +1,165 @@ +--[[ +FFLuCI - UCI wrapper library + +Description: +Wrapper for the /sbin/uci application, syntax of implemented functions +is comparable to the syntax of the uci application + +Any return value of false or nil can be interpreted as an error + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +module("ffluci.model.uci.wrapper", package.seeall) + +require("ffluci.util") +require("ffluci.fs") +require("ffluci.sys") + +-- The OS uci command +ucicmd = "uci" + +-- Session class +Session = ffluci.util.class() + +-- Session constructor +function Session.__init__(self, path, uci) + uci = uci or ucicmd + if path then + self.ucicmd = uci .. " -P " .. path + else + self.ucicmd = uci + end +end + +function Session.add(self, config, section_type) + return self:_uci("add " .. _path(config) .. " " .. _path(section_type)) +end + +function Session.changes(self, config) + return self:_uci("changes " .. _path(config)) +end + +function Session.commit(self, config) + return self:_uci2("commit " .. _path(config)) +end + +function Session.del(self, config, section, option) + return self:_uci2("del " .. _path(config, section, option)) +end + +function Session.get(self, config, section, option) + return self:_uci("get " .. _path(config, section, option)) +end + +function Session.revert(self, config) + return self:_uci2("revert " .. _path(config)) +end + +function Session.sections(self, config) + if not config then + return nil + end + + local r1, r2 = self:_uci3("show " .. _path(config)) + if type(r1) == "table" then + return r1[config] + else + return nil, r2 + end +end + +function Session.set(self, config, section, option, value) + return self:_uci2("set " .. _path(config, section, option, value)) +end + + + +-- Internal functions -- + + +function Session._uci(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd) + + if res:len() == 0 then + return nil + else + return res:sub(1, res:len()-1) + end +end + +function Session._uci2(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd) + + if res:len() > 0 then + return false, res + else + return true + end +end + +function Session._uci3(self, cmd) + local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd) + if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then + return nil, res[1] + end + + tbl = {} + + for k,line in pairs(res) do + c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[c] = tbl[c] or {} + tbl[c][".order"] = tbl[c][".order"] or {} + + tbl[c][s] = {} + table.insert(tbl[c][".order"], s) + tbl[c][s][".type"] = t + end + + c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[c][s][o] = v + end + end + + return tbl +end + +-- Build path (config.section.option=value) and prevent command injection +function _path(...) + local result = "" + + -- Not using ipairs because it is not reliable in case of nil arguments + arg.n = nil + for k,v in pairs(arg) do + if v then + v = tostring(v) + if k == 1 then + result = "'" .. v:gsub("['.]", "") .. "'" + elseif k < 4 then + result = result .. ".'" .. v:gsub("['.]", "") .. "'" + elseif k == 4 then + result = result .. "='" .. v:gsub("'", "") .. "'" + end + end + end + return result +end
\ No newline at end of file diff --git a/core/src/ffluci/sgi/haserl.lua b/core/src/ffluci/sgi/haserl.lua new file mode 100644 index 000000000..01c2083c2 --- /dev/null +++ b/core/src/ffluci/sgi/haserl.lua @@ -0,0 +1,89 @@ +--[[ +FFLuCI - SGI-Module for Haserl + +Description: +Server Gateway Interface for Haserl + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("ffluci.sgi.haserl", package.seeall) + +ENV = ENV or {} +FORM = FORM or {} +require("ffluci.util") + +-- HTTP interface + +-- Returns a table of all COOKIE, GET and POST Parameters +function ffluci.http.formvalues(prefix) + return FORM +end + +-- Gets form value from key +function ffluci.http.formvalue(key, default) + local c = ffluci.http.formvalues() + + for match in key:gmatch("[%w-_]+") do + c = c[match] + if c == nil then + return default + end + end + + return c +end + +-- Gets a table of values with a certain prefix +function ffluci.http.formvaluetable(prefix) + return formvalue(prefix, {}) +end + + +-- Returns the User's IP +function ffluci.http.get_remote_addr() + return ENV.REMOTE_ADDR +end + +-- Returns the script name +function ffluci.http.get_script_name() + return ENV.SCRIPT_NAME +end + + +-- Asks the browser to redirect to "url" +function ffluci.http.redirect(url, qs) + if qs then + url = url .. "?" .. qs + end + + set_status(302, "Found") + print("Location: " .. url .. "\n") +end + + +-- Set Content-Type +function ffluci.http.set_content_type(type) + print("Content-Type: "..type.."\n") +end + +-- Sets HTTP-Status-Header +function ffluci.http.set_status(code, message) + print("Status: " .. tostring(code) .. " " .. message) +end diff --git a/core/src/ffluci/template.lua b/core/src/ffluci/template.lua index 797e9d127..04cc07dbb 100644 --- a/core/src/ffluci/template.lua +++ b/core/src/ffluci/template.lua @@ -54,7 +54,7 @@ compiler_enable_bytecode = false viewns = { translate = ffluci.i18n.translate, config = function(...) return ffluci.model.uci.get(...) or "" end, - controller = ffluci.http.script_name(), + controller = ffluci.http.get_script_name(), media = ffluci.config.main.mediaurlbase, write = io.write, include = function(name) Template(name):render(getfenv(2)) end, diff --git a/core/src/ffluci/view/header.htm b/core/src/ffluci/view/header.htm index ac76e0ab5..7ed735de5 100644 --- a/core/src/ffluci/view/header.htm +++ b/core/src/ffluci/view/header.htm @@ -5,7 +5,7 @@ local req = require("ffluci.dispatcher").request local menu = require("ffluci.menu").get()[req.category] menu = menu or {} require("ffluci.i18n").loadc("default") -require("ffluci.http").htmlheader() +require("ffluci.http").set_content_type("text/html") %><?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> |