1) Replaced trim with luci.util.trim in pbx-calls.lua
[project/luci.git] / applications / luci-pbx / luasrc / model / cbi / pbx-calls.lua
1 --[[
2 Copyright 2011 Iordan Iordanov <iiordanov (AT) gmail.com>
3
4 This file is part of luci-pbx.
5
6 luci-pbx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 luci-pbx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with luci-pbx. If not, see <http://www.gnu.org/licenses/>.
18 ]]--
19
20 if nixio.fs.access("/etc/init.d/asterisk") then
21 server = "asterisk"
22 elseif nixio.fs.access("/etc/init.d/freeswitch") then
23 server = "freeswitch"
24 else
25 server = ""
26 end
27
28 modulename = "pbx-calls"
29 voipmodulename = "pbx-voip"
30 googlemodulename = "pbx-google"
31 usersmodulename = "pbx-users"
32 validoutaccounts = {}
33 allvalidusers = {}
34
35 -- Checks whether the entered extension is valid syntactically.
36 function is_valid_extension(exten)
37 return (exten:match("[#*+0-9NXZ]+$") ~= nil)
38 end
39
40
41 m = Map (modulename, translate("Call Routing"),
42 translate("This is where you indicate which Google/SIP accounts are used to call what \
43 country/area codes, which users can use which SIP/Google accounts, how incoming\
44 calls are routed, what numbers can get into this PBX with a password, and what\
45 numbers are blacklisted."))
46
47 -- Recreate the config, and restart services after changes are commited to the configuration.
48 function m.on_after_commit(self)
49 luci.sys.call("/etc/init.d/pbx-" .. server .. " restart 1\>/dev/null 2\>/dev/null")
50 luci.sys.call("/etc/init.d/" .. server .. " restart 1\>/dev/null 2\>/dev/null")
51 end
52
53 ----------------------------------------------------------------------------------------------------
54 s = m:section(NamedSection, "outgoing_calls", "call_routing", translate("Outgoing Calls"),
55 translate("If you have more than one account which can make outgoing calls, you\
56 should enter a list of phone numbers and prefixes in the following fields for each\
57 provider listed. Invalid prefixes are removed silently, and only 0-9, X, Z, N, #, *,\
58 and + are valid characters. The letter X matches 0-9, Z matches 1-9, and N matches 2-9.\
59 For example to make calls to Germany through a provider, you can enter 49. To make calls\
60 to North America, you can enter 1NXXNXXXXXX. If one of your providers can make \"local\"\
61 calls to an area code like New York's 646, you can enter 646NXXXXXX for that\
62 provider. You should leave one account with an empty list to make calls with\
63 it by default, if no other provider's prefixes match. The system will automatically\
64 replace an empty list with a message that the provider dials all numbers. Be as specific as\
65 possible (i.e. 1NXXNXXXXXX is better than 1). Please note all international dial codes\
66 are discarded (e.g. 00, 011, 010, 0011). Entries can be made in a\
67 space-separated list, and/or one per line by hitting enter after every one."))
68 s.anonymous = true
69
70 m.uci:foreach(googlemodulename, "gtalk_jabber",
71 function(s1)
72 if s1.username ~= nil and s1.name ~= nil and
73 s1.make_outgoing_calls == "yes" then
74 patt = s:option(DynamicList, s1.name, s1.username)
75
76 -- Add provider to the associative array of valid accounts.
77 validoutaccounts[s1.name] = s1.username
78
79 -- If the saved field is empty, we return a string
80 -- telling the user that this account would dial any exten.
81 function patt.cfgvalue(self, section)
82 value = self.map:get(section, self.option)
83
84 if value == nil then
85 return {"Dials any number"}
86 else
87 return value
88 end
89 end
90
91 -- Write only valid extensions into the config file.
92 function patt.write(self, section, value)
93 newvalue = {}
94 nindex = 1
95 for index, field in ipairs(value) do
96 val = luci.util.trim(value[index])
97 if is_valid_extension(val) == true then
98 newvalue[nindex] = val
99 nindex = nindex + 1
100 end
101 end
102 DynamicList.write(self, section, newvalue)
103 end
104 end
105 end)
106
107 m.uci:foreach(voipmodulename, "voip_provider",
108 function(s1)
109 if s1.defaultuser ~= nil and s1.host ~= nil and
110 s1.name ~= nil and s1.make_outgoing_calls == "yes" then
111 patt = s:option(DynamicList, s1.name, s1.defaultuser .. "@" .. s1.host)
112
113 -- Add provider to the associative array of valid accounts.
114 validoutaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
115
116 -- If the saved field is empty, we return a string
117 -- telling the user that this account would dial any exten.
118 function patt.cfgvalue(self, section)
119 value = self.map:get(section, self.option)
120
121 if value == nil then
122 return {"Dials any number"}
123 else
124 return value
125 end
126 end
127
128 -- Write only valid extensions into the config file.
129 function patt.write(self, section, value)
130 newvalue = {}
131 nindex = 1
132 for index, field in ipairs(value) do
133 val = luci.util.trim(value[index])
134 if is_valid_extension(val) == true then
135 newvalue[nindex] = val
136 nindex = nindex + 1
137 end
138 end
139 DynamicList.write(self, section, newvalue)
140 end
141 end
142 end)
143
144 ----------------------------------------------------------------------------------------------------
145 s = m:section(NamedSection, "incoming_calls", "call_routing", translate("Incoming Calls"),
146 translate("For each provider that receives calls, here you can restrict which users to ring\
147 on incoming calls. If the list is empty, the system will indicate that all users\
148 which are enabled for incoming calls will ring. Invalid usernames will be rejected\
149 silently. Also, entering a username here overrides the user's setting to not receive\
150 incoming calls, so this way, you can make users ring only for select providers.\
151 Entries can be made in a space-separated list, and/or one per\
152 line by hitting enter after every one."))
153 s.anonymous = true
154
155 m.uci:foreach(googlemodulename, "gtalk_jabber",
156 function(s1)
157 if s1.username ~= nil and s1.register == "yes" then
158 field_name=string.gsub(s1.username, "%W", "_")
159 gtalkaccts = s:option(DynamicList, field_name, s1.username)
160
161 -- If the saved field is empty, we return a string
162 -- telling the user that this account would dial any exten.
163 function gtalkaccts.cfgvalue(self, section)
164 value = self.map:get(section, self.option)
165
166 if value == nil then
167 return {"Rings all users"}
168 else
169 return value
170 end
171 end
172
173 -- Write only valid user names.
174 function gtalkaccts.write(self, section, value)
175 newvalue = {}
176 nindex = 1
177 for index, field in ipairs(value) do
178 trimuser = luci.util.trim(value[index])
179 if allvalidusers[trimuser] == true then
180 newvalue[nindex] = trimuser
181 nindex = nindex + 1
182 end
183 end
184 DynamicList.write(self, section, newvalue)
185 end
186 end
187 end)
188
189
190 m.uci:foreach(voipmodulename, "voip_provider",
191 function(s1)
192 if s1.defaultuser ~= nil and s1.host ~= nil and s1.register == "yes" then
193 field_name=string.gsub(s1.defaultuser .. "_" .. s1.host, "%W", "_")
194 voipaccts = s:option(DynamicList, field_name, s1.defaultuser .. "@" .. s1.host)
195
196 -- If the saved field is empty, we return a string
197 -- telling the user that this account would dial any exten.
198 function voipaccts.cfgvalue(self, section)
199 value = self.map:get(section, self.option)
200
201 if value == nil then
202 return {"Rings all users"}
203 else
204 return value
205 end
206 end
207
208 -- Write only valid user names.
209 function voipaccts.write(self, section, value)
210 newvalue = {}
211 nindex = 1
212 for index, field in ipairs(value) do
213 trimuser = luci.util.trim(value[index])
214 if allvalidusers[trimuser] == true then
215 newvalue[nindex] = trimuser
216 nindex = nindex + 1
217 end
218 end
219 DynamicList.write(self, section, newvalue)
220 end
221 end
222 end)
223
224 ----------------------------------------------------------------------------------------------------
225 s = m:section(NamedSection, "providers_user_can_use", "call_routing",
226 translate("Providers Used for Outgoing Calls"),
227 translate("If you would like, you could restrict which providers users are allowed to use for outgoing\
228 calls. By default all users can use all providers. To show up in the list below the user should\
229 be allowed to make outgoing calls in the \"User Accounts\" page. Enter VoIP providers in the format\
230 username@some.host.name, as listed in \"Outgoing Calls\" above. It's easiest to copy and paste\
231 the providers from above. Invalid entries will be rejected silently. Entries can be made in a \
232 space-separated list, and/or one per line by hitting enter after every one."))
233 s.anonymous = true
234
235 m.uci:foreach(usersmodulename, "local_user",
236 function(s1)
237 -- Add user to list of all valid users.
238 if s1.defaultuser ~= nil then allvalidusers[s1.defaultuser] = true end
239
240 if s1.defaultuser ~= nil and s1.can_call == "yes" then
241 providers = s:option(DynamicList, s1.defaultuser, s1.defaultuser)
242
243 -- If the saved field is empty, we return a string
244 -- telling the user that this account would dial any exten.
245 function providers.cfgvalue(self, section)
246 value = self.map:get(section, self.option)
247
248 if value == nil then
249 return {"Uses all provider accounts"}
250 else
251 newvalue = {}
252 -- Convert internal names to user@host values.
253 for i,v in ipairs(value) do
254 newvalue[i] = validoutaccounts[v]
255 end
256 return newvalue
257 end
258 end
259
260 -- Cook the new values prior to entering them into the config file.
261 -- Also, enter them only if they are valid.
262 function providers.write(self, section, value)
263 cookedvalue = {}
264 cindex = 1
265 for index, field in ipairs(value) do
266 cooked = string.gsub(luci.util.trim(value[index]), "%W", "_")
267 if validoutaccounts[cooked] ~= nil then
268 cookedvalue[cindex] = cooked
269 cindex = cindex + 1
270 end
271 end
272 DynamicList.write(self, section, cookedvalue)
273 end
274 end
275 end)
276
277 ----------------------------------------------------------------------------------------------------
278 s = m:section(TypedSection, "callthrough_numbers", translate("Call-through Numbers"),
279 translate("Designate numbers which will be allowed to call through this system and which user's\
280 privileges it will have."))
281 s.anonymous = true
282 s.addremove = true
283
284 num = s:option(DynamicList, "callthrough_number_list", translate("Call-through Numbers"))
285 num.datatype = "uinteger"
286
287 p = s:option(ListValue, "enabled", translate("Enabled"))
288 p:value("yes", translate("Yes"))
289 p:value("no", translate("No"))
290 p.default = "yes"
291
292 user = s:option(Value, "defaultuser", translate("User Name"),
293 translate("The number(s) specified above will be able to dial out with this user's providers.\
294 Invalid usernames are dropped silently, please verify that the entry was accepted."))
295 function user.write(self, section, value)
296 trimuser = luci.util.trim(value)
297 if allvalidusers[trimuser] == true then
298 Value.write(self, section, trimuser)
299 end
300 end
301
302 pwd = s:option(Value, "pin", translate("PIN"),
303 translate("Your PIN disappears when saved for your protection. It will be changed\
304 only when you enter a value different from the saved one. Leaving the PIN\
305 empty is possible, but please beware of the security implications."))
306 pwd.password = true
307 pwd.rmempty = false
308
309 -- We skip reading off the saved value and return nothing.
310 function pwd.cfgvalue(self, section)
311 return ""
312 end
313
314 -- We check the entered value against the saved one, and only write if the entered value is
315 -- something other than the empty string, and it differes from the saved value.
316 function pwd.write(self, section, value)
317 local orig_pwd = m:get(section, self.option)
318 if value and #value > 0 and orig_pwd ~= value then
319 Value.write(self, section, value)
320 end
321 end
322
323 ----------------------------------------------------------------------------------------------------
324 s = m:section(NamedSection, "blacklisting", "call_routing", translate("Blacklisted Numbers"),
325 translate("Enter phone numbers that you want to decline calls from automatically.\
326 You should probably omit the country code and any leading\
327 zeroes, but please experiment to make sure you are blocking numbers from your\
328 desired area successfully."))
329 s.anonymous = true
330
331 b = s:option(DynamicList, "blacklist1", translate("Dynamic List of Blacklisted Numbers"),
332 translate("Specify numbers individually here. Press enter to add more numbers."))
333 b.cast = "string"
334 b.datatype = "uinteger"
335
336 b = s:option(Value, "blacklist2", translate("Space-Separated List of Blacklisted Numbers"),
337 translate("Copy-paste large lists of numbers here."))
338 b.template = "cbi/tvalue"
339 b.rows = 3
340
341 return m