13e2a911817537ceb2868f575f0d42a380b3e9d9
[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 space-separated \
67 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