2 Copyright 2011 Iordan Iordanov <iiordanov (AT) gmail.com>
4 This file is part of luci-pbx.
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.
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.
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/>.
20 if nixio.fs.access("/etc/init.d/asterisk") then
22 elseif nixio.fs.access("/etc/init.d/freeswitch") then
28 modulename = "pbx-calls"
29 voipmodulename = "pbx-voip"
30 googlemodulename = "pbx-google"
31 usersmodulename = "pbx-users"
44 -- Checks whether the entered extension is valid syntactically.
45 function is_valid_extension(exten)
46 return (exten:match("[#*+0-9NXZ]+$") ~= nil)
50 m = Map (modulename, translate("Call Routing"),
51 translate("This is where you indicate which Google/SIP accounts are used to call what \
52 country/area codes, which users can use what SIP/Google accounts, how incoming \
53 calls are routed, what numbers can get into this PBX with a password, and what \
54 numbers are blacklisted."))
56 -- Recreate the config, and restart services after changes are commited to the configuration.
57 function m.on_after_commit(self)
58 luci.sys.call("/etc/init.d/pbx-" .. server .. " restart 1\>/dev/null 2\>/dev/null")
59 luci.sys.call("/etc/init.d/" .. server .. " restart 1\>/dev/null 2\>/dev/null")
62 -- Add Google accounts to all valid accounts, and accounts valid for incoming and outgoing calls.
63 m.uci:foreach(googlemodulename, "gtalk_jabber",
65 -- Add this provider to list of valid accounts.
66 if s1.username ~= nil and s1.name ~= nil then
67 allvalidaccounts[s1.name] = s1.username
68 nallvalidaccounts = nallvalidaccounts + 1
70 if s1.make_outgoing_calls == "yes" then
71 -- Add provider to the associative array of valid outgoing accounts.
72 validoutaccounts[s1.name] = s1.username
73 nvalidoutaccounts = nvalidoutaccounts + 1
76 if s1.register == "yes" then
77 -- Add provider to the associative array of valid outgoing accounts.
78 validinaccounts[s1.name] = s1.username
79 nvalidinaccounts = nvalidinaccounts + 1
84 -- Add SIP accounts to all valid accounts, and accounts valid for incoming and outgoing calls.
85 m.uci:foreach(voipmodulename, "voip_provider",
87 -- Add this provider to list of valid accounts.
88 if s1.defaultuser ~= nil and s1.host ~= nil and s1.name ~= nil then
89 allvalidaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
90 nallvalidaccounts = nallvalidaccounts + 1
92 if s1.make_outgoing_calls == "yes" then
93 -- Add provider to the associative array of valid outgoing accounts.
94 validoutaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
95 nvalidoutaccounts = nvalidoutaccounts + 1
98 if s1.register == "yes" then
99 -- Add provider to the associative array of valid outgoing accounts.
100 validinaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
101 nvalidinaccounts = nvalidinaccounts + 1
106 -- Add Local User accounts to all valid users, and users allowed to make outgoing calls.
107 m.uci:foreach(usersmodulename, "local_user",
109 -- Add user to list of all valid users.
110 if s1.defaultuser ~= nil then
111 allvalidusers[s1.defaultuser] = true
112 nallvalidusers = nallvalidusers + 1
114 if s1.can_call == "yes" then
115 validoutusers[s1.defaultuser] = true
116 nvalidoutusers = nvalidoutusers + 1
122 ----------------------------------------------------------------------------------------------------
123 -- If there are no accounts configured, or no accounts enabled for outgoing calls, display a warning.
124 -- Otherwise, display the usual help text within the section.
125 if nallvalidaccounts == 0 then
126 text = translate("NOTE: There are no Google or SIP provider accounts configured.")
127 elseif nvalidoutaccounts == 0 then
128 text = translate("NOTE: There are no Google or SIP provider accounts enabled for outgoing calls.")
130 text = translate("If you have more than one account that can make outgoing calls, you \
131 should enter a list of phone numbers and/or prefixes in the following fields for each \
132 provider listed. Invalid prefixes are removed silently, and only 0-9, X, Z, N, #, *, \
133 and + are valid characters. The letter X matches 0-9, Z matches 1-9, and N matches 2-9. \
134 For example to make calls to Germany through a provider, you can enter 49. To make calls \
135 to North America, you can enter 1NXXNXXXXXX. If one of your providers can make \"local\" \
136 calls to an area code like New York's 646, you can enter 646NXXXXXX for that \
137 provider. You should leave one account with an empty list to make calls with \
138 it by default, if no other provider's prefixes match. The system will automatically \
139 replace an empty list with a message that the provider dials all numbers not matched by another \
140 provider's prefixes. Be as specific as possible (i.e. 1NXXNXXXXXX is better than 1). Please note \
141 all international dial codes are discarded (e.g. 00, 011, 010, 0011). Entries can be made in a \
142 space-separated list, and/or one per line by hitting enter after every one.")
146 s = m:section(NamedSection, "outgoing_calls", "call_routing", translate("Outgoing Calls"), text)
149 for k,v in pairs(validoutaccounts) do
150 patterns = s:option(DynamicList, k, v)
152 -- If the saved field is empty, we return a string
153 -- telling the user that this provider would dial any exten.
154 function patterns.cfgvalue(self, section)
155 value = self.map:get(section, self.option)
158 return {translate("Dials numbers unmatched elsewhere")}
164 -- Write only valid extensions into the config file.
165 function patterns.write(self, section, value)
168 for index, field in ipairs(value) do
169 val = luci.util.trim(value[index])
170 if is_valid_extension(val) == true then
171 newvalue[nindex] = val
175 DynamicList.write(self, section, newvalue)
179 ----------------------------------------------------------------------------------------------------
180 -- If there are no accounts configured, or no accounts enabled for incoming calls, display a warning.
181 -- Otherwise, display the usual help text within the section.
182 if nallvalidaccounts == 0 then
183 text = translate("NOTE: There are no Google or SIP provider accounts configured.")
184 elseif nvalidinaccounts == 0 then
185 text = translate("NOTE: There are no Google or SIP provider accounts enabled for incoming calls.")
187 text = translate("For each provider enabled for incoming calls, here you can restrict which users to\
188 ring on incoming calls. If the list is empty, the system will indicate that all users \
189 enabled for incoming calls will ring. Invalid usernames will be rejected \
190 silently. Also, entering a username here overrides the user's setting to not receive \
191 incoming calls. This way, you can make certain users ring only for specific providers. \
192 Entries can be made in a space-separated list, and/or one per line by hitting enter after \
197 s = m:section(NamedSection, "incoming_calls", "call_routing", translate("Incoming Calls"), text)
200 for k,v in pairs(validinaccounts) do
201 users = s:option(DynamicList, k, v)
203 -- If the saved field is empty, we return a string telling the user that
204 -- this provider would ring all users configured for incoming calls.
205 function users.cfgvalue(self, section)
206 value = self.map:get(section, self.option)
209 return {translate("Rings users enabled for incoming calls")}
215 -- Write only valid user names.
216 function users.write(self, section, value)
219 for index, field in ipairs(value) do
220 trimuser = luci.util.trim(value[index])
221 if allvalidusers[trimuser] == true then
222 newvalue[nindex] = trimuser
226 DynamicList.write(self, section, newvalue)
231 ----------------------------------------------------------------------------------------------------
232 -- If there are no user accounts configured, no user accounts enabled for outgoing calls,
233 -- display a warning. Otherwise, display the usual help text within the section.
234 if nallvalidusers == 0 then
235 text = translate("NOTE: There are no local user accounts configured.")
236 elseif nvalidoutusers == 0 then
237 text = translate("NOTE: There are no local user accounts enabled for outgoing calls.")
239 text = translate("For each user enabled for outgoing calls you can restrict what providers the user \
240 can use for outgoing calls. By default all users can use all providers. To show up in the list \
241 below the user should be allowed to make outgoing calls in the \"User Accounts\" page. Enter VoIP \
242 providers in the format username@some.host.name, as listed in \"Outgoing Calls\" above. It's \
243 easiest to copy and paste the providers from above. Invalid entries, including providers not \
244 enabled for outgoing calls, will be rejected silently. Entries can be made in a space-separated \
245 list, and/or one per line by hitting enter after every one.")
249 s = m:section(NamedSection, "providers_user_can_use", "call_routing",
250 translate("Providers Used for Outgoing Calls"), text)
253 for k,v in pairs(validoutusers) do
254 providers = s:option(DynamicList, k, k)
256 -- If the saved field is empty, we return a string telling the user
257 -- that this user uses all providers enavled for outgoing calls.
258 function providers.cfgvalue(self, section)
259 value = self.map:get(section, self.option)
262 return {translate("Uses providers enabled for outgoing calls")}
265 -- Convert internal names to user@host values.
266 for i,v in ipairs(value) do
267 newvalue[i] = validoutaccounts[v]
273 -- Cook the new values prior to entering them into the config file.
274 -- Also, enter them only if they are valid.
275 function providers.write(self, section, value)
278 for index, field in ipairs(value) do
279 cooked = string.gsub(luci.util.trim(value[index]), "%W", "_")
280 if validoutaccounts[cooked] ~= nil then
281 cookedvalue[cindex] = cooked
285 DynamicList.write(self, section, cookedvalue)
289 ----------------------------------------------------------------------------------------------------
290 s = m:section(TypedSection, "callthrough_numbers", translate("Call-through Numbers"),
291 translate("Designate numbers that are allowed to call through this system and which user's \
292 privileges they will have."))
296 num = s:option(DynamicList, "callthrough_number_list", translate("Call-through Numbers"),
297 translate("Specify numbers individually here. Press enter to add more numbers. \
298 You will have to experiment with what country and area codes you need to add \
300 num.datatype = "uinteger"
302 p = s:option(ListValue, "enabled", translate("Enabled"))
303 p:value("yes", translate("Yes"))
304 p:value("no", translate("No"))
307 user = s:option(Value, "defaultuser", translate("User Name"),
308 translate("The number(s) specified above will be able to dial out with this user's providers. \
309 Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
310 Please verify that the entry was accepted."))
311 function user.write(self, section, value)
312 trimuser = luci.util.trim(value)
313 if allvalidusers[trimuser] == true then
314 Value.write(self, section, trimuser)
318 pwd = s:option(Value, "pin", translate("PIN"),
319 translate("Your PIN disappears when saved for your protection. It will be changed \
320 only when you enter a value different from the saved one. Leaving the PIN \
321 empty is possible, but please beware of the security implications."))
325 -- We skip reading off the saved value and return nothing.
326 function pwd.cfgvalue(self, section)
330 -- We check the entered value against the saved one, and only write if the entered value is
331 -- something other than the empty string, and it differes from the saved value.
332 function pwd.write(self, section, value)
333 local orig_pwd = m:get(section, self.option)
334 if value and #value > 0 and orig_pwd ~= value then
335 Value.write(self, section, value)
339 ----------------------------------------------------------------------------------------------------
340 s = m:section(TypedSection, "callback_numbers", translate("Call-back Numbers"),
341 translate("Designate numbers to whom the system will hang up and call back, which provider will \
342 be used to call them, and which user's privileges will be granted to them."))
346 num = s:option(DynamicList, "callback_number_list", translate("Call-back Numbers"),
347 translate("Specify numbers individually here. Press enter to add more numbers. \
348 You will have to experiment with what country and area codes you need to add \
350 num.datatype = "uinteger"
352 p = s:option(ListValue, "enabled", translate("Enabled"))
353 p:value("yes", translate("Yes"))
354 p:value("no", translate("No"))
357 delay = s:option(Value, "callback_hangup_delay", translate("Hang-up Delay"),
358 translate("How long to wait before hanging up. If the provider you use to dial automatically forwards \
359 to voicemail, you can set this value to a delay that will allow you to hang up before your call gets \
360 forwarded and you get billed for it."))
361 delay.datatype = "uinteger"
364 user = s:option(Value, "defaultuser", translate("User Name"),
365 translate("The number(s) specified above will be able to dial out with this user's providers. \
366 Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
367 Please verify that the entry was accepted."))
368 function user.write(self, section, value)
369 trimuser = luci.util.trim(value)
370 if allvalidusers[trimuser] == true then
371 Value.write(self, section, trimuser)
375 pwd = s:option(Value, "pin", translate("PIN"),
376 translate("Your PIN disappears when saved for your protection. It will be changed \
377 only when you enter a value different from the saved one. Leaving the PIN \
378 empty is possible, but please beware of the security implications."))
382 -- We skip reading off the saved value and return nothing.
383 function pwd.cfgvalue(self, section)
387 -- We check the entered value against the saved one, and only write if the entered value is
388 -- something other than the empty string, and it differes from the saved value.
389 function pwd.write(self, section, value)
390 local orig_pwd = m:get(section, self.option)
391 if value and #value > 0 and orig_pwd ~= value then
392 Value.write(self, section, value)
396 provider = s:option(Value, "callback_provider", translate("Call-back Provider"),
397 translate("Enter a VoIP provider to use for call-back in the format username@some.host.name, as listed in \
398 \"Outgoing Calls\" above. It's easiest to copy and paste the providers from above. Invalid entries, including \
399 providers not enabled for outgoing calls, will be rejected silently."))
400 function provider.write(self, section, value)
401 cooked = string.gsub(luci.util.trim(value), "%W", "_")
402 if validoutaccounts[cooked] ~= nil then
403 Value.write(self, section, value)
407 ----------------------------------------------------------------------------------------------------
408 s = m:section(NamedSection, "blacklisting", "call_routing", translate("Blacklisted Numbers"),
409 translate("Enter phone numbers that you want to decline calls from automatically. \
410 You should probably omit the country code and any leading zeroes, but please \
411 experiment to make sure you are blocking numbers from your desired area successfully."))
414 b = s:option(DynamicList, "blacklist1", translate("Dynamic List of Blacklisted Numbers"),
415 translate("Specify numbers individually here. Press enter to add more numbers."))
417 b.datatype = "uinteger"
419 b = s:option(Value, "blacklist2", translate("Space-Separated List of Blacklisted Numbers"),
420 translate("Copy-paste large lists of numbers here."))
421 b.template = "cbi/tvalue"