* Rewrote ffluci.http, ffluci.model.uci
authorSteven Barth <steven@midlink.org>
Mon, 5 May 2008 19:27:30 +0000 (19:27 +0000)
committerSteven Barth <steven@midlink.org>
Mon, 5 May 2008 19:27:30 +0000 (19:27 +0000)
* WARNING: API CHANGES FOR ffluci.http and ffluci.model.uci

26 files changed:
core/Makefile
core/contrib/webuci_bootstrap.lua [new file with mode: 0644]
core/src/ffluci/cbi.lua
core/src/ffluci/config.lua
core/src/ffluci/dispatcher.lua
core/src/ffluci/http.lua
core/src/ffluci/init.lua
core/src/ffluci/model/uci.lua
core/src/ffluci/model/uci/libuci.lua [new file with mode: 0644]
core/src/ffluci/model/uci/wrapper.lua [new file with mode: 0644]
core/src/ffluci/sgi/haserl.lua [new file with mode: 0644]
core/src/ffluci/template.lua
core/src/ffluci/view/header.htm
module/admin-core/src/controller/admin/index.lua
module/admin-core/src/controller/admin/system.lua
module/admin-core/src/controller/splash/splash.lua
module/admin-core/src/model/cbi/admin_network/dhcp.lua
module/admin-core/src/model/cbi/admin_network/routes.lua
module/admin-core/src/model/cbi/admin_services/olsrd.lua
module/admin-core/src/model/cbi/admin_services/splash.lua
module/admin-core/src/model/cbi/admin_wifi/networks.lua
module/public-core/src/view/public_index/contact.htm
module/public-core/src/view/public_index/index.htm
module/public-core/src/view/sudo_status/iwconfig.htm
module/public-core/src/view/sudo_status/iwscan.htm
module/rpc-core/src/controller/rpc/luciinfo.lua

