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