1) Made spacing with \ syntax consistent across the board.
[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