index 6421a41..b497b3c 100644 (file)
@@ -3,12 +3,14 @@ LUAC_OPTIONS = -s
 
 FILES = ffluci/debug.lua ffluci/view/*.htm ffluci/view/cbi/*.htm ffluci/i18n/*
 
 
 FILES = ffluci/debug.lua ffluci/view/*.htm ffluci/view/cbi/*.htm ffluci/i18n/*
 
-CFILES = ffluci/bits.lua ffluci/util.lua ffluci/http.lua ffluci/fs.lua \
-ffluci/sys.lua ffluci/model/uci.lua ffluci/model/ipkg.lua \
-ffluci/config.lua ffluci/i18n.lua ffluci/template.lua \
+CFILES = ffluci/bits.lua ffluci/util.lua \
+ffluci/sgi/haserl.lua \
+ffluci/http.lua ffluci/fs.lua ffluci/sys.lua \
+ffluci/model/uci/wrapper.lua ffluci/model/uci/libuci.lua ffluci/model/uci.lua \
+ffluci/model/ipkg.lua ffluci/config.lua ffluci/i18n.lua ffluci/template.lua \
 ffluci/cbi.lua ffluci/dispatcher.lua ffluci/menu.lua ffluci/init.lua 
 
 ffluci/cbi.lua ffluci/dispatcher.lua ffluci/menu.lua ffluci/init.lua 
 
-DIRECTORIES = ffluci/model/cbi ffluci/model/menu ffluci/controller ffluci/i18n ffluci/view/cbi
+DIRECTORIES = ffluci/model/cbi ffluci/model/menu ffluci/controller ffluci/i18n ffluci/view/cbi ffluci/model/uci ffluci/sgi
 
 OUTDIRS = $(DIRECTORIES:%=dist/%)
 INFILES = $(CFILES:%=src/%)
 
 OUTDIRS = $(DIRECTORIES:%=dist/%)
 INFILES = $(CFILES:%=src/%)
diff --git a/core/contrib/webuci_bootstrap.lua b/core/contrib/webuci_bootstrap.lua
new file mode 100644 (file)
index 0000000..1733437
--- /dev/null
@@ -0,0 +1,2 @@
+package.path  = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
index f653e45..99d742b 100644 (file)
@@ -119,15 +119,10 @@ function Map.__init__(self, config, ...)
        self.config = config
        self.template = "cbi/map"
        self.uci = ffluci.model.uci.Session()
        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)
        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
 end
 
 -- Creates a child section
@@ -249,7 +244,7 @@ function AbstractSection.parse_optionals(self, section)
                end
        end
        
                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
                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))
        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
        
        for key,val in pairs(arr) do
                local create = true
@@ -440,14 +433,12 @@ function TypedSection.parse(self)
                
                -- Remove
                crval = "cbi.rts." .. self.config
                
                -- 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     
        end
        
        for i, k in ipairs(self:cfgsections()) do
        end
        
        for i, k in ipairs(self:cfgsections()) do
index 8b1a73d..90fa6b1 100644 (file)
@@ -45,7 +45,7 @@ main.lang = "de"
 
 
 -- Now overwrite with UCI values
 
 
 -- 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
 end
\ No newline at end of file
index 34e6a9d..15ac3c7 100644 (file)
@@ -87,9 +87,6 @@ require("ffluci.template")
 require("ffluci.config")
 require("ffluci.sys")
 
 require("ffluci.config")
 require("ffluci.sys")
 
-
-local tree = {}
-
 -- Sets privilege for given category
 function assign_privileges(category)
        local cp = ffluci.config.category_privileges
 -- 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
 
        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
 -- 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)
 
 -- 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
        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    
                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)
 
 -- 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
        
        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    
                print(message)
        end
        return false    
@@ -212,7 +222,7 @@ end
 -- Internal Dispatcher Functions --
 
 function _action(request)
 -- 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
        local i18n = require("ffluci.i18n")
        
        if action then
index 62b9da1..a2c524e 100644 (file)
@@ -27,86 +27,8 @@ limitations under the License.
 
 ]]--
 
 
 ]]--
 
-ENV = ENV or {}
-FORM = FORM or {}
 module("ffluci.http", package.seeall)
 
 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
index 7269087..8d4cea2 100644 (file)
@@ -25,5 +25,5 @@ limitations under the License.
 ]]--
 module("ffluci", package.seeall)
 
 ]]--
 module("ffluci", package.seeall)
 
-__version__ = "0.3"
+__version__ = "0.4"
 __appname__ = "FFLuCI"
 __appname__ = "FFLuCI"
index 75a898a..511c974 100644 (file)
@@ -1,14 +1,8 @@
 --[[
 --[[
-FFLuCI - UCI wrapper library
+FFLuCI - UCI mpdel
 
 Description:
 
 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$
 
 FileId:
 $Id$
@@ -30,24 +24,12 @@ limitations under the License.
 
 ]]--
 module("ffluci.model.uci", package.seeall)
 
 ]]--
 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
 end
 
 -- The default Session
@@ -61,156 +43,48 @@ end
 
 
 -- Wrapper for "uci add"
 
 
 -- 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 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 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 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 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 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 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"
 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(...)
 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
 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 (file)
index 0000000..8414fad
--- /dev/null
@@ -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 (file)
index 0000000..142e719
--- /dev/null
@@ -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 (file)
index 0000000..01c2083
--- /dev/null
@@ -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
index 797e9d1..04cc07d 100644 (file)
@@ -54,7 +54,7 @@ compiler_enable_bytecode = false
 viewns = {
        translate  = ffluci.i18n.translate,
        config     = function(...) return ffluci.model.uci.get(...) or "" end,
 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,      
        media      = ffluci.config.main.mediaurlbase,
        write      = io.write,
        include    = function(name) Template(name):render(getfenv(2)) end,      
index ac76e0a..7ed735d 100644 (file)
@@ -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")
 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">
 %><?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">
index 8bd04dd..09d5aa1 100644 (file)
@@ -6,10 +6,10 @@ function action_wizard()
        end
        
        local ifaces = {}
        end
        
        local ifaces = {}
-       local wldevs = ffluci.model.uci.show("wireless")
+       local wldevs = ffluci.model.uci.sections("wireless")
        
        if wldevs then
        
        if wldevs then
-               for k, v in pairs(wldevs.wireless) do
+               for k, v in pairs(wldevs) do
                        if v[".type"] == "wifi-device" then
                                table.insert(ifaces, k)
                        end
                        if v[".type"] == "wifi-device" then
                                table.insert(ifaces, k)
                        end
@@ -55,9 +55,9 @@ function configure_freifunk()
                uci:set("network", "ffdhcp", "ipaddr", dhcpip)
                uci:set("network", "ffdhcp", "netmask", uci:get("freifunk", "community", "dhcpmask"))
                
                uci:set("network", "ffdhcp", "ipaddr", dhcpip)
                uci:set("network", "ffdhcp", "netmask", uci:get("freifunk", "community", "dhcpmask"))
                
-               local dhcp = uci:show("dhcp")
+               local dhcp = uci:sections("dhcp")
                if dhcp then
                if dhcp then
-                       for k, v in pairs(dhcp.dhcp) do
+                       for k, v in pairs(dhcp) do
                                if v[".type"] == "dhcp" and v.interface == "ffdhcp" then
                                        uci:del("dhcp", k)
                                end
                                if v[".type"] == "dhcp" and v.interface == "ffdhcp" then
                                        uci:del("dhcp", k)
                                end
@@ -72,9 +72,9 @@ function configure_freifunk()
                        uci:set("dhcp", sk, "leasetime", "30m")
                end 
                
                        uci:set("dhcp", sk, "leasetime", "30m")
                end 
                
-               local splash = uci:show("luci_splash")
+               local splash = uci:sections("luci_splash")
                if splash then
                if splash then
-                       for k, v in pairs(splash.luci_splash) do
+                       for k, v in pairs(splash) do
                                if v[".type"] == "iface" then
                                        uci:del("luci_splash", k)
                                end
                                if v[".type"] == "iface" then
                                        uci:del("luci_splash", k)
                                end
@@ -86,8 +86,8 @@ function configure_freifunk()
        end
        
        -- Configure OLSR
        end
        
        -- Configure OLSR
-       if ffluci.http.formvalue("olsr") and uci:show("olsr") then
-               for k, v in pairs(uci:show("olsr").olsr) do
+       if ffluci.http.formvalue("olsr") and uci:sections("olsr") then
+               for k, v in pairs(uci:sections("olsr")) do
                        if v[".type"] == "Interface" or v[".type"] == "LoadPlugin" then
                                uci:del("olsr", k)
                        end
                        if v[".type"] == "Interface" or v[".type"] == "LoadPlugin" then
                                uci:del("olsr", k)
                        end
@@ -122,14 +122,13 @@ function configure_freifunk()
        end
        
        -- Configure Wifi
        end
        
        -- Configure Wifi
-       local wifi = ffluci.http.formvalue("wifi")
-       local wcfg = uci:show("wireless")
-       if type(wifi) == "table" and wcfg then
-               for iface, v in pairs(wifi) do
-                       if wcfg.wireless[iface] then
+       local wcfg = uci:sections("wireless")
+       if wcfg then
+               for iface, v in pairs(wcfg) do
+                       if v[".type"] == "wifi-device" and ffluci.http.formvalue("wifi."..iface) then
                                -- Cleanup
                                -- Cleanup
-                               for k, v in pairs(wcfg.wireless) do
-                                       if v[".type"] == "wifi-iface" and v.device == iface then
+                               for k, j in pairs(wcfg) do
+                                       if j[".type"] == "wifi-iface" and j.device == iface then
                                                uci:del("wireless", k)
                                        end
                                end
                                                uci:del("wireless", k)
                                        end
                                end
@@ -152,5 +151,5 @@ function configure_freifunk()
        end
                
 
        end
                
 
-       ffluci.http.request_redirect("admin", "uci", "changes")
+       ffluci.http.redirect(ffluci.dispatcher.build_url("admin", "uci", "changes"))
 end
\ No newline at end of file
 end
\ No newline at end of file
index b0763d8..7a927d6 100644 (file)
@@ -61,8 +61,7 @@ function action_packages()
        
        
        -- Packets to be installed
        
        
        -- Packets to be installed
-       local install = ffluci.http.formvalue("install")
-       install = (type(install) == "table" and submit) and install or nil
+       local install = submit and ffluci.http.formvaluetable("install")
        
        -- Install from URL
        local url = ffluci.http.formvalue("url")
        
        -- Install from URL
        local url = ffluci.http.formvalue("url")
@@ -73,7 +72,7 @@ function action_packages()
                install[url] = 1
        end
        
                install[url] = 1
        end
        
-       -- Do install           
+       -- Do install
        if install then
                for k, v in pairs(install) do
                        void, install[k] = ipkg.install(k)
        if install then
                for k, v in pairs(install) do
                        void, install[k] = ipkg.install(k)
@@ -82,8 +81,7 @@ function action_packages()
        
        
        -- Remove packets
        
        
        -- Remove packets
-       local remove = ffluci.http.formvalue("remove")
-       remove = (type(remove) == "table" and submit) and remove or nil
+       local remove = submit and ffluci.http.formvaluetable("remove")
        if remove then  
                for k, v in pairs(remove) do
                        void, remove[k] = ipkg.remove(k)
        if remove then  
                for k, v in pairs(remove) do
                        void, remove[k] = ipkg.remove(k)
@@ -187,7 +185,7 @@ function action_upgrade()
        if plat and imgname then
                local kpattern = nil
                if keepcfg then
        if plat and imgname then
                local kpattern = nil
                if keepcfg then
-                       local files = ffluci.model.uci.show("luci", "flash_keep")
+                       local files = ffluci.model.uci.sections("luci").flash_keep
                        if files.luci and files.luci.flash_keep then
                                kpattern = ""
                                for k,v in pairs(files.luci.flash_keep) do
                        if files.luci and files.luci.flash_keep then
                                kpattern = ""
                                for k,v in pairs(files.luci.flash_keep) do
index 4e8a79a..7e3d67e 100644 (file)
@@ -6,14 +6,14 @@ function action_activate()
                os.execute("luci-splash add "..mac.." >/dev/null 2>&1")
                ffluci.http.redirect(ffluci.model.uci.get("freifunk", "community", "homepage"))
        else
                os.execute("luci-splash add "..mac.." >/dev/null 2>&1")
                ffluci.http.redirect(ffluci.model.uci.get("freifunk", "community", "homepage"))
        else
-               ffluci.http.request_redirect()
+               ffluci.http.redirect(ffluci.dispatcher.build_url())
        end
 end
 
 function action_accepted()
        end
 end
 
 function action_accepted()
-       ffluci.http.request_redirect()
+       ffluci.http.redirect(ffluci.dispatcher.build_url())
 end
 
 function action_unknown()
 end
 
 function action_unknown()
-       ffluci.http.request_redirect()
+       ffluci.http.redirect(ffluci.dispatcher.build_url())
 end
\ No newline at end of file
 end
\ No newline at end of file
index c8f1007..caac277 100644 (file)
@@ -10,7 +10,7 @@ s.addremove = true
 s.anonymous = true
 
 iface = s:option(ListValue, "interface", "Schnittstelle")
 s.anonymous = true
 
 iface = s:option(ListValue, "interface", "Schnittstelle")
-for k, v in pairs(ffluci.model.uci.show("network").network) do
+for k, v in pairs(ffluci.model.uci.sections("network")) do
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
                s:depends("interface", k) -- Only change sections with existing interfaces
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
                s:depends("interface", k) -- Only change sections with existing interfaces
index 35f5423..49e4321 100644 (file)
@@ -8,7 +8,7 @@ s.addremove = true
 s.anonymous = true
 
 iface = s:option(ListValue, "interface", "Schnittstelle")
 s.anonymous = true
 
 iface = s:option(ListValue, "interface", "Schnittstelle")
-for k, v in pairs(ffluci.model.uci.show("network").network) do
+for k, v in pairs(ffluci.model.uci.sections("network")) do
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
        end
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
        end
index 1090601..8431a81 100644 (file)
@@ -51,7 +51,7 @@ i.dynamic = true
 
 network = i:option(ListValue, "Interface", "Netzwerkschnittstellen")
 network:value("")
 
 network = i:option(ListValue, "Interface", "Netzwerkschnittstellen")
 network:value("")
-for k, v in pairs(ffluci.model.uci.show("network").network) do
+for k, v in pairs(ffluci.model.uci.sections("network")) do
        if v[".type"] == "interface" and k ~= "loopback" then
                network:value(k)
        end
        if v[".type"] == "interface" and k ~= "loopback" then
                network:value(k)
        end
index d3c3f0a..fe4d2c3 100644 (file)
@@ -11,7 +11,7 @@ s.addremove = true
 s.anonymous = true
 
 iface = s:option(ListValue, "network", "Schnittstelle")
 s.anonymous = true
 
 iface = s:option(ListValue, "network", "Schnittstelle")
-for k, v in pairs(ffluci.model.uci.show("network").network) do
+for k, v in pairs(ffluci.model.uci.sections("network")) do
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
        end
        if v[".type"] == "interface" and k ~= "loopback" then
                iface:value(k)
        end
index feb2c74..4a7ad12 100644 (file)
@@ -11,7 +11,7 @@ s.anonymous = true
 s:option(Value, "ssid", "Netzkennung (ESSID)").maxlength = 32
 
 device = s:option(ListValue, "device", "Gerät")
 s:option(Value, "ssid", "Netzkennung (ESSID)").maxlength = 32
 
 device = s:option(ListValue, "device", "Gerät")
-local d = ffluci.model.uci.show("wireless").wireless
+local d = ffluci.model.uci.sections("wireless")
 if d then
        for k, v in pairs(d) do
                if v[".type"] == "wifi-device" then
 if d then
        for k, v in pairs(d) do
                if v[".type"] == "wifi-device" then
@@ -22,7 +22,7 @@ end
 
 network = s:option(ListValue, "network", "Netzwerk", "WLAN-Netz zu Netzwerk hinzufügen")
 network:value("")
 
 network = s:option(ListValue, "network", "Netzwerk", "WLAN-Netz zu Netzwerk hinzufügen")
 network:value("")
-for k, v in pairs(ffluci.model.uci.show("network").network) do
+for k, v in pairs(ffluci.model.uci.sections("network")) do
        if v[".type"] == "interface" and k ~= "loopback" then
                network:value(k)
        end
        if v[".type"] == "interface" and k ~= "loopback" then
                network:value(k)
        end
index df34812..221dc89 100644 (file)
@@ -1,5 +1,5 @@
 <%+header%>
 <%+header%>
-<% local contact = ffluci.model.uci.show("freifunk").freifunk.contact %>
+<% local contact = ffluci.model.uci.sections("freifunk").contact %>
 <h1><%:contact Kontakt%></h1>
 <table cellspacing="0" cellpadding="6">
        <tr><th><%:nickname Pseudonym%>:</th><td><%=contact.nickname%></td></tr>
 <h1><%:contact Kontakt%></h1>
 <table cellspacing="0" cellpadding="6">
        <tr><th><%:nickname Pseudonym%>:</th><td><%=contact.nickname%></td></tr>
index a8a469e..6c7fe85 100644 (file)
@@ -1,5 +1,5 @@
 <%+header%>
 <%+header%>
-<% local ff = ffluci.model.uci.show("freifunk").freifunk %>
+<% local ff = ffluci.model.uci.sections("freifunk") %>
 <h1><%:hellonet Hallo und willkommen im Netz von%> <%=ff.community.name%>!</h1>
 <p><%:public1 Wir sind eine Initiative zur Schaffung eines freien, offenen und unabhängigen Funknetzwerks auf WLAN-Basis.%><br />
 <%:public2 Dies ist der Zugangspunkt %><%=ffluci.sys.hostname()%>. <%:public3 Er wird betrieben von %>
 <h1><%:hellonet Hallo und willkommen im Netz von%> <%=ff.community.name%>!</h1>
 <p><%:public1 Wir sind eine Initiative zur Schaffung eines freien, offenen und unabhängigen Funknetzwerks auf WLAN-Basis.%><br />
 <%:public2 Dies ist der Zugangspunkt %><%=ffluci.sys.hostname()%>. <%:public3 Er wird betrieben von %>
index e06b631..92371ef 100644 (file)
@@ -1,5 +1,5 @@
 <%
 <%
-ffluci.http.textheader()
+ffluci.http.set_content_type("text/plain")
 for k, v in pairs(ffluci.sys.wifi.getiwconfig()) do
 %>
 <tr>
 for k, v in pairs(ffluci.sys.wifi.getiwconfig()) do
 %>
 <tr>
index 8a1ee72..f426857 100644 (file)
@@ -1,5 +1,5 @@
 <%
 <%
-ffluci.http.textheader()
+ffluci.http.set_content_type("text/plain")
 for iface, cells in pairs(ffluci.sys.wifi.iwscan()) do
        for i, cell in ipairs(cells) do 
 %>
 for iface, cells in pairs(ffluci.sys.wifi.iwscan()) do
        for i, cell in ipairs(cells) do 
 %>
index 8d10fa8..d4e5cb3 100644 (file)
@@ -3,7 +3,7 @@ module("ffluci.controller.rpc.luciinfo", package.seeall)
 function action_index()
        local uci = ffluci.model.uci.StateSession()
 
 function action_index()
        local uci = ffluci.model.uci.StateSession()
 
-       ffluci.http.textheader()
+       ffluci.http.set_content_type("text/plain")
        
        -- General
        print("luciinfo.api=1")
        
        -- General
        print("luciinfo.api=1")
@@ -26,8 +26,14 @@ function action_index()
 
        
        -- Freifunk
 
        
        -- Freifunk
-       local ff = uci:show("freifunk", true) or ""
-       print(ff)
+       local ff = uci:sections("freifunk") or {}
+       for k, v in pairs(ff) do
+               if k:sub(1, 1) ~= "." then
+                       for i, j in pairs(v) do
+                               print("freifunk." .. k .. "." .. i .. "=" .. j)
+                       end
+               end
+       end
 end
 
 function sanitize(val)
 end
 
 function sanitize(val)