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