123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- --[[
- Copyright 2011 Iordan Iordanov <iiordanov (AT) gmail.com>
- This file is part of luci-pbx.
- luci-pbx is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- luci-pbx is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with luci-pbx. If not, see <http://www.gnu.org/licenses/>.
- ]]--
- if nixio.fs.access("/etc/init.d/asterisk") then
- server = "asterisk"
- elseif nixio.fs.access("/etc/init.d/freeswitch") then
- server = "freeswitch"
- else
- server = ""
- end
- modulename = "pbx-calls"
- voipmodulename = "pbx-voip"
- googlemodulename = "pbx-google"
- usersmodulename = "pbx-users"
- allvalidaccounts = {}
- nallvalidaccounts = 0
- validoutaccounts = {}
- nvalidoutaccounts = 0
- validinaccounts = {}
- nvalidinaccounts = 0
- allvalidusers = {}
- nallvalidusers = 0
- validoutusers = {}
- nvalidoutusers = 0
- -- Checks whether the entered extension is valid syntactically.
- function is_valid_extension(exten)
- return (exten:match("[#*+0-9NXZ]+$") ~= nil)
- end
- m = Map (modulename, translate("Call Routing"),
- translate("This is where you indicate which Google/SIP accounts are used to call what \
- country/area codes, which users can use what SIP/Google accounts, how incoming \
- calls are routed, what numbers can get into this PBX with a password, and what \
- numbers are blacklisted."))
- -- Recreate the config, and restart services after changes are commited to the configuration.
- function m.on_after_commit(self)
- luci.sys.call("/etc/init.d/pbx-" .. server .. " restart 1\>/dev/null 2\>/dev/null")
- luci.sys.call("/etc/init.d/" .. server .. " restart 1\>/dev/null 2\>/dev/null")
- end
- -- Add Google accounts to all valid accounts, and accounts valid for incoming and outgoing calls.
- m.uci:foreach(googlemodulename, "gtalk_jabber",
- function(s1)
- -- Add this provider to list of valid accounts.
- if s1.username ~= nil and s1.name ~= nil then
- allvalidaccounts[s1.name] = s1.username
- nallvalidaccounts = nallvalidaccounts + 1
- if s1.make_outgoing_calls == "yes" then
- -- Add provider to the associative array of valid outgoing accounts.
- validoutaccounts[s1.name] = s1.username
- nvalidoutaccounts = nvalidoutaccounts + 1
- end
- if s1.register == "yes" then
- -- Add provider to the associative array of valid outgoing accounts.
- validinaccounts[s1.name] = s1.username
- nvalidinaccounts = nvalidinaccounts + 1
- end
- end
- end)
- -- Add SIP accounts to all valid accounts, and accounts valid for incoming and outgoing calls.
- m.uci:foreach(voipmodulename, "voip_provider",
- function(s1)
- -- Add this provider to list of valid accounts.
- if s1.defaultuser ~= nil and s1.host ~= nil and s1.name ~= nil then
- allvalidaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
- nallvalidaccounts = nallvalidaccounts + 1
- if s1.make_outgoing_calls == "yes" then
- -- Add provider to the associative array of valid outgoing accounts.
- validoutaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
- nvalidoutaccounts = nvalidoutaccounts + 1
- end
- if s1.register == "yes" then
- -- Add provider to the associative array of valid outgoing accounts.
- validinaccounts[s1.name] = s1.defaultuser .. "@" .. s1.host
- nvalidinaccounts = nvalidinaccounts + 1
- end
- end
- end)
- -- Add Local User accounts to all valid users, and users allowed to make outgoing calls.
- m.uci:foreach(usersmodulename, "local_user",
- function(s1)
- -- Add user to list of all valid users.
- if s1.defaultuser ~= nil then
- allvalidusers[s1.defaultuser] = true
- nallvalidusers = nallvalidusers + 1
-
- if s1.can_call == "yes" then
- validoutusers[s1.defaultuser] = true
- nvalidoutusers = nvalidoutusers + 1
- end
- end
- end)
- ----------------------------------------------------------------------------------------------------
- -- If there are no accounts configured, or no accounts enabled for outgoing calls, display a warning.
- -- Otherwise, display the usual help text within the section.
- if nallvalidaccounts == 0 then
- text = translate("NOTE: There are no Google or SIP provider accounts configured.")
- elseif nvalidoutaccounts == 0 then
- text = translate("NOTE: There are no Google or SIP provider accounts enabled for outgoing calls.")
- else
- text = translate("If you have more than one account that can make outgoing calls, you \
- should enter a list of phone numbers and/or prefixes in the following fields for each \
- provider listed. Invalid prefixes are removed silently, and only 0-9, X, Z, N, #, *, \
- and + are valid characters. The letter X matches 0-9, Z matches 1-9, and N matches 2-9. \
- For example to make calls to Germany through a provider, you can enter 49. To make calls \
- to North America, you can enter 1NXXNXXXXXX. If one of your providers can make \"local\" \
- calls to an area code like New York's 646, you can enter 646NXXXXXX for that \
- provider. You should leave one account with an empty list to make calls with \
- it by default, if no other provider's prefixes match. The system will automatically \
- replace an empty list with a message that the provider dials all numbers not matched by another \
- provider's prefixes. Be as specific as possible (i.e. 1NXXNXXXXXX is better than 1). Please note \
- all international dial codes are discarded (e.g. 00, 011, 010, 0011). Entries can be made in a \
- space-separated list, and/or one per line by hitting enter after every one.")
- end
- s = m:section(NamedSection, "outgoing_calls", "call_routing", translate("Outgoing Calls"), text)
- s.anonymous = true
- for k,v in pairs(validoutaccounts) do
- patterns = s:option(DynamicList, k, v)
-
- -- If the saved field is empty, we return a string
- -- telling the user that this provider would dial any exten.
- function patterns.cfgvalue(self, section)
- value = self.map:get(section, self.option)
-
- if value == nil then
- return {translate("Dials numbers unmatched elsewhere")}
- else
- return value
- end
- end
-
- -- Write only valid extensions into the config file.
- function patterns.write(self, section, value)
- newvalue = {}
- nindex = 1
- for index, field in ipairs(value) do
- val = luci.util.trim(value[index])
- if is_valid_extension(val) == true then
- newvalue[nindex] = val
- nindex = nindex + 1
- end
- end
- DynamicList.write(self, section, newvalue)
- end
- end
- ----------------------------------------------------------------------------------------------------
- -- If there are no accounts configured, or no accounts enabled for incoming calls, display a warning.
- -- Otherwise, display the usual help text within the section.
- if nallvalidaccounts == 0 then
- text = translate("NOTE: There are no Google or SIP provider accounts configured.")
- elseif nvalidinaccounts == 0 then
- text = translate("NOTE: There are no Google or SIP provider accounts enabled for incoming calls.")
- else
- text = translate("For each provider enabled for incoming calls, here you can restrict which users to\
- ring on incoming calls. If the list is empty, the system will indicate that all users \
- enabled for incoming calls will ring. Invalid usernames will be rejected \
- silently. Also, entering a username here overrides the user's setting to not receive \
- incoming calls. This way, you can make certain users ring only for specific providers. \
- Entries can be made in a space-separated list, and/or one per line by hitting enter after \
- every one.")
- end
- s = m:section(NamedSection, "incoming_calls", "call_routing", translate("Incoming Calls"), text)
- s.anonymous = true
- for k,v in pairs(validinaccounts) do
- users = s:option(DynamicList, k, v)
-
- -- If the saved field is empty, we return a string telling the user that
- -- this provider would ring all users configured for incoming calls.
- function users.cfgvalue(self, section)
- value = self.map:get(section, self.option)
-
- if value == nil then
- return {translate("Rings users enabled for incoming calls")}
- else
- return value
- end
- end
-
- -- Write only valid user names.
- function users.write(self, section, value)
- newvalue = {}
- nindex = 1
- for index, field in ipairs(value) do
- trimuser = luci.util.trim(value[index])
- if allvalidusers[trimuser] == true then
- newvalue[nindex] = trimuser
- nindex = nindex + 1
- end
- end
- DynamicList.write(self, section, newvalue)
- end
- end
- ----------------------------------------------------------------------------------------------------
- -- If there are no user accounts configured, no user accounts enabled for outgoing calls,
- -- display a warning. Otherwise, display the usual help text within the section.
- if nallvalidusers == 0 then
- text = translate("NOTE: There are no local user accounts configured.")
- elseif nvalidoutusers == 0 then
- text = translate("NOTE: There are no local user accounts enabled for outgoing calls.")
- else
- text = translate("For each user enabled for outgoing calls you can restrict what providers the user \
- can use for outgoing calls. By default all users can use all providers. To show up in the list \
- below the user should be allowed to make outgoing calls in the \"User Accounts\" page. Enter VoIP \
- providers in the format username@some.host.name, as listed in \"Outgoing Calls\" above. It's \
- easiest to copy and paste the providers from above. Invalid entries, including providers not \
- enabled for outgoing calls, will be rejected silently. Entries can be made in a space-separated \
- list, and/or one per line by hitting enter after every one.")
- end
- s = m:section(NamedSection, "providers_user_can_use", "call_routing",
- translate("Providers Used for Outgoing Calls"), text)
- s.anonymous = true
- for k,v in pairs(validoutusers) do
- providers = s:option(DynamicList, k, k)
- -- If the saved field is empty, we return a string telling the user
- -- that this user uses all providers enavled for outgoing calls.
- function providers.cfgvalue(self, section)
- value = self.map:get(section, self.option)
-
- if value == nil then
- return {translate("Uses providers enabled for outgoing calls")}
- else
- newvalue = {}
- -- Convert internal names to user@host values.
- for i,v in ipairs(value) do
- newvalue[i] = validoutaccounts[v]
- end
- return newvalue
- end
- end
-
- -- Cook the new values prior to entering them into the config file.
- -- Also, enter them only if they are valid.
- function providers.write(self, section, value)
- cookedvalue = {}
- cindex = 1
- for index, field in ipairs(value) do
- cooked = string.gsub(luci.util.trim(value[index]), "%W", "_")
- if validoutaccounts[cooked] ~= nil then
- cookedvalue[cindex] = cooked
- cindex = cindex + 1
- end
- end
- DynamicList.write(self, section, cookedvalue)
- end
- end
- ----------------------------------------------------------------------------------------------------
- s = m:section(TypedSection, "callthrough_numbers", translate("Call-through Numbers"),
- translate("Designate numbers that are allowed to call through this system and which user's \
- privileges they will have."))
- s.anonymous = true
- s.addremove = true
- num = s:option(DynamicList, "callthrough_number_list", translate("Call-through Numbers"),
- translate("Specify numbers individually here. Press enter to add more numbers. \
- You will have to experiment with what country and area codes you need to add \
- to the number."))
- num.datatype = "uinteger"
- p = s:option(ListValue, "enabled", translate("Enabled"))
- p:value("yes", translate("Yes"))
- p:value("no", translate("No"))
- p.default = "yes"
- user = s:option(Value, "defaultuser", translate("User Name"),
- translate("The number(s) specified above will be able to dial out with this user's providers. \
- Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
- Please verify that the entry was accepted."))
- function user.write(self, section, value)
- trimuser = luci.util.trim(value)
- if allvalidusers[trimuser] == true then
- Value.write(self, section, trimuser)
- end
- end
- pwd = s:option(Value, "pin", translate("PIN"),
- translate("Your PIN disappears when saved for your protection. It will be changed \
- only when you enter a value different from the saved one. Leaving the PIN \
- empty is possible, but please beware of the security implications."))
- pwd.password = true
- pwd.rmempty = false
- -- We skip reading off the saved value and return nothing.
- function pwd.cfgvalue(self, section)
- return ""
- end
- -- We check the entered value against the saved one, and only write if the entered value is
- -- something other than the empty string, and it differes from the saved value.
- function pwd.write(self, section, value)
- local orig_pwd = m:get(section, self.option)
- if value and #value > 0 and orig_pwd ~= value then
- Value.write(self, section, value)
- end
- end
- ----------------------------------------------------------------------------------------------------
- s = m:section(TypedSection, "callback_numbers", translate("Call-back Numbers"),
- translate("Designate numbers to whom the system will hang up and call back, which provider will \
- be used to call them, and which user's privileges will be granted to them."))
- s.anonymous = true
- s.addremove = true
- num = s:option(DynamicList, "callback_number_list", translate("Call-back Numbers"),
- translate("Specify numbers individually here. Press enter to add more numbers. \
- You will have to experiment with what country and area codes you need to add \
- to the number."))
- num.datatype = "uinteger"
- p = s:option(ListValue, "enabled", translate("Enabled"))
- p:value("yes", translate("Yes"))
- p:value("no", translate("No"))
- p.default = "yes"
- delay = s:option(Value, "callback_hangup_delay", translate("Hang-up Delay"),
- translate("How long to wait before hanging up. If the provider you use to dial automatically forwards \
- to voicemail, you can set this value to a delay that will allow you to hang up before your call gets \
- forwarded and you get billed for it."))
- delay.datatype = "uinteger"
- delay.default = 0
- user = s:option(Value, "defaultuser", translate("User Name"),
- translate("The number(s) specified above will be able to dial out with this user's providers. \
- Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
- Please verify that the entry was accepted."))
- function user.write(self, section, value)
- trimuser = luci.util.trim(value)
- if allvalidusers[trimuser] == true then
- Value.write(self, section, trimuser)
- end
- end
- pwd = s:option(Value, "pin", translate("PIN"),
- translate("Your PIN disappears when saved for your protection. It will be changed \
- only when you enter a value different from the saved one. Leaving the PIN \
- empty is possible, but please beware of the security implications."))
- pwd.password = true
- pwd.rmempty = false
- -- We skip reading off the saved value and return nothing.
- function pwd.cfgvalue(self, section)
- return ""
- end
- -- We check the entered value against the saved one, and only write if the entered value is
- -- something other than the empty string, and it differes from the saved value.
- function pwd.write(self, section, value)
- local orig_pwd = m:get(section, self.option)
- if value and #value > 0 and orig_pwd ~= value then
- Value.write(self, section, value)
- end
- end
- provider = s:option(Value, "callback_provider", translate("Call-back Provider"),
- translate("Enter a VoIP provider to use for call-back in the format username@some.host.name, as listed in \
- \"Outgoing Calls\" above. It's easiest to copy and paste the providers from above. Invalid entries, including \
- providers not enabled for outgoing calls, will be rejected silently."))
- function provider.write(self, section, value)
- cooked = string.gsub(luci.util.trim(value), "%W", "_")
- if validoutaccounts[cooked] ~= nil then
- Value.write(self, section, value)
- end
- end
- ----------------------------------------------------------------------------------------------------
- s = m:section(NamedSection, "blacklisting", "call_routing", translate("Blacklisted Numbers"),
- translate("Enter phone numbers that you want to decline calls from automatically. \
- You should probably omit the country code and any leading zeroes, but please \
- experiment to make sure you are blocking numbers from your desired area successfully."))
- s.anonymous = true
- b = s:option(DynamicList, "blacklist1", translate("Dynamic List of Blacklisted Numbers"),
- translate("Specify numbers individually here. Press enter to add more numbers."))
- b.cast = "string"
- b.datatype = "uinteger"
- b = s:option(Value, "blacklist2", translate("Space-Separated List of Blacklisted Numbers"),
- translate("Copy-paste large lists of numbers here."))
- b.template = "cbi/tvalue"
- b.rows = 3
- return m
|