8414fadc42e737e4527ebd63b90e34dc1d22de66
[project/luci.git] / core / src / ffluci / model / uci / libuci.lua
1 --[[
2 FFLuCI - UCI libuci wrapper
3
4 Description:
5 Wrapper for the libuci Lua bindings
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at 
16
17         http://www.apache.org/licenses/LICENSE-2.0 
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26
27 module("ffluci.model.uci.libuci", package.seeall)
28
29 require("ffluci.util")
30 require("ffluci.fs")
31 require("ffluci.sys")
32
33 -- The OS uci command
34 ucicmd = "uci"
35
36 -- Session class
37 Session = ffluci.util.class()
38
39 -- Session constructor
40 function Session.__init__(self, path, uci)
41         uci = uci or ucicmd
42         if path then
43                 self.ucicmd = uci .. " -P " .. path 
44         else
45                 self.ucicmd = uci
46         end
47 end
48
49 function Session.add(self, config, section_type)
50         return self:_uci("add " .. _path(config) .. " " .. _path(section_type))
51 end
52
53 function Session.changes(self, config)
54         return self:_uci("changes " .. _path(config))
55 end
56
57 function Session.commit(self, config)
58         return self:_uci2("commit " .. _path(config))
59 end
60
61 function Session.del(self, config, section, option)
62         return self:_uci2("del " .. _path(config, section, option))
63 end
64
65 function Session.get(self, config, section, option)
66         return self:_uci("get " .. _path(config, section, option))
67 end
68
69 function Session.revert(self, config)
70         return self:_uci2("revert " .. _path(config))
71 end
72
73 function Session.sections(self, config) 
74         if not config then
75                 return nil
76         end
77         
78         local r1, r2 = self:_uci3("show " .. _path(config))
79         if type(r1) == "table" then
80                 return r1[config]
81         else
82                 return nil, r2
83         end
84 end
85
86 function Session.set(self, config, section, option, value)
87         return self:_uci2("set " .. _path(config, section, option, value))
88 end
89
90
91
92 -- Internal functions --
93
94
95 function Session._uci(self, cmd)
96         local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd)
97         
98         if res:len() == 0 then
99                 return nil
100         else
101                 return res:sub(1, res:len()-1)
102         end     
103 end
104
105 function Session._uci2(self, cmd)
106         local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd)
107         
108         if res:len() > 0 then
109                 return false, res
110         else
111                 return true
112         end     
113 end
114
115 function Session._uci3(self, cmd)
116         local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd)
117         if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then
118                 return nil, res[1]
119         end
120
121         tbl = {}
122
123         for k,line in pairs(res) do
124                 c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$")
125                 if c then
126                         tbl[c] = tbl[c] or {}
127                         tbl[c][".order"] = tbl[c][".order"] or {}
128                         
129                         tbl[c][s] = {}
130                         table.insert(tbl[c][".order"], s)
131                         tbl[c][s][".type"] = t
132                 end
133         
134                 c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$")
135                 if c then
136                         tbl[c][s][o] = v
137                 end
138         end
139         
140         return tbl
141 end
142
143 -- Build path (config.section.option=value) and prevent command injection
144 function _path(...)
145         local result = ""
146         
147         -- Not using ipairs because it is not reliable in case of nil arguments
148         arg.n = nil
149         for k,v in pairs(arg) do
150                 if v then
151                         v = tostring(v)
152                         if k == 1 then
153                                 result = "'" .. v:gsub("['.]", "") .. "'"
154                         elseif k < 4 then
155                                 result = result .. ".'" .. v:gsub("['.]", "") .. "'"
156                         elseif k == 4 then
157                                 result = result .. "='" .. v:gsub("'", "") .. "'"
158                         end
159                 end
160         end
161         return result
162 end