root/modules/branches/2.3/core/functions.inc.php

Revision 7882, 137.6 kB (checked in by p_lindheimer, 5 days ago)

Merged revisions 7881 via svnmerge from
http://svn.freepbx.org/modules/branches/2.4

........

r7878 | p_lindheimer | 2009-06-29 19:36:32 -0700 (Mon, 29 Jun 2009) | 1 line


fixes #3741 added new function core_routing_trunk_del(trunknum) which deletes the specified trunk from all routes

........

  • Property svn:mime-type set to text/plain
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2
3 // The destinations this module provides
4 // returns a associative arrays with keys 'destination' and 'description'
5 function core_destinations() {
6         //static destinations
7         $extens = array();
8         $category = 'Terminate Call';
9         $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category);
10         $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category);
11         $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category);
12         $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category);
13         $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category);
14        
15         //get the list of meetmes
16         $results = core_users_list();
17        
18         if (isset($results) && function_exists('voicemail_getVoicemail')) {
19                 //get voicemail
20                 $uservm = voicemail_getVoicemail();
21                 $vmcontexts = array_keys($uservm);
22                 foreach ($results as $thisext) {
23                         $extnum = $thisext[0];
24                         // search vm contexts for this extensions mailbox
25                         foreach ($vmcontexts as $vmcontext) {
26                                 if(isset($uservm[$vmcontext][$extnum])){
27                                         //$vmname = $uservm[$vmcontext][$extnum]['name'];
28                                         //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>');
29                                         $vmboxes[$extnum] = true;
30                                 }
31                         }
32                 }
33         }
34        
35         // return an associative array with destination and description
36         // core provides both users and voicemail boxes as destinations
37         if (isset($results)) {
38                 foreach($results as $result) {
39                         $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions');
40                         if(isset($vmboxes[$result['0']])) {
41                                 $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail');
42                                 $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail');
43                                 $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail');
44                         }
45                 }
46         }
47        
48         if (isset($extens))
49                 return $extens;
50         else
51                 return null;
52
53 }
54
55 /*      Generates dialplan for "core" components (extensions & inbound routing)
56         We call this with retrieve_conf
57 */
58 function core_get_config($engine) {
59         global $ext;  // is this the best way to pass this?
60         global $version;  // this is not the best way to pass this, this should be passetd together with $engine
61         global $amp_conf;
62
63         $modulename = "core";
64        
65         switch($engine) {
66                 case "asterisk":
67                         // FeatureCodes
68                         $fcc = new featurecode($modulename, 'userlogon');
69                         $fc_userlogon = $fcc->getCodeActive();
70                         unset($fcc);
71
72                         $fcc = new featurecode($modulename, 'userlogoff');
73                         $fc_userlogoff = $fcc->getCodeActive();
74                         unset($fcc);
75
76                         $fcc = new featurecode($modulename, 'zapbarge');
77                         $fc_zapbarge = $fcc->getCodeActive();
78                         unset($fcc);
79
80                         $fcc = new featurecode($modulename, 'chanspy');
81                         $fc_chanspy = $fcc->getCodeActive();
82                         unset($fcc);
83
84                         $fcc = new featurecode($modulename, 'simu_pstn');
85                         $fc_simu_pstn = $fcc->getCodeActive();
86                         unset($fcc);
87
88                         $fcc = new featurecode($modulename, 'simu_fax');
89                         $fc_simu_fax = $fcc->getCodeActive();
90                         unset($fcc);
91
92                         $fcc = new featurecode($modulename, 'pickup');
93                         $fc_pickup = $fcc->getCodeActive();
94                         unset($fcc);
95
96                         // Log on / off -- all in one context
97                         if ($fc_userlogoff != '' || $fc_userlogon != '') {
98                                 $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal
99                                
100                                 if ($fc_userlogoff != '') {
101                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
102                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup(''));
103                                 }
104        
105                                 if ($fc_userlogon != '') {
106                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
107                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
108                                        
109                                         $clen = strlen($fc_userlogon);
110                                         $fc_userlogon = "_$fc_userlogon.";
111                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}'));
112                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
113                                 }
114                         }
115
116                         // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
117                         // when a user pushes a flashing BLF.
118                         if ($fc_pickup != '') {
119                                 $ext->addInclude('from-internal-additional', 'app-pickup');
120                                 $fclen = strlen($fc_pickup);
121                                 $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}'));
122                                 if (strstr($version, 'BRI'))
123                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_dpickup('${EXTEN:'.$fclen.'}'));
124                                 else
125                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_pickup('${EXTEN:'.$fclen.'}'));
126                         }
127                        
128                        
129                         // zap barge
130                         if ($fc_zapbarge != '') {
131                                 $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal
132                                
133                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
134                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}'));
135                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
136                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
137                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
138                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
139                         }
140
141                         // chan spy
142                         if ($fc_chanspy != '') {
143                                 $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal
144                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
145                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
146                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
147                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
148                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
149                         }
150                        
151                         // Simulate options (ext-test)
152                         if ($fc_simu_pstn != '' || $fc_simu_fax != '') {
153                                 $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal
154                                
155                                 if ($fc_simu_pstn != '') {
156                                         $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
157                                 }
158
159                                 if ($fc_simu_fax != '') {
160                                         $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax'));
161                                 }
162
163                                 $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
164                         }
165                        
166                         /* Always have Fax detection in ext-did, no matter what */
167                         $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax'));
168
169                         /* inbound routing extensions */
170                         $didlist = core_did_list();
171                         if(is_array($didlist)){
172                                 $catchall = false;
173                                 $catchall_context='ext-did-catchall';
174                                 foreach($didlist as $item) {
175                                         $did = core_did_get($item['extension'],$item['cidnum'],$item['channel']);
176                                         $exten = $did['extension'];
177                                         $cidnum = $did['cidnum'];
178                                         $channel = $did['channel'];
179
180                                         $exten = (empty($exten)?"s":$exten);
181                                         $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it
182
183                                         if (empty($channel))
184                                                 $context = "ext-did";
185                                         else {
186                                                 $context = "macro-from-zaptel-{$channel}";
187                                                 if (!isset($zapchan[$channel])) {
188                                                         // create the macro-from-zaptel-$chan context and load up the
189                                                         // startup settings
190                                                         $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
191                                                         $ext->add($context, 's', '', new ext_noop('Entering '.$context.' with DID = ${DID}'));
192                                                         $zapchan[$channel] = "unfinished";
193                                                 }
194                                         }
195
196                                         // Start inbound processing. Unneeded line to be possibly overridden by something in
197                                         // extensions_custom.conf
198                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
199                                         // always set callerID name
200                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
201                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
202                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
203
204                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
205                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
206                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
207                                         }
208
209                                         // If we require RINGING, signal it as soon as we enter.
210                                         if ($item['ringing'] === "CHECKED") {
211                                                 $ext->add($context, $exten, '', new ext_ringing(''));
212                                         }
213
214                                         if ($exten == "s" && $context == "ext-did") { 
215                                                 //if the exten is s, then also make a catchall for undefined DIDs if it's not a zaptel route
216                                                 $catchaccount = "_X.".(empty($cidnum)?"":"/".$cidnum);
217                                                 if ($catchaccount == "_X.")
218                                                         $catchall = true;
219                                                 $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
220                                                 $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did'));
221                                         }
222                                        
223                                         if ($item['faxexten'] != "default") {
224                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
225                                         }
226                                         if (!empty($item['faxemail'])) {
227                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
228                                         }
229                                         if ($item['answer'] == "1") {
230                                                 $ext->add($context, $exten, '', new ext_answer(''));
231                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
232                                         }
233                                         if ($item['answer'] == "2") { // NVFaxDetect
234                                                 $ext->add($context, $exten, '', new ext_answer(''));
235                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
236                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
237                                         }
238                                         if ($item['privacyman'] == "1") {
239                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
240                                         }
241                                         if (!empty($item['alertinfo'])) {
242                                                 $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo'])));
243                                         }
244                                         // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should
245                                         // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different
246                                         // modules.
247                                         //
248                                         // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here.
249                                         //
250                                         // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX)
251                                         //
252                                         if (!empty($item['grppre'])) {
253                                                 $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre']));
254                                                 $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
255                                         }
256                                        
257                                         // If we're doing a zaptel route, now we need to do the gotos ONLY IF it's the first time round.
258                                         // Except for the fact that this doesn't work. Not at all. Dial returns -1 and hangs up the
259                                         // call. This is fixed in 1.4 with TryExec(), but until then, we can't match on zap
260                                         // _and_ anything else.  When we decide to say 'Only 1.4!' then we can reenable this
261                                         // and use TryExec(Goto..) and then check ${TRYSTATUS} for FAILED or SUCCESS. I didn't
262                                         // bother actually writing that, as the syntax may change.
263                                         //if (isset($zapchan[$channel]) && $zapchan[$channel] == "unfinished") {
264                                         //      $ext->add($context, 's', '', new ext_gotoif('$[ "${DID}" = "s" ]', 'nos', 'sok'));
265                                         //      $ext->add($context, 's', 'nos', new ext_noop('Skipping ${DID} because it is s'));
266                                         //      $ext->add($context, 's', '', new ext_goto("trycid"));
267                                         //      $ext->add($context, 's', 'sok', new ext_noop('Trying ${DID}'));
268                                         //      $ext->add($context, 's', '', new ext_goto("1", '${DID}'));
269                                         //      $ext->add($context, 's', 'trycid', new ext_gotoif('$[ "${CALLERID(num)}" = "" ]', 'nocid', 'cidok'));
270                                         //      $ext->add($context, 's', 'nocid', new ext_noop('Skipping empty CallerID Num'));
271                                         //      $ext->add($context, 's', '', new ext_goto("end"));
272                                         //      $ext->add($context, 's', 'cidok', new ext_noop('Trying ${DID}/${CALLERID(num)}'));
273                                         //      $ext->add($context, 's', '', new ext_goto("1", '${DID}/${CALLERID(num)}'));
274                                         //      $ext->add($context, 's', 'end', new ext_noop('End of macro init'));
275                                                 // Now set $zapchan[$channel] so we don't do this again
276                                                 $zapchan[$channel] = "set";
277                                         //}
278                                         //the goto destination
279                                         // destination field in 'incoming' database is backwards from what ext_goto expects
280                                         $goto_context = strtok($did['destination'],',');
281                                         $goto_exten = strtok(',');
282                                         $goto_pri = strtok(',');
283                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
284                                        
285                                 }
286                                 // If there's not a catchall, make one with an error message
287                                 if (!$catchall) {
288                                         $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
289                                         $ext->add($catchall_context, 's', '', new ext_answer(''));
290                                         $ext->add($catchall_context, 's', '', new ext_wait('2'));
291                                         $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
292                                         $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
293                                         $ext->add($catchall_context, '_[*#X].', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
294                                         $ext->add($catchall_context, '_[*#X].', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
295                                         $ext->add($catchall_context, '_[*#X].', '', new ext_goto('1','s','ext-did'));
296                                 }
297                                        
298                         }
299
300                         /* MODIFIED (PL)
301                          *
302                          * Add Direct DIDs
303                          *
304                          * This functions creates a new context, ext-did-direct, used to route an incoming DID directly to the specified user.
305                          * The purpose is to use when a user has a personal external DID. This keeps it clean and easy to administer.
306                          * Any conflict with those routes will depend on which of the two contexts are included first in the extensions.conf file.
307                          *
308                          * Calls are sent to context from-did-direct though this feature. You must create that context in extenions.conf or
309                          * in extensions_custom.conf and it should look something like:
310                          *
311                          * [from-did-direct]
312                          * include => ext-findmefollow
313                          * include => ext-local
314                          *
315                          * This is so that personal ring groups are used if they exist for the direct did and if not, then the local extension.
316                          * If the module is not implented, it will just go to the users extension.
317                          */
318
319                         $directdidlist = core_directdid_list();
320                         if(is_array($directdidlist)){
321                                 $context = "ext-did";
322                                 if(!is_array($didlist)){
323                                         /* if not set above, add one here */
324                                         $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
325                                 }
326                                 foreach($directdidlist as $item) {
327                                         $exten = $item['directdid'];
328                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
329                                         // always set callerID name
330                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
331                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
332                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
333
334                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
335                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
336                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
337                                         }
338                                        
339                                         if ($item['faxexten'] != "default") {
340                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
341                                         }
342                                         if (!empty($item['faxemail'])) {
343                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
344                                         }
345                                         if ($item['answer'] == "1") {
346                                                 $ext->add($context, $exten, '', new ext_answer(''));
347                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
348                                         }
349                                         if ($item['answer'] == "2") { // NVFaxDetect
350                                                 $ext->add($context, $exten, '', new ext_answer(''));
351                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
352                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
353                                         }
354                                         if ($item['privacyman'] == "1") {
355                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
356                                         }
357
358
359                                         if (!empty($item['didalert'])) {
360                                                 $ext->add($context, $exten, '', new ext_setvar("_ALERT_INFO", str_replace(';', '\;', $item['didalert'])));
361                                         }
362                                         $goto_context = 'from-did-direct';
363                                         $goto_exten = $item['extension'];
364                                         $goto_pri = 1;
365                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
366
367                                 }
368                         }
369
370                        
371                         /* user extensions */
372                         $ext->addInclude('from-internal-additional','ext-local');
373                         $userlist = core_users_list();
374                         if (is_array($userlist)) {
375                                 foreach($userlist as $item) {
376                                         $exten = core_users_get($item[0]);
377                                         $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']);
378
379                                         if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0)
380                                                 $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer']));
381                                        
382                                         $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension']));
383                                         $ext->add('ext-local', $exten['extension'], '', new ext_hangup(''));
384                                        
385                                         if($vm != "novm") {
386                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',"$vm,DIRECTDIAL"));
387                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_hangup(''));
388                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',"$vm,BUSY"));
389                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_hangup(''));
390                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',"$vm,NOANSWER"));
391                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_hangup(''));
392                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',"$vm,NOMESSAGE"));
393                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_hangup(''));
394                                         }
395                                                
396                                         $hint = core_hint_get($exten['extension']);
397                                         if (!empty($hint))
398                                                 $ext->addHint('ext-local', $exten['extension'], $hint);
399                                         if ($exten['sipname']) {
400                                                 $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal'));
401                                         }
402                                 }
403                         }
404
405                         // create from-trunk context for each trunk that adds counts to channels
406                         //
407                         $trunklist = core_trunks_list(true);
408                         if (is_array($trunklist)) {
409                                 foreach ($trunklist as $trunkprops) {
410                                         if (trim($trunkprops['value']) == 'on') {
411                                                 // value of on is disabled and for zap we don't create a context
412                                                 continue;
413                                         }
414                                         switch ($trunkprops['tech']) {
415                                                 case 'IAX':
416                                                 case 'IAX2':
417                                                 case 'SIP':
418                                                         $trunkgroup = $trunkprops['globalvar'];
419                                                         $trunkcontext  = "from-trunk-".$trunkprops['name'];
420                                                         $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup));
421                                                         $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk'));
422                                                         break;
423                                                 default:
424                                         }
425                                 }
426                         }
427
428                         /* dialplan globals */
429                         // modules should NOT use the globals table to store anything!
430                         // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
431                         // I'm cheating for core functionality - do as I say, not as I do ;-)           
432
433                         // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
434                         //
435                         $amp_conf_globals = array(
436                                 "ASTETCDIR",
437                                 "ASTMODDIR",
438                                 "ASTVARLIBDIR",
439                                 "ASTAGIDIR",
440                                 "ASTSPOOLDIR",
441                                 "ASTRUNDIR",
442                                 "ASTLOGDIR",
443                                 "CWINUSEBUSY",
444                                 "AMPMGRUSER",
445                                 "AMPMGRPASS"
446                         );
447
448                         $sql = "SELECT * FROM globals";
449                         $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
450                         foreach($globals as $global) {
451                                 $ext->addGlobal($global['variable'],$global['value']);
452
453                                 // now if for some reason we have a variable in the global table
454                                 // that is in our $amp_conf_globals list, then remove it so we
455                                 // don't duplicate, the sql table will take precedence
456                                 //
457                                 if (array_key_exists($global['variable'],$amp_conf_globals)) {
458                                         $rm_keys = array_keys($amp_conf_globals,$global['variable']);
459                                         foreach ($rm_keys as $index) {
460                                                 unset($amp_conf_globals[$index]);
461                                         }
462                                 }
463                         }
464                         foreach ($amp_conf_globals as $global) {
465                                 if (isset($amp_conf[$global])) {
466                                         $value = $amp_conf[$global];
467                                         if ($value === true || $value === false) {
468                                                 $value = ($value) ? 'true':'false';
469                                         }
470                                         $ext->addGlobal($global, $value);
471                                         out("Added to globals: $global = $value");
472                                 }
473                         }
474                        
475                         /* outbound routes */
476                         // modules should use their own table for storage (and module_get_config() to add dialplan)
477                         // modules should NOT use the extension table to store anything!
478                         $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application";
479                         $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
480                         $ext->addInclude('from-internal-additional','outbound-allroutes');
481                         $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
482                         foreach($outrts as $outrt) {
483                                 $ext->addInclude('outbound-allroutes',$outrt['application']);
484                                 $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC";
485                                 $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
486                                 foreach($thisrt as $exten) {
487                                         //if emergencyroute, then set channel var
488                                         if(strpos($exten['args'],"EMERGENCYROUTE") !== false)
489                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15)));
490                                         if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false)
491                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18)));
492                                         // Don't set MOHCLASS if already set, threre may be a feature code that overrode it
493                                         if(strpos($exten['args'],"MOHCLASS") !== false)
494                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' ));
495                                         if(strpos($exten['args'],"dialout-trunk") !== false)
496                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
497                                         if(strpos($exten['args'],"dialout-enum") !== false)
498                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
499                                         if(strpos($exten['args'],"outisbusy") !== false)
500                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy"));
501                                 }
502                         }
503                         general_generate_indications();
504
505                         // "blackhole" destinations
506                         $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
507                         $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
508
509                         $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
510                         $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
511                         $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
512                         // Should hangup ?
513                         // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
514                                        
515                         $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
516                         $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
517                         $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
518
519                         $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
520                         $ext->add('app-blackhole', 'congestion', '', new ext_answer());
521                         $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
522                         $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
523                         $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
524
525                         $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
526                         $ext->add('app-blackhole', 'busy', '', new ext_answer());
527                         $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy'));
528                         $ext->add('app-blackhole', 'busy', '', new ext_busy());
529                         $ext->add('app-blackhole', 'busy', '', new ext_hangup());
530
531                         if ($amp_conf['AMPBADNUMBER'] !== false) {
532                                 $context = 'bad-number';
533                                 $exten = '_X.';
534                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
535                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
536                                 $ext->add($context, $exten, '', new ext_wait('1'));
537                                 $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
538                                 $ext->add($context, $exten, '', new ext_wait('1'));
539                                 $ext->add($context, $exten, '', new ext_congestion('20'));
540                                 $ext->add($context, $exten, '', new ext_hangup());
541
542                                 $exten = '_*.';
543                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
544                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
545                                 $ext->add($context, $exten, '', new ext_wait('1'));
546                                 $ext->add($context, $exten, '', new ext_playback('silence/1&feature-not-avail-line&silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
547                                 $ext->add($context, $exten, '', new ext_wait('1'));
548                                 $ext->add($context, $exten, '', new ext_congestion('20'));
549                                 $ext->add($context, $exten, '', new ext_hangup());
550                         }
551
552                 break;
553         }
554 }
555
556
557
558
559
560
561
562
563
564
565
566 /* begin page.ampusers.php functions */
567
568 function core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections) {
569         $sql = "INSERT INTO ampusers (username, password, extension_low, extension_high, deptname, sections) VALUES (";
570         $sql .= "'".$username."',";
571         $sql .= "'".$password."',";
572         $sql .= "'".$extension_low."',";
573         $sql .= "'".$extension_high."',";
574         $sql .= "'".$deptname."',";
575         $sql .= "'".implode(";",$sections)."');";
576        
577         sql($sql,"query");
578 }
579
580 function core_ampusers_del($username) {
581         $sql = "DELETE FROM ampusers WHERE username = '".$username."'";
582         sql($sql,"query");
583 }
584
585 function core_ampusers_list() {
586         $sql = "SELECT username FROM ampusers ORDER BY username";
587         return sql($sql,"getAll");
588 }
589
590 /* end page.ampusers.php functions */
591
592
593
594
595
596
597
598
599
600 /* begin page.did.php functions */
601
602 function core_did_list($order='extension'){
603         switch ($order) {
604                 case 'description':
605                         $sql = "SELECT * FROM incoming ORDER BY description,extension,cidnum";
606                         break;
607                 case 'extension':
608                 default:
609                         $sql = "SELECT * FROM incoming ORDER BY extension,cidnum";
610         }
611         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
612 }
613
614 function core_did_get($extension="",$cidnum="",$channel=""){
615         $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\" AND channel = \"$channel\"";
616         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
617 }
618
619 function core_did_del($extension,$cidnum, $channel){
620         $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\" AND channel = \"$channel\"";
621         sql($sql);
622 }
623
624 function core_did_edit($old_extension,$old_cidnum, $old_channel, $incoming){
625
626         $old_extension = addslashes(trim($old_extension));
627         $old_cidnum = addslashes(trim($old_cidnum));
628         $old_channel = addslashes(trim($old_channel));
629
630         $incoming['extension'] = trim($incoming['extension']);
631         $incoming['cidnum'] = trim($incoming['cidnum']);
632         $incoming['channel'] = trim($incoming['channel']);
633
634         $extension = addslashes($incoming['extension']);
635         $cidnum = addslashes($incoming['cidnum']);
636         $channel = addslashes($incoming['channel']);
637
638         // if did or cid changed, then check to make sure that this pair is not already being used.
639         //
640         if (($extension != $old_extension) || ($cidnum != $old_cidnum)) {
641                 $existing=core_did_get($extension,$cidnum,$channel);
642                 if (empty($existing) && (trim($cidnum) == "")) {
643                         $existing_directdid = core_users_directdid_get($extension);
644                 } else {
645                         $existing_directdid = "";
646                 }
647         } else {
648                 $existing = $existing_directdid = "";
649         }
650
651         if (empty($existing) && empty($existing_directdid)) {
652                 core_did_del($old_extension,$old_cidnum,$old_channel);
653                 core_did_add($incoming);
654                 return true;
655         } else {
656                 if (!empty($existing)) {
657                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
658                 } else {
659                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
660                 }
661                 return false;
662         }
663 }
664
665 function core_did_add($incoming){
666         foreach ($incoming as $key => $val) { ${$key} = addslashes($val); } // create variables from request
667
668         // Check to make sure the did is not being used elsewhere
669         //
670         $existing=core_did_get($extension,$cidnum,$channel);
671         if (empty($existing) && (trim($cidnum) == "")) {
672                 $existing_directdid = core_users_directdid_get($extension);
673         } else {
674                 $existing_directdid = "";
675         }
676
677         if (empty($existing) && empty($existing_directdid)) {
678                 $destination=${$goto0.'0'};
679                 $sql="INSERT INTO incoming (cidnum,extension,destination,faxexten,faxemail,answer,wait,privacyman,alertinfo, channel, ringing, mohclass, description, grppre) values ('$cidnum','$extension','$destination','$faxexten','$faxemail','$answer','$wait','$privacyman','$alertinfo', '$channel', '$ringing', '$mohclass', '$description', '$grppre')";
680                 sql($sql);
681                 return true;
682         } else {
683                 if (!empty($existing)) {
684                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
685                 } else {
686                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
687                 }
688                 return false;
689         }
690 }
691
692 /* end page.did.php functions */
693
694
695
696
697
698
699
700 /* begin page.devices.php functions */
701
702 //get the existing devices
703 function core_devices_list($tech="all") {
704         $sql = "SELECT id,description FROM devices";
705         switch (strtoupper($tech)) {
706                 case "IAX":
707                         $sql .= " WHERE tech = 'iax2'";
708                         break;
709                 case "IAX2":
710                 case "SIP":
711                 case "ZAP":
712                         $sql .= " WHERE tech = '".strtolower($tech)."'";
713                         break;
714                 case "ALL":
715                 default:
716         }
717         $sql .= ' ORDER BY id';
718         $results = sql($sql,"getAll");
719
720         foreach($results as $result){
721                 if (checkRange($result[0])){
722                         $extens[] = array(
723                                 0=>$result[0],  // for backwards compatibility
724                                 1=>$result[1],
725                                 'id'=>$result[0], // FETCHMODE_ASSOC emulation
726                                 'description'=>$result[1],
727                         );
728                 }
729         }
730         if (isset($extens)) {
731                 return $extens;
732         } else {
733                 return null;
734         }
735 }
736
737
738 function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){
739         global $amp_conf;
740         global $currentFile;
741         global $astman;
742
743         $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
744
745         if (trim($id) == '' ) {
746                 if ($display != 'extensions') {
747                         echo "<script>javascript:alert('"._("You must put in a device id")."');</script>";
748                 }
749                 return false;
750         }
751        
752         //ensure this id is not already in use
753         $devices = core_devices_list();
754         if (is_array($devices)) {
755                 foreach($devices as $device) {
756                         if ($device[0] === $id) {
757                                 if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
758                                 return false;
759                         }
760                 }
761         }
762         //unless defined, $dial is TECH/id
763         if ( $dial == '' ) {
764                 //zap is an exception
765                 if ( strtolower($tech) == "zap" ) {
766                         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
767                         $dial = 'ZAP/'.$zapchan;
768                 } else {
769                         $dial = strtoupper($tech)."/".$id;
770                 }
771         }
772        
773         //check to see if we are requesting a new user
774         if ($user == "new") {
775                 $user = $id;
776                 $jump = true;
777         }
778        
779         if(!get_magic_quotes_gpc()) {
780                 if(!empty($emergency_cid))
781                         $emergency_cid = addslashes($emergency_cid);
782                 if(!empty($description))
783                         $description = addslashes($description);
784         }
785        
786         //insert into devices table
787         $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
788         sql($sql);
789        
790         //add details to astdb
791         if ($astman) {
792                 // if adding or editting a fixed device, user property should always be set
793                 if ($devicetype == 'fixed' || !$editmode) {
794                         $astman->database_put("DEVICE",$id."/user",$user);
795                 }
796                 // If changing from a fixed to an adhoc, the user property should be intialized
797                 // to the new default, not remain as the previous fixed user
798                 if ($editmode) {
799                         $previous_type = $astman->database_get("DEVICE",$id."/type");
800                         if ($previous_type == 'fixed' && $devicetype == 'adhoc') {
801                                 $astman->database_put("DEVICE",$id."/user",$user);
802                         }
803                 }
804                 $astman->database_put("DEVICE",$id."/dial",$dial);
805                 $astman->database_put("DEVICE",$id."/type",$devicetype);
806                 $astman->database_put("DEVICE",$id."/default_user",$user);
807                 if(!empty($emergency_cid)) {
808                         $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
809                 }
810
811                 if ($user != "none") {
812                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
813                         if (empty($existingdevices)) {
814                                 $astman->database_put("AMPUSER",$user."/device",$id);
815                         } else {
816                                 $existingdevices_array = explode('&',$existingdevices);
817                                 if (!in_array($id, $existingdevices_array)) {
818                                         $existingdevices_array[]=$id;
819                                         $existingdevices = implode('&',$existingdevices_array);
820                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices);
821                                 }
822                         }
823                 }
824
825         } else {
826                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
827         }
828        
829         // create a voicemail symlink if needed
830         $thisUser = core_users_get($user);
831         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
832                 if(empty($thisUser['voicemail']))
833                         $vmcontext = "default";
834                 else
835                         $vmcontext = $thisUser['voicemail'];
836                
837                 //voicemail symlink
838                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
839                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
840         }
841                
842         //take care of sip/iax/zap config
843         $funct = "core_devices_add".strtolower($tech);
844         if(function_exists($funct)){
845                 $funct($id);
846         }
847        
848 /*      if($user != "none") {
849                 core_hint_add($user);
850         }*/
851        
852         //if we are requesting a new user, let's jump to users.php
853         if (isset($jump)) {
854                 echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
855         }
856         return true;
857 }
858
859 function core_devices_del($account,$editmode=false){
860         global $amp_conf;
861         global $currentFile;
862         global $astman;
863        
864         //get all info about device
865         $devinfo = core_devices_get($account);
866        
867         //delete details to astdb
868         if ($astman) {
869                 // If a user was selected, remove this device from the user
870                 $deviceuser = $astman->database_get("DEVICE",$account."/user");
871                 if (isset($deviceuser) && $deviceuser != "none") {
872                         // Remove the device record from the user's device list
873                         $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
874
875                         // We need to remove just this user and leave the rest alone
876                         $userdevicesarr = explode("&", $userdevices);
877                         $userdevicesarr_hash = array_flip($userdevicesarr);
878                         unset($userdevicesarr_hash[$account]);
879                         $userdevicesarr = array_flip($userdevicesarr_hash);
880                         $userdevices = implode("&", $userdevicesarr);
881                        
882                         if (empty($userdevices)) {
883                                         $astman->database_del("AMPUSER",$deviceuser."/device");
884                         } else {
885                                         $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
886                         }
887                 }
888                 if (! $editmode) {
889                         $astman->database_del("DEVICE",$account."/dial");
890                         $astman->database_del("DEVICE",$account."/type");
891                         $astman->database_del("DEVICE",$account."/user");
892                         $astman->database_del("DEVICE",$account."/default_user");
893                         $astman->database_del("DEVICE",$account."/emergency_cid");
894                 }
895
896                 //delete from devices table
897                 $sql="DELETE FROM devices WHERE id = \"$account\"";
898                 sql($sql);
899
900                 //voicemail symlink
901                 exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
902         } else {
903                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
904         }
905        
906         //take care of sip/iax/zap config
907         $funct = "core_devices_del".strtolower($devinfo['tech']);
908         if(function_exists($funct)){
909                 $funct($account);
910         }
911 }
912
913 function core_devices_get($account){
914         //get all the variables for the meetme
915         $sql = "SELECT * FROM devices WHERE id = '$account'";
916         $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
917        
918         //take care of sip/iax/zap config
919         $funct = "core_devices_get".strtolower($results['tech']);
920         if (!empty($results['tech']) && function_exists($funct)) {
921                 $devtech = $funct($account);
922                 if (is_array($devtech)){
923                         $results = array_merge($results,$devtech);
924                 }
925         }
926        
927         return $results;
928 }
929
930 // this function rebuilds the astdb based on device table contents
931 // used on devices.php if action=resetall
932 function core_devices2astdb(){
933         global $astman;
934         global $amp_conf;
935
936         $sql = "SELECT * FROM devices";
937         $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
938
939         //add details to astdb
940         if ($astman) {
941                 $astman->database_deltree("DEVICE");
942                 foreach ($devresults as $dev) {
943                         extract($dev); 
944                         $astman->database_put("DEVICE",$id."/dial",$dial);
945                         $astman->database_put("DEVICE",$id."/type",$devicetype);
946                         $astman->database_put("DEVICE",$id."/user",$user);             
947                         // If a user is selected, add this device to the user
948                         if ($user != "none") {
949                                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
950                                         if (!empty($existingdevices)) {
951                                                         $existingdevices .= "&";
952                                         }
953                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
954                         }
955                        
956                         // create a voicemail symlink if needed
957                         $thisUser = core_users_get($user);
958                         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
959                                 if(empty($thisUser['voicemail']))
960                                         $vmcontext = "default";
961                                 else
962                                         $vmcontext = $thisUser['voicemail'];
963                                 //voicemail symlink
964                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
965                                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
966                         }
967                 }
968                 return true;
969         } else {
970                 return false;
971         }
972 }
973
974 // this function rebuilds the astdb based on users table contents
975 // used on devices.php if action=resetall
976 function core_users2astdb(){
977         global $amp_conf;
978         global $astman;
979
980         $sql = "SELECT * FROM users";
981         $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
982        
983         //add details to astdb
984         if ($astman) {
985                 foreach($userresults as $usr) {
986                         extract($usr);
987                         $astman->database_put("AMPUSER",$extension."/password",$password);
988                         $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
989                         $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
990                         $astman->database_put("AMPUSER",$extension."/recording",$recording);
991                         $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
992                         $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
993                         $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
994                 }       
995                 return true;
996         } else {
997                 return false;
998         }
999
1000 //      TODO: this was...       
1001 //      return $astman->disconnect();
1002 //      is "true" the correct value...?
1003 }
1004
1005 //add to sip table
1006 function core_devices_addsip($account) {
1007         global $db;
1008         global $currentFile;
1009
1010         foreach ($_REQUEST as $req=>$data) {
1011                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1012                         $keyword = substr($req, 8);
1013                         if ( $keyword == 'dial' && $data == '' ) {
1014                                 $sipfields[] = array($account, $keyword, 'SIP/'.$account);
1015                         } elseif ($keyword == 'mailbox' && $data == '') {
1016                                 $sipfields[] = array($account,'mailbox',$account.'@device');
1017                         } else {
1018                                 $sipfields[] = array($account, $keyword, $data);
1019                         }
1020                 }
1021         }
1022        
1023         if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
1024                 $sipfields = array(
1025                         //array($account,'account',$account),
1026                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1027                         array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
1028                         array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
1029                         array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
1030                         array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
1031                         array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
1032                         array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
1033                         array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
1034                         array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
1035                         array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
1036                         array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
1037                         array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
1038                         array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
1039                         array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
1040                         array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
1041                         array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
1042                         //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
1043                         //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
1044                         //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1045                 );
1046         }
1047
1048         // Very bad
1049         $sipfields[] = array($account,'account',$account);     
1050         $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1051        
1052         // Where is this in the interface ??????
1053         $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1054         $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1055
1056         $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
1057         $result = $db->executeMultiple($compiled,$sipfields);
1058         if(DB::IsError($result)) {
1059                 die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table');   
1060         }
1061 }
1062
1063 function core_devices_delsip($account) {
1064         global $db;
1065         global $currentFile;
1066        
1067         $sql = "DELETE FROM sip WHERE id = '$account'";
1068         $result = $db->query($sql);
1069        
1070         if(DB::IsError($result)) {
1071                 die_freepbx($result->getMessage().$sql);
1072         }
1073 }
1074
1075 function core_devices_getsip($account) {
1076         global $db;
1077         $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
1078         $results = $db->getAssoc($sql);
1079         if(DB::IsError($results)) {
1080                 $results = null;
1081         }
1082        
1083         return $results;
1084 }
1085
1086 //add to iax table
1087 function core_devices_addiax2($account) {
1088         global $db;
1089         global $currentFile;
1090        
1091         foreach ($_REQUEST as $req=>$data) {
1092                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1093                         $keyword = substr($req, 8);
1094                         if ( $keyword == 'dial' && $data == '' ) {
1095                                 $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
1096                         } elseif ($keyword == 'mailbox' && $data == '') {
1097                                 $iaxfields[] = array($account,'mailbox',$account.'@device');
1098                         } else {
1099                                 $iaxfields[] = array($account, $keyword, $data);
1100                         }
1101                 }
1102         }
1103        
1104         if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
1105                 $iaxfields = array(
1106                         //array($account,'account',$account),
1107                         array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
1108                         array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
1109                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1110                         array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
1111                         array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
1112                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1113                         array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
1114                         array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
1115                         array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
1116                         array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
1117                         array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
1118                         array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
1119                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
1120                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1121                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1122                 );
1123         }
1124
1125         // Very bad
1126         $iaxfields[] = array($account,'account',$account);     
1127         $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1128         // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
1129         // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
1130         // callerid as a variable which gets picked up in macro-callerid.
1131         // Ref - http://bugs.digium.com/view.php?id=456
1132         $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
1133        
1134         // Where is this in the interface ??????
1135         $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1136         $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1137        
1138         $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
1139         $result = $db->executeMultiple($compiled,$iaxfields);
1140         if(DB::IsError($result)) {
1141                 die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
1142         }
1143 }
1144
1145 function core_devices_deliax2($account) {
1146         global $db;
1147         global $currentFile;
1148        
1149         $sql = "DELETE FROM iax WHERE id = '$account'";
1150         $result = $db->query($sql);
1151        
1152         if(DB::IsError($result)) {
1153                 die_freepbx($result->getMessage().$sql);
1154         }
1155 }
1156
1157 function core_devices_getiax2($account) {
1158         global $db;
1159         $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
1160         $results = $db->getAssoc($sql);
1161         if(DB::IsError($results)) {
1162                 $results = null;
1163         }
1164        
1165         return $results;
1166 }
1167
1168 function core_devices_addzap($account) {
1169         global $db;
1170         global $currentFile;
1171        
1172         foreach ($_REQUEST as $req=>$data) {
1173                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1174                         $keyword = substr($req, 8);
1175                         if ( $keyword == 'dial' && $data == '' ) {
1176                                 $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1177                                 $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
1178                         } elseif ($keyword == 'mailbox' && $data == '') {
1179                                 $zapfields[] = array($account,'mailbox',$account.'@device');
1180                         } else {
1181                                 $zapfields[] = array($account, $keyword, $data);
1182                         }
1183                 }
1184         }
1185        
1186         if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
1187                 $zapfields = array(
1188                         //array($account,'account',$account),
1189                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1190                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1191                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
1192                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1193                         array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
1194                         array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
1195                         array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
1196                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),       
1197                         array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
1198                         array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
1199                         array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
1200                         array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
1201                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),     
1202                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1203                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1204                         array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
1205                 );
1206         }
1207
1208         // Very bad
1209         $zapfields[] = array($account,'account',$account);     
1210         $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1211        
1212         // Where is this in the interface ??????
1213         $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1214         $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1215
1216         $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
1217         $result = $db->executeMultiple($compiled,$zapfields);
1218         if(DB::IsError($result)) {
1219                 die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
1220         }
1221 }
1222
1223 function core_devices_delzap($account) {
1224         global $db;
1225         global $currentFile;
1226        
1227         $sql = "DELETE FROM zap WHERE id = '$account'";
1228         $result = $db->query($sql);
1229         if(DB::IsError($result)) {
1230                 die_freepbx($result->getMessage().$sql);
1231         }
1232 }
1233
1234 function core_devices_getzap($account) {
1235         global $db;
1236         $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
1237         $results = $db->getAssoc($sql);
1238         if(DB::IsError($results)) {
1239                 $results = null;
1240         }
1241         return $results;
1242 }
1243 /* end page.devices.php functions */
1244
1245
1246
1247
1248 function core_hint_get($account){
1249         //determine what devices this user is associated with
1250         $sql = "SELECT dial from devices where user = '{$account}'";
1251         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1252         //print_r($results);
1253        
1254         //create an array of strings
1255         if (is_array($results)){
1256                 foreach ($results as $result) {
1257                         $dial[] = $result['dial'];
1258                 }
1259         }
1260        
1261         //create a string with & delimiter
1262         if (isset($dial) && is_array($dial)){
1263                 $hint = implode($dial,"&");
1264         } else {
1265                 if (isset($results[0]['dial'])) {
1266                         $hint = $results[0]['dial'];
1267                 } else {
1268                         $hint = null;
1269                 }
1270         }
1271        
1272         return $hint;
1273 }
1274
1275
1276
1277 /* begin page.users.php functions */
1278
1279 // get the existing extensions
1280 // the returned arrays contain [0]:extension [1]:name
1281 function core_users_list() {
1282         $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
1283
1284         //only allow extensions that are within administrator's allowed range
1285         foreach($results as $result){
1286                 if (checkRange($result[0])){
1287                         $extens[] = array($result[0],$result[1]);
1288                 }
1289         }
1290        
1291         if (isset($extens)) {
1292                 sort($extens);
1293                 return $extens;
1294         } else {
1295                 return null;
1296         }
1297 }
1298
1299 function core_sipname_check($sipname, $extension) {
1300         global $db;
1301         if (!isset($sipname) || trim($sipname)=='')
1302                 return true;
1303
1304         $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
1305         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1306         if(DB::IsError($results)) {
1307         die_freepbx($results->getMessage().$sql);
1308         }
1309        
1310         if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
1311                 return false;
1312         else
1313                 return true;
1314 }
1315
1316 function core_users_add($vars) {
1317         extract($vars);
1318        
1319         global $db;
1320         global $amp_conf;
1321         global $astman;
1322
1323         $thisexten = isset($thisexten) ? $thisexten : '';
1324
1325         if (trim($extension) == '' ) {
1326                 echo "<script>javascript:alert('"._("You must put in an extension (or user) number")."');</script>";
1327                 return false;
1328         }
1329
1330         //ensure this id is not already in use
1331         $extens = core_users_list();
1332         if(is_array($extens)) {
1333                 foreach($extens as $exten) {
1334                         if ($exten[0]===$extension) {
1335                                 echo "<script>javascript:alert('".sprintf(_("This user/extension %s is already in use"),$extension)."');</script>";
1336                                 return false;
1337                         }
1338                 }
1339         }
1340
1341         // clean and check the did to make sure it is not being used by another extension or in did routing
1342         //
1343         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1344         if (trim($directdid) != "") {
1345                 $existing=core_did_get($directdid,"","");
1346                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1347                 if (!empty($existing) || !empty($existing_directdid)) {
1348                         if (!empty($existing)) {
1349                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1350                         } else {
1351                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1352                         }
1353                         return false;
1354                 }
1355         }
1356
1357         $sipname = preg_replace("/\s/" ,"", trim($sipname));
1358         if (! core_sipname_check($sipname, $extension)) {
1359                 echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
1360                 return false;
1361         }
1362        
1363         //build the recording variable
1364         $recording = "out=".$record_out."|in=".$record_in;
1365        
1366         //escape quotes and any other bad chars:
1367         if(!get_magic_quotes_gpc()) {
1368                 $outboundcid = addslashes($outboundcid);
1369                 $name = addslashes($name);
1370         }
1371
1372         //if voicemail is enabled, set the box@context to use
1373         //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
1374         if ( function_exists('voicemail_mailbox_get') ) {
1375                 $vmbox = voicemail_mailbox_get($extension);
1376                 if ( $vmbox == null ) {
1377                         $voicemail = "novm";
1378                         $vmx_state = "false";
1379                 } else {
1380                         $voicemail = $vmbox['vmcontext'];
1381                 }
1382         }
1383
1384         // MODIFICATION: (PL)
1385         // Added for directdid and didalert l for Alert Info distinctive ring)
1386         //
1387         // cleanup any non dial pattern characters prior to inserting into the database
1388         // then add directdid to the insert command.
1389         //
1390         // Clean replace any <> with () in display name - should have javascript stopping this but ...
1391         //
1392         $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
1393        
1394         //insert into users table
1395         $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
1396         $sql.= "$extension\", \"";
1397         $sql.= isset($password)?$password:'';
1398         $sql.= "\", \"";
1399         $sql.= isset($name)?$name:'';
1400         $sql.= "\", \"";
1401         $sql.= isset($voicemail)?$voicemail:'default';
1402         $sql.= "\", \"";
1403         $sql.= isset($ringtimer)?$ringtimer:'';
1404         $sql.= "\", \"";
1405         $sql.= isset($noanswer)?$noanswer:'';
1406         $sql.= "\", \"";
1407         $sql.= isset($recording)?$recording:'';
1408         $sql.= "\", \"";
1409         $sql.= isset($outboundcid)?$outboundcid:'';
1410         $sql.= "\", \"";
1411         $sql.= isset($directdid)?$directdid:'';
1412         $sql.= "\", \"";
1413         $sql.= isset($didalert)?$didalert:'';
1414
1415         $sql.= "\", \"";
1416         $sql.= isset($faxexten)?$faxexten:'';
1417         $sql.= "\", \"";
1418         $sql.= isset($faxemail)?$faxemail:'';
1419         $sql.= "\", \"";
1420         $sql.= isset($answer)?$answer:'';
1421         $sql.= "\", \"";
1422         $sql.= isset($wait)?$wait:'';
1423         $sql.= "\", \"";
1424         $sql.= isset($privacyman)?$privacyman:'';
1425         $sql.= "\", \"";
1426         $sql.= isset($mohclass)?$mohclass:'';
1427         $sql.= "\", \"";
1428         $sql.= isset($sipname)?$sipname:'';
1429         $sql.= "\")";
1430         sql($sql);
1431
1432         //write to astdb
1433         if ($astman) {
1434                 $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
1435                 $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
1436                 $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
1437                 $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
1438                 $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
1439                 $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
1440                 $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
1441                 $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
1442                 $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
1443                 $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
1444
1445                 if (trim($callwaiting) == 'enabled') {
1446                         $astman->database_put("CW",$extension,"\"ENABLED\"");
1447                 } else if (trim($callwaiting) == 'disabled') {
1448                         $astman->database_del("CW",$extension);
1449                 } else {
1450                         echo "ERROR: this state should not exist<br>";
1451                 }
1452
1453                 if ($vmx_state && $voicemail != "novm") {
1454
1455                         $unavail_mode="enabled";
1456                         $busy_mode="disabled";
1457                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1458
1459                         if (trim($vmx_state) == 'blocked') {
1460
1461                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
1462                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
1463
1464                         } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
1465
1466                                 $repeat="1";
1467                                 $timeout="2";
1468                                 $vmxopts_timeout="";
1469                                 $loops="1";
1470
1471                                 $mode="unavail";
1472                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
1473                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1474                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1475                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1476                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1477
1478                                 $mode="busy";
1479                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
1480                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1481                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1482                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1483                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1484                                
1485                         }
1486                 } else {
1487                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1488                         if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
1489                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
1490                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
1491                         }
1492                 }
1493         } else {
1494                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1495         }
1496         return true;
1497 }
1498
1499 function core_users_get($extension){
1500         global $db;
1501         global $amp_conf;
1502         global $astman;
1503         //get all the variables for the meetme
1504         $sql = "SELECT * FROM users WHERE extension = '$extension'";
1505         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1506         if(DB::IsError($results)) {
1507                 die_freepbx($results->getMessage().$sql);
1508         }
1509        
1510         //explode recording vars
1511         $recording = explode("|",$results['recording']);
1512         if (isset($recording[1])) {
1513                 $recout = substr($recording[0],4);
1514                 $recin = substr($recording[1],3);
1515                 $results['record_in']=$recin;
1516                 $results['record_out']=$recout;
1517         } else {
1518                 $results['record_in']='Adhoc';
1519                 $results['record_out']='Adhoc';
1520         }
1521         if ($astman) {
1522                 $cw = $astman->database_get("CW",$extension);
1523                 $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
1524                 $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1525                 $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
1526                 $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
1527         } else {
1528                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1529         }
1530
1531         return $results;
1532 }
1533
1534 function core_users_del($extension){
1535         global $db;
1536         global $amp_conf;
1537         global $astman;
1538        
1539         //delete from devices table
1540         $sql="DELETE FROM users WHERE extension = \"$extension\"";
1541         $results = $db->query($sql);
1542         if(DB::IsError($results)) {
1543                 die_freepbx($results->getMessage().$sql);
1544         }
1545
1546         //delete details to astdb
1547         if ($astman) {
1548                 $astman->database_del("AMPUSER",$extension."/password");
1549                 $astman->database_del("AMPUSER",$extension."/ringtimer");
1550                 $astman->database_del("AMPUSER",$extension."/noanswer");
1551                 $astman->database_del("AMPUSER",$extension."/recording");
1552                 $astman->database_del("AMPUSER",$extension."/outboundcid");
1553                 $astman->database_del("AMPUSER",$extension."/cidname");
1554                 $astman->database_del("AMPUSER",$extension."/cidnum");
1555                 $astman->database_del("AMPUSER",$extension."/voicemail");
1556                 $astman->database_del("AMPUSER",$extension."/device");
1557         } else {
1558                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1559         }
1560 }
1561
1562 function core_users_directdid_get($directdid=""){
1563         if (empty($directdid)) {
1564                 return array();
1565         } else {
1566                 $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
1567                 return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1568         }
1569 }
1570
1571 function core_users_cleanastdb($extension) {
1572         // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
1573         // call forwarding, call waiting settings could hang around and bite someone if they
1574         // recycle an extension. Is called from page.xtns and page.users.
1575         global $amp_conf;
1576         global $astman;
1577
1578         if ($astman) {
1579                 $astman->database_del("CW",$extension);
1580                 $astman->database_del("CF",$extension);
1581                 $astman->database_del("CFB",$extension);
1582                 $astman->database_del("CFU",$extension);
1583                 $astman->database_deltree("AMPUSER/".$extension."/vmx");
1584
1585         } else {
1586                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1587         }
1588 }
1589
1590 function core_users_edit($extension,$vars){
1591         global $db;
1592         global $amp_conf;
1593         global $astman;
1594        
1595         //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
1596         if ($astman) {
1597                 $ud = $astman->database_get("AMPUSER",$extension."/device");
1598                 $vars['device'] = $ud;
1599         } else {
1600                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1601         }
1602        
1603         $directdid=$vars['directdid'];
1604         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1605         // clean and check the did to make sure it is not being used by another extension or in did routing
1606         //
1607         if (trim($directdid) != "") {
1608                 $existing=core_did_get($directdid,"","");
1609                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1610                 if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
1611                         if (!empty($existing)) {
1612                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1613                         } else {
1614                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1615                         }
1616                         return false;
1617                 }
1618         }
1619
1620         //delete and re-add
1621         if (core_sipname_check($vars['sipname'],$extension)) {
1622                 core_users_del($extension);
1623                 core_users_add($vars);
1624         }
1625         return true;
1626        
1627 }
1628
1629 function core_directdid_list(){
1630         $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
1631         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1632 }
1633
1634
1635
1636 /* end page.users.php functions */
1637
1638
1639
1640
1641
1642 /* begin page.trunks.php functions */
1643
1644 // we're adding ,don't require a $trunknum
1645 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1646         global $db;
1647        
1648         // find the next available ID
1649         $trunknum = 1;
1650         foreach(core_trunks_list() as $trunk) {
1651                 if ($trunknum == ltrim($trunk[0],"OUT_")) {
1652                         $trunknum++;
1653                 }
1654         }
1655        
1656         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1657        
1658         return $trunknum;
1659 }
1660
1661 function core_trunks_del($trunknum, $tech = null) {
1662         global $db;
1663        
1664         if ($tech === null) { // in EditTrunk, we get this info anyways
1665                 $tech = core_trunks_getTrunkTech($trunknum);
1666         }
1667
1668         //delete from globals table
1669         sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
1670        
1671         //write outids
1672         core_trunks_writeoutids();
1673
1674         // conditionally, delete from iax or sip
1675         switch (strtolower($tech)) {
1676                 case "iax":
1677                 case "iax2":
1678                         sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1679                 break;
1680                 case "sip":
1681                         sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1682                 break;
1683         }
1684 }
1685
1686 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1687         //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1688         $tech = core_trunks_getTrunkTech($trunknum);
1689         core_trunks_del($trunknum, $tech);
1690         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1691 }
1692
1693 // just used internally by addTrunk() and editTrunk()
1694 //obsolete
1695 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1696         global $db;
1697        
1698         if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
1699        
1700         //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1701        
1702         // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
1703         $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
1704         $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
1705        
1706         $glofields = array(
1707                         array('OUT_'.$trunknum, $outval),
1708                         array('OUTPREFIX_'.$trunknum, $dialoutprefix),
1709                         array('OUTMAXCHANS_'.$trunknum, $maxchans),
1710                         array('OUTCID_'.$trunknum, $outcid),
1711                         array('OUTKEEPCID_'.$trunknum, $keepcid),
1712                         array('OUTFAIL_'.$trunknum, $failtrunk),
1713                         array('OUTDISABLE_'.$trunknum, $disabletrunk),
1714                         );
1715                        
1716         unset($techtemp);
1717        
1718         $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1719         $result = $db->executeMultiple($compiled,$glofields);
1720         if(DB::IsError($result)) {
1721                 die_freepbx($result->getMessage()."<br><br>".$sql);
1722         }
1723        
1724         core_trunks_writeoutids();
1725
1726         $disable_flag = ($disabletrunk == "on")?1:0;
1727        
1728         switch (strtolower($tech)) {
1729                 case "iax":
1730                 case "iax2":
1731                         core_trunks_addSipOrIax($peerdetails,'iax',$channelid,$trunknum,$disable_flag);
1732                         if ($usercontext != ""){
1733                                 core_trunks_addSipOrIax($userconfig,'iax',$usercontext,'9'.$trunknum,$disable_flag);
1734                         }
1735                         if ($register != ""){
1736                                 core_trunks_addRegister($trunknum,'iax',$register,$disable_flag);
1737                         }
1738                 break;
1739                 case "sip":
1740                         core_trunks_addSipOrIax($peerdetails,'sip',$channelid,$trunknum,$disable_flag);
1741                         if ($usercontext != ""){
1742                                 core_trunks_addSipOrIax($userconfig,'sip',$usercontext,'9'.$trunknum,$disable_flag);
1743                         }
1744                         if ($register != ""){
1745                                 core_trunks_addRegister($trunknum,'sip',$register,$disable_flag);
1746                         }
1747                 break;
1748         }       
1749 }
1750
1751 function core_trunks_getTrunkTech($trunknum) {
1752
1753         $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1754         if (!$results) {
1755                 return false;
1756         }
1757         if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1758                 $tech = "custom";
1759         } else {
1760                 $tech = strtolower( strtok($results[0][0],'/') ); // the technology.  ie: ZAP/g0 is ZAP
1761                
1762                 if ($tech == "iax2") $tech = "iax"; // same thing, here
1763         }
1764         return $tech;
1765 }
1766
1767 //add trunk info to sip or iax table
1768 function core_trunks_addSipOrIax($config,$table,$channelid,$trunknum,$disable_flag=0) {
1769         global $db;
1770        
1771         $confitem['account'] = $channelid;
1772         $gimmieabreak = nl2br($config);
1773         $lines = split('<br />',$gimmieabreak);
1774         foreach ($lines as $line) {
1775                 $line = trim($line);
1776                 if (count(split('=',$line)) > 1) {
1777                         $tmp = split('=',$line,2);
1778                         $key=trim($tmp[0]);
1779                         $value=trim($tmp[1]);
1780                         if (isset($confitem[$key]) && !empty($confitem[$key]))
1781                                 $confitem[$key].="&".$value;
1782                         else
1783                                 $confitem[$key]=$value;
1784                 }
1785         }
1786         foreach($confitem as $k=>$v) {
1787                 $dbconfitem[]=array($k,$v);
1788         }
1789         $compiled = $db->prepare("INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')");
1790         $result = $db->executeMultiple($compiled,$dbconfitem);
1791         if(DB::IsError($result)) {
1792                 die_freepbx($result->getMessage()."<br><br>INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')");       
1793         }
1794 }
1795
1796 //get unique trunks
1797 function core_trunks_list($assoc = false) {
1798         // TODO: $assoc default to true, eventually..
1799
1800         global $db;
1801         global $amp_conf;
1802        
1803         if ($amp_conf["AMPDBENGINE"] == "sqlite3")
1804         {
1805                 // TODO: sqlite work arround - diego
1806                 // TODO: WILL NOT WORK, need to remove the usage of SUBSTRING
1807                 // need to reorder the trunks in PHP code
1808                 $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1809                 $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\_%') d ";
1810                 $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\_%' ";
1811                 $sqlstr .= "UNION ALL ";
1812                 $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1813                 $sqlstr .= "WHERE v.variable LIKE 'OUT\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1814                 $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\_%' ) ";
1815                 $sqlstr .= "ORDER BY variable";
1816
1817                 //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT_%' ORDER BY variable","getAll");
1818                 $unique_trunks = sql($sqlstr,"getAll");
1819         }
1820         else
1821         {
1822                 // we have to escape _ for mysql: normally a wildcard
1823                 $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1824                 $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\\\_%') d ";
1825                 $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\\\_%' ";
1826                 $sqlstr .= "UNION ALL ";
1827                 $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1828                 $sqlstr .= "WHERE v.variable LIKE 'OUT\\\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1829                 $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\\\_%' ) ";
1830                 $sqlstr .= "ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0";
1831
1832                 //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT\\\_%' ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0","getAll");
1833                 $unique_trunks = sql($sqlstr,"getAll");
1834         }
1835
1836         //if no trunks have ever been defined, then create the proper variables with the default zap trunk
1837         if (count($unique_trunks) == 0)
1838         {
1839                 //If all trunks have been deleted from admin, dialoutids might still exist
1840                 sql("DELETE FROM globals WHERE variable = 'DIALOUTIDS'");
1841        
1842                 $glofields = array(array('OUT_1','ZAP/g0'),
1843                                                         array('DIAL_OUT_1','9'),
1844                                                         array('DIALOUTIDS','1'));
1845                 $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1846                 $result = $db->executeMultiple($compiled,$glofields);
1847                 if(DB::IsError($result))
1848                 {
1849                         die_freepbx($result->getMessage()."<br><br>".$sql);     
1850                 }
1851                 $unique_trunks[] = array('OUT_1','ZAP/g0');
1852         }
1853         // asort($unique_trunks);
1854
1855         if ($assoc) {
1856                 $trunkinfo = array();
1857
1858                 foreach ($unique_trunks as $trunk) {
1859                         list($tech,$name) = explode('/',$trunk[1]);
1860                         $trunkinfo[$name] = array(
1861                                 'name' => $name,
1862                                 'tech' => $tech,
1863                                 'globalvar' => $trunk[0], // ick
1864                                 'value' => $trunk[2], // ??  no idea what this is.
1865                         );     
1866                 }
1867                 return $trunkinfo;
1868         } else {
1869                 return $unique_trunks;
1870         }
1871 }
1872
1873 //write the OUTIDS global variable (used in dialparties.agi)
1874 function core_trunks_writeoutids() {
1875         // we have to escape _ for mysql: normally a wildcard
1876         $unique_trunks = sql("SELECT variable FROM globals WHERE variable LIKE 'OUT\\\_%'","getAll");
1877
1878         $outids = null; // Start off with nothing
1879         foreach ($unique_trunks as $unique_trunk) {
1880                 $outid = strtok($unique_trunk[0],"_");
1881                 $outid = strtok("_");
1882                 $outids .= $outid ."/";
1883         }
1884        
1885         sql("UPDATE globals SET value = '$outids' WHERE variable = 'DIALOUTIDS'");
1886 }
1887
1888 function core_trunks_addRegister($trunknum,$tech,$reg,$disable_flag=0) {
1889         sql("INSERT INTO $tech (id, keyword, data, flags) values ('9999999$trunknum','register','$reg','$disable_flag')");
1890 }
1891
1892
1893 function core_trunks_addDialRules($trunknum, $dialrules) {
1894         $values = array();
1895         $i = 1;
1896         foreach ($dialrules as $rule) {
1897                 $values["rule".$i++] = $rule;
1898         }
1899        
1900         $conf = core_trunks_readDialRulesFile();
1901        
1902         // rewrite for this trunk
1903         $conf["trunk-".$trunknum] = $values;
1904        
1905         core_trunks_writeDialRulesFile($conf);
1906 }
1907
1908 function core_trunks_readDialRulesFile() {
1909         global $amp_conf;
1910         $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1911        
1912         core_trunks_parse_conf($localPrefixFile, $conf, $section);
1913        
1914         return $conf;
1915 }
1916
1917 function core_trunks_writeDialRulesFile($conf) {
1918         global $amp_conf;
1919         $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1920        
1921         $fd = fopen($localPrefixFile,"w");
1922         foreach ($conf as $section=>$values) {
1923                 fwrite($fd, "[".$section."]\n");
1924                 foreach ($values as $key=>$value) {
1925                         fwrite($fd, $key."=".$value."\n");
1926                 }
1927                 fwrite($fd, "\n");
1928         }
1929         fclose($fd);
1930 }
1931
1932 function core_trunks_parse_conf($filename, &$conf, &$section) {
1933         if (is_null($conf)) {
1934                 $conf = array();
1935         }
1936         if (is_null($section)) {
1937                 $section = "general";
1938         }
1939        
1940         if (file_exists($filename)) {
1941                 $fd = fopen($filename, "r");
1942                 while ($line = fgets($fd, 1024)) {
1943                         if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
1944                                 // name = value
1945                                 // option line
1946                                 $conf[$section][ $matches[1] ] = $matches[2];
1947                         } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
1948                                 // section name
1949                                 $section = strtolower($matches[1]);
1950                         } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
1951                                 // include another file
1952                                
1953                                 if ($matches[1][0] == "/") {
1954                                         // absolute path
1955                                         $filename = $matches[1];
1956                                 } else {
1957                                         // relative path
1958                                         $filename =  dirname($filename)."/".$matches[1];
1959                                 }
1960                                
1961                                 core_trunks_parse_conf($filename, $conf, $section);
1962                         }
1963                 }
1964         }
1965 }
1966
1967 function core_trunks_getTrunkTrunkName($trunknum) {
1968         $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1969         if (!$results) {
1970                 return false;
1971         }
1972        
1973         if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1974                 $tname = substr($results[0][0],4);
1975         } else {
1976         strtok($results[0][0],'/');
1977                 $tname = strtok('/'); // the text _after_ technology.  ie: ZAP/g0 is g0
1978         }
1979         return $tname;
1980 }
1981
1982 //get and print peer details (prefixed with 4 9's)
1983 function core_trunks_getTrunkPeerDetails($trunknum) {
1984         global $db;
1985        
1986         $tech = core_trunks_getTrunkTech($trunknum);
1987        
1988         if ($tech == "zap") return ""; // zap has no details
1989        
1990         $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999$trunknum' ORDER BY id","getAll");
1991        
1992         foreach ($results as $result) {
1993                 if ($result[0] != 'account') {
1994                         if (isset($confdetail))
1995                                 $confdetail .= $result[0] .'='. $result[1] . "\n";
1996                         else
1997                                 $confdetail = $result[0] .'='. $result[1] . "\n";
1998                 }
1999         }
2000         return $confdetail;
2001 }
2002
2003 //get trunk user context (prefixed with 5 9's)
2004 function core_trunks_getTrunkUserContext($trunknum) {
2005         $tech = core_trunks_getTrunkTech($trunknum);
2006         if ($tech == "zap") return ""; // zap has no account
2007        
2008         $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
2009
2010         foreach ($results as $result) {
2011                 if ($result[0] == 'account') {
2012                         $account = $result[1];
2013                 }
2014         }
2015         return isset($account)?$account:null;
2016 }
2017
2018 //get and print user config (prefixed with 5 9's)
2019 function core_trunks_getTrunkUserConfig($trunknum) {
2020         global $db;
2021        
2022         $tech = core_trunks_getTrunkTech($trunknum);
2023        
2024         if ($tech == "zap") return ""; // zap has no details
2025        
2026         $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
2027
2028         foreach ($results as $result) {
2029                 if ($result[0] != 'account') {
2030                         if (isset($confdetail))
2031                                 $confdetail .= $result[0] .'='. $result[1] . "\n";
2032                         else
2033                                 $confdetail = $result[0] .'='. $result[1] . "\n";
2034                 }
2035         }
2036         return isset($confdetail)?$confdetail:null;
2037 }
2038
2039 //get trunk account register string
2040 function core_trunks_getTrunkRegister($trunknum) {
2041         $tech = core_trunks_getTrunkTech($trunknum);
2042        
2043         if ($tech == "zap") return ""; // zap has no register
2044        
2045         $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999999$trunknum'","getAll");
2046
2047         foreach ($results as $result) {
2048                         $register = $result[1];
2049         }
2050         return isset($register)?$register:null;
2051 }
2052
2053 function core_trunks_getDialRules($trunknum) {
2054         $conf = core_trunks_readDialRulesFile();
2055         if (isset($conf["trunk-".$trunknum])) {
2056                 return $conf["trunk-".$trunknum];
2057         }
2058         return false;
2059 }
2060
2061 //get outbound routes for a given trunk
2062 function core_trunks_gettrunkroutes($trunknum) {
2063         global $amp_conf;
2064
2065         if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2066                 $sql_code = "SELECT DISTINCT              context, priority FROM extensions WHERE context LIKE 'outrt-%' AND (args LIKE 'dialout-trunk,".$trunknum.",%' OR args LIKE 'dialout-enum,".$trunknum.",%') ORDER BY context";
2067         else
2068                 $sql_code = "SELECT DISTINCT SUBSTRING(context,7), priority FROM extensions WHERE context LIKE 'outrt-%' AND (args LIKE 'dialout-trunk,".$trunknum.",%' OR args LIKE 'dialout-enum,".$trunknum.",%') ORDER BY context";
2069
2070         $results = sql( $sql_code, "getAll" );
2071
2072         foreach ($results as $row) {
2073                 // original code was:
2074                 //      $routes[$row[0]] = $row[1];
2075                 // but substring is not supported in sqlite3.
2076                 // how about we remove the 2nd part of the "if"? and use the same code on all DB's?
2077
2078                 $t = ($amp_conf["AMPDBENGINE"] == "sqlite3") ? substr( $row[0], 7 ) : $row[0];
2079                 $r = $row[1];
2080                 $routes[ $r ] = $t;
2081
2082         }
2083         // array(routename=>priority)
2084         return isset($routes)?$routes:null;
2085 }
2086
2087 function core_trunks_deleteDialRules($trunknum) {
2088         $conf = core_trunks_readDialRulesFile();
2089        
2090         // remove rules for this trunk
2091         unset($conf["trunk-".$trunknum]);
2092        
2093         core_trunks_writeDialRulesFile($conf);
2094 }
2095
2096 /* end page.trunks.php functions */
2097
2098
2099 /* begin page.routing.php functions */
2100
2101 //get unique outbound route names
2102 function core_routing_getroutenames()
2103 {
2104         global $amp_conf;
2105        
2106         if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2107         {
2108                 // SUBSTRING is not supported under sqlite3, we need to filter
2109                 // this in php. I am not sure why "6" and not "7"
2110                 // but I don't really care -> it works :)
2111                 $results = sql("SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2112                 foreach( array_keys($results) as $idx )
2113                 {
2114                          $results[$idx][0] = substr( $results[$idx][0], 6);
2115                 }
2116         }
2117         else
2118         {
2119                 // we SUBSTRING() to remove "outrt-"
2120                 $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2121         }
2122
2123
2124         //TODO: This needs to be yanked, should be in the upgrade script somewhere not here
2125         //
2126         if (count($results) == 0) {
2127                 // see if they're still using the old dialprefix method
2128                 $results = sql("SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\\\_OUT\\\_%'","getAll");
2129                 // we SUBSTRING() to remove "outrt-"
2130                
2131                 if (count($results) > 0) {
2132                         // yes, they are using old method, let's update
2133                        
2134                         // get the default trunk
2135                         $results_def = sql("SELECT value FROM globals WHERE variable = 'OUT'","getAll");
2136                        
2137                         if (preg_match("/{OUT_(\d+)}/", $results_def[0][0], $matches)) {
2138                                 $def_trunk = $matches[1];
2139                         } else {
2140                                 $def_trunk = "";
2141                         }
2142                        
2143                         $default_patterns = array(      // default patterns that used to be in extensions.conf
2144                                                 "NXXXXXX",
2145                                                 "NXXNXXXXXX",
2146                                                 "1800NXXXXXX",
2147                                                 "1888NXXXXXX",
2148                                                 "1877NXXXXXX",
2149                                                 "1866NXXXXXX",
2150                                                 "1NXXNXXXXXX",
2151                                                 "011.",
2152                                                 "911",
2153                                                 "411",
2154                                                 "311",
2155                                                 );
2156                        
2157                         foreach ($results as $temp) {
2158                                 // temp[0] is "DIAL_OUT_1"
2159                                 // temp[1] is the dial prefix
2160                                
2161                                 $trunknum = substr($temp[0],9);
2162                                
2163                                 $name = "route".$trunknum;
2164                                
2165                                 $trunks = array(1=>"OUT_".$trunknum); // only one trunk to use
2166                                
2167                                 $patterns = array();
2168                                 foreach ($default_patterns as $pattern) {
2169                                         $patterns[] = $temp[1]."|".$pattern;
2170                                 }
2171                                
2172                                 if ($trunknum == $def_trunk) {
2173                                         // this is the default trunk, add the patterns with no prefix
2174                                         $patterns = array_merge($patterns, $default_patterns);
2175                                 }
2176                                
2177                                 // add this as a new route
2178                                 core_routing_add($name, $patterns, $trunks,"new");
2179                         }
2180                        
2181                        
2182                         // delete old values
2183                         sql("DELETE FROM globals WHERE (variable LIKE 'DIAL\\\_OUT\\\_%') OR (variable = 'OUT') ");
2184
2185                         // we need to re-generate extensions_additional.conf
2186                         // i'm not sure how to do this from here
2187                        
2188                         // re-run our query
2189                         $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2190                         // we SUBSTRING() to remove "outrt-"
2191                 }
2192                
2193         } // else, it just means they have no routes.
2194        
2195         return $results;
2196 }
2197
2198 function core_routing_setroutepriority($routepriority, $reporoutedirection, $reporoutekey)
2199 {
2200         global $db, $amp_conf;
2201         $counter=-1;
2202         foreach ($routepriority as $tresult)
2203         {
2204                 $counter++;
2205                 if (($counter==($reporoutekey-1)) && ($reporoutedirection=="up")) {
2206                         // swap this one with the one before (move up)
2207                         $temproute = $routepriority[$counter];
2208                         $routepriority[ $counter ] = $routepriority[ $counter+1 ];
2209                         $routepriority[ $counter+1 ] = $temproute;
2210                        
2211                 } else if (($counter==($reporoutekey)) && ($reporoutedirection=="down")) {
2212                         // swap this one with the one after (move down)
2213                         $temproute = $routepriority[ $counter+1 ];
2214                         $routepriority[ $counter+1 ] = $routepriority[ $counter ];
2215                         $routepriority[ $counter ] = $temproute;
2216                 }
2217         }
2218         unset($temptrunk);
2219         $routepriority = array_values($routepriority); // resequence our numbers
2220         $counter=0;
2221         foreach ($routepriority as $tresult) {
2222                 $order=core_routing_setroutepriorityvalue($counter++);
2223                 $sql = sprintf("Update extensions set context='outrt-%s-%s' WHERE context='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2224                 $result = $db->query($sql);
2225                 if(DB::IsError($result)) {     
2226                         die_freepbx($result->getMessage());
2227                 }
2228         }
2229        
2230         // Delete and readd the outbound-allroutes entries
2231         $sql = "delete from  extensions WHERE context='outbound-allroutes'";
2232         $result = $db->query($sql);
2233         if(DB::IsError($result)) {
2234                 die_freepbx($result->getMessage().$sql);
2235         }
2236        
2237         $sql = "SELECT DISTINCT context FROM extensions WHERE context like 'outrt-%' ORDER BY context";
2238         $results = $db->getAll($sql);
2239         if(DB::IsError($results)) {
2240                 die_freepbx($results->getMessage());
2241         }
2242
2243         $priority_loops=1;     
2244         foreach ($results as $row) {
2245                 $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2246                 $sql .= "('outbound-allroutes', ";
2247                 $sql .= "'include', ";
2248                 $sql .= "'".$priority_loops++."', ";
2249                 $sql .= "'".$row[0]."', ";
2250                 $sql .= "'', ";
2251                 $sql .= "'', ";
2252                 $sql .= "'2')";
2253        
2254                 //$sql = sprintf("Update extensions set application='outrt-%s-%s' WHERE context='outbound-allroutes' and  application='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2255                 $result = $db->query($sql);
2256                 if(DB::IsError($result)) {     
2257                         die_freepbx($result->getMessage(). $sql);
2258                 }
2259         }
2260        
2261         if ( $amp_conf["AMPDBENGINE"] == "sqlite3")
2262                 $sql = "SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2263         else
2264                 $sql = "SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2265
2266         // we SUBSTRING() to remove "outrt-"
2267         $routepriority = $db->getAll($sql);
2268         if(DB::IsError($routepriority)) {
2269                 die_freepbx($routepriority->getMessage());
2270         }
2271
2272         // TODO: strip the context on the sqlite3 backend
2273         // not sure where does it effects, since this is working on my setup...
2274         // welcome to funky town
2275         return ($routepriority);
2276 }
2277
2278 function core_routing_setroutepriorityvalue($key)
2279 {
2280         $key=$key+1;
2281         if ($key<10)
2282                 $prefix = sprintf("00%d",$key);
2283         else if ((9<$key)&&($key<100))
2284                 $prefix = sprintf("0%d",$key);
2285         else if ($key>100)
2286                 $prefix = sprintf("%d",$key);
2287         return ($prefix);
2288 }
2289
2290
2291 function core_routing_add($name, $patterns, $trunks, $method, $pass, $emergency = "", $intracompany = "", $mohsilence = "") {
2292
2293         global $db;
2294
2295         $trunktech=array();
2296
2297         //Retrieve each trunk tech for later lookup
2298         $sql="select * from globals WHERE variable LIKE 'OUT\\_%'";
2299         $result = $db->getAll($sql);
2300         if(DB::IsError($result)) {
2301                 die_freepbx($result->getMessage());
2302         }
2303         foreach($result as $tr) {
2304                 $tech = strtok($tr[1], "/");
2305                 $trunktech[$tr[0]]=$tech;
2306         }
2307        
2308         if ($method=="new") {   
2309                 $sql="select DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context";
2310                 $routepriority = $db->getAll($sql);
2311                 if(DB::IsError($result)) {
2312                         die_freepbx($result->getMessage());
2313                 }
2314                 $order=core_routing_setroutepriorityvalue(count($routepriority));
2315                 $name = sprintf ("%s-%s",$order,$name);
2316         }
2317         $trunks = array_values($trunks); // probably already done, but it's important for our dialplan
2318
2319        
2320         foreach ($patterns as $pattern) {
2321                 if (false !== ($pos = strpos($pattern,"|"))) {
2322                         // we have a | meaning to not pass the digits on
2323                         // (ie, 9|NXXXXXX should use the pattern _9NXXXXXX but only pass NXXXXXX, not the leading 9)
2324                        
2325                         $pattern = str_replace("|","",$pattern); // remove all |'s
2326                         $exten = "EXTEN:".$pos; // chop off leading digit
2327                 } else {
2328                         // we pass the full dialed number as-is
2329                         $exten = "EXTEN";
2330                 }
2331                
2332                 if (!preg_match("/^[0-9*]+$/",$pattern)) {
2333                         // note # is not here, as asterisk doesn't recoginize it as a normal digit, thus it requires _ pattern matching
2334                        
2335                         // it's not strictly digits, so it must have patterns, so prepend a _
2336                         $pattern = "_".$pattern;
2337                 }
2338                
2339                 // 1st priority is emergency dialing variable (if set)
2340                 if(!empty($emergency)) {
2341                         $startpriority = 1;
2342                         $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2343                         $sql .= "('outrt-".$name."', ";
2344                         $sql .= "'".$pattern."', ";
2345                         $sql .= "'".$startpriority."', ";
2346                         $sql .= "'SetVar', ";
2347                         $sql .= "'EMERGENCYROUTE=YES', ";
2348                         $sql .= "'Use Emergency CID for device')";
2349                         $result = $db->query($sql);
2350                         if(DB::IsError($result)) {
2351                                 die_freepbx($result->getMessage());
2352                         }
2353                 } else {
2354                         $startpriority = 0;
2355                 }
2356
2357                 // Next Priority (either first or second depending on above)
2358                 if(!empty($intracompany)) {
2359                            $startpriority += 1;
2360                            $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2361                            $sql .= "('outrt-".$name."', ";
2362                            $sql .= "'".$pattern."', ";
2363                            $sql .= "'".$startpriority."', ";
2364                            $sql .= "'SetVar', ";
2365                            $sql .= "'INTRACOMPANYROUTE=YES', ";
2366                            $sql .= "'Preserve Intenal CID Info')";
2367                            $result = $db->query($sql);
2368                                 if(DB::IsError($result)) {
2369                                            die_freepbx($result->getMessage());
2370                                 }
2371                 }
2372
2373                 // Next Priority (either first, second or third depending on above)
2374                 if(!empty($mohsilence) && trim($mohsilence) != 'default') {
2375                            $startpriority += 1;
2376                            $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2377                            $sql .= "('outrt-".$name."', ";
2378                            $sql .= "'".$pattern."', ";
2379                            $sql .= "'".$startpriority."', ";
2380                            $sql .= "'SetVar', ";
2381                            $sql .= "'MOHCLASS=".$mohsilence."', ";
2382                            $sql .= "'Do not play moh on this route')";
2383                            $result = $db->query($sql);
2384                                 if(DB::IsError($result)) {
2385                                            die_freepbx($result->getMessage());
2386                                 }
2387                 }
2388
2389                 $first_trunk = 1;
2390                 foreach ($trunks as $priority => $trunk) {
2391                         $priority += $startpriority;
2392                         $priority += 1; // since arrays are 0-based, but we want priorities to start at 1
2393                        
2394                         $sql = "INSERT INTO extensions (context, extension, priority, application, args) VALUES ";
2395                         $sql .= "('outrt-".$name."', ";
2396                         $sql .= "'".$pattern."', ";
2397                         $sql .= "'".$priority."', ";
2398                         $sql .= "'Macro', ";
2399                         if ($first_trunk)
2400                                 $pass_str = $pass;
2401                         else
2402                                 $pass_str = "";
2403
2404                         if ($trunktech[$trunk] == "ENUM")
2405                                 $sql .= "'dialout-enum,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2406                         else
2407                                 $sql .= "'dialout-trunk,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2408                         $sql .= ")";
2409                        
2410                         $result = $db->query($sql);
2411                         if(DB::IsError($result)) {
2412                                 die_freepbx($result->getMessage());
2413                         }
2414                         //To identify the first trunk in a pattern
2415                         //so that passwords are in the first trunk in
2416                         //each pattern
2417                         $first_trunk = 0;
2418                 }
2419                
2420                 $priority += 1;
2421                 $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2422                 $sql .= "('outrt-".$name."', ";
2423                 $sql .= "'".$pattern."', ";
2424                 $sql .= "'".$priority."', ";
2425                 $sql .= "'Macro', ";
2426                 $sql .= "'outisbusy', ";
2427                 $sql .= "'No available circuits')";
2428                
2429                 $result = $db->query($sql);
2430                 if(DB::IsError($result)) {
2431                         die_freepbx($result->getMessage());
2432                 }
2433         }
2434
2435        
2436         // add an include=>outrt-$name  to [outbound-allroutes]:
2437        
2438         // we have to find the first available priority.. priority doesn't really matter for the include, but
2439         // there is a unique index on (context,extension,priority) so if we don't do this we can't put more than
2440         // one route in the outbound-allroutes context.
2441         $sql = "SELECT priority FROM extensions WHERE context = 'outbound-allroutes' AND extension = 'include'";
2442         $results = $db->getAll($sql);
2443         if(DB::IsError($results)) {
2444                 die_freepbx($results->getMessage());
2445         }
2446         $priorities = array();
2447         foreach ($results as $row) {
2448                 $priorities[] = $row[0];
2449         }
2450         for ($priority = 1; in_array($priority, $priorities); $priority++);
2451        
2452         // $priority should now be the lowest available number
2453        
2454         $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2455         $sql .= "('outbound-allroutes', ";
2456         $sql .= "'include', ";
2457         $sql .= "'".$priority."', ";
2458         $sql .= "'outrt-".$name."', ";
2459         $sql .= "'', ";
2460         $sql .= "'', ";
2461         $sql .= "'2')";
2462        
2463         $result = $db->query($sql);
2464         if(DB::IsError($result)) {
2465                 die_freepbx($priority.$result->getMessage());
2466         }
2467        
2468 }
2469
2470 function core_routing_edit($name, $patterns, $trunks, $pass, $emergency="", $intracompany = "", $mohsilence="") {
2471         core_routing_del($name);
2472         core_routing_add($name, $patterns, $trunks,"edit", $pass, $emergency, $intracompany, $mohsilence);
2473 }
2474
2475 function core_routing_del($name) {
2476         global $db;
2477         $sql = "DELETE FROM extensions WHERE context = 'outrt-".$name."'";
2478         $result = $db->query($sql);
2479         if(DB::IsError($result)) {
2480                 die_freepbx($result->getMessage());
2481         }
2482        
2483         $sql = "DELETE FROM extensions WHERE context = 'outbound-allroutes' AND application = 'outrt-".$name."' ";
2484         $result = $db->query($sql);
2485         if(DB::IsError($result)) {
2486                 die_freepbx($result->getMessage());
2487         }
2488        
2489         return $result;
2490 }
2491
2492 /* Delete all occurences of the specified trunk from all routes that may use it
2493  */
2494 function core_routing_trunk_del($trunknum) {
2495         global $db;
2496
2497   $sql = "DELETE FROM `extensions` WHERE `application` = 'Macro' AND `context` LIKE 'outrt-%' AND `args` LIKE 'dialout-%,$trunknum,%'";
2498         $result = $db->query($sql);
2499 }
2500
2501 function core_routing_rename($oldname, $newname) {
2502         global $db;
2503
2504         $route_prefix=substr($oldname,0,4);
2505         $newname=$route_prefix.$newname;
2506         $sql = "SELECT context FROM extensions WHERE context = 'outrt-".$newname."'";
2507         $results = $db->getAll($sql);
2508         if (count($results) > 0) {
2509                 // there's already a route with this name
2510                 return false;
2511         }
2512        
2513         $sql = "UPDATE extensions SET context = 'outrt-".$newname."' WHERE context = 'outrt-".$oldname."'";
2514         $result = $db->query($sql);
2515         if(DB::IsError($result)) {
2516                 die_freepbx($result->getMessage());
2517         }
2518         $mypriority=sprintf("%d",$route_prefix);       
2519         $sql = "UPDATE extensions SET application = 'outrt-".$newname."', priority = '$mypriority' WHERE context = 'outbound-allroutes' AND application = 'outrt-".$oldname."' ";
2520         $result = $db->query($sql);
2521         if(DB::IsError($result)) {
2522                 die_freepbx($result->getMessage());
2523         }
2524        
2525         return true;
2526 }
2527
2528 //get unique outbound route patterns for a given context
2529 function core_routing_getroutepatterns($route) {
2530         global $db;
2531         $sql = "SELECT extension, args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk%' OR args LIKE'dialout-enum%') ORDER BY extension ";
2532         $results = $db->getAll($sql);
2533         if(DB::IsError($results)) {
2534                 die_freepbx($results->getMessage());
2535         }
2536        
2537         $patterns = array();
2538         foreach ($results as $row) {
2539                 if ($row[0][0] == "_") {
2540                         // remove leading _
2541                         $pattern = substr($row[0],1);
2542                 } else {
2543                         $pattern = $row[0];
2544                 }
2545                
2546                 if (preg_match("/{EXTEN:(\d+)}/", $row[1], $matches)) {
2547                         // this has a digit offset, we need to insert a |
2548                         $pattern = substr($pattern,0,$matches[1])."|".substr($pattern,$matches[1]);
2549                 }
2550                
2551                 $patterns[] = $pattern;
2552         }
2553         return array_unique($patterns);
2554 }
2555
2556 //get unique outbound route trunks for a given context
2557 function core_routing_getroutetrunks($route) {
2558         global $db;
2559         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%') ORDER BY CAST(priority as UNSIGNED) ";
2560         $results = $db->getAll($sql);
2561         if(DB::IsError($results)) {
2562                 die_freepbx($results->getMessage());
2563         }
2564        
2565         $trunks = array();
2566         foreach ($results as $row) {
2567                 if (preg_match('/^dialout-trunk,(\d+)/', $row[0], $matches)) {
2568                         // check in_array -- even though we did distinct
2569                         // we still might get ${EXTEN} and ${EXTEN:1} if they used | to split a pattern
2570                         if (!in_array("OUT_".$matches[1], $trunks)) {
2571                                 $trunks[] = "OUT_".$matches[1];
2572                         }
2573                 } else if (preg_match('/^dialout-enum,(\d+)/', $row[0], $matches)) {
2574                         if (!in_array("OUT_".$matches[1], $trunks)) {
2575                                 $trunks[] = "OUT_".$matches[1];
2576                         }
2577                 }
2578         }
2579         return $trunks;
2580 }
2581
2582
2583 //get password for this route
2584 function core_routing_getroutepassword($route) {
2585         global $db;
2586         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%') ORDER BY CAST(priority as UNSIGNED) ";
2587         $results = $db->getOne($sql);
2588         if(DB::IsError($results)) {
2589                 die_freepbx($results->getMessage());
2590         }
2591         if (preg_match('/^.*,.*,.*,(\d+|\/\S+)/', $results, $matches)) {
2592                 $password = $matches[1];
2593         } else {
2594                 $password = "";
2595         }
2596        
2597         return $password;
2598 }
2599
2600 //get emergency state for this route
2601 function core_routing_getrouteemergency($route) {
2602         global $db;
2603         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'EMERGENCYROUTE%') ";
2604         $results = $db->getOne($sql);
2605         if(DB::IsError($results)) {
2606                 die_freepbx($results->getMessage());
2607         }
2608         if (preg_match('/^.*=(.*)/', $results, $matches)) {
2609                 $emergency = $matches[1];
2610         } else {
2611                 $emergency = "";
2612         }
2613        
2614         return $emergency;
2615 }
2616
2617 //get intracompany routing status for this route
2618 function core_routing_getrouteintracompany($route) {
2619
2620        global $db;
2621        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'INTRACOMPANYROUTE%') ";
2622        $results = $db->getOne($sql);
2623        if(DB::IsError($results)) {
2624                die_freepbx($results->getMessage());
2625        }
2626        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2627                $intracompany = $matches[1];
2628        } else {
2629                $intracompany = "";
2630        }
2631        return $intracompany;
2632 }
2633
2634 //get mohsilence routing status for this route
2635 function core_routing_getroutemohsilence($route) {
2636
2637        global $db;
2638        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'MOHCLASS%') ";
2639        $results = $db->getOne($sql);
2640        if(DB::IsError($results)) {
2641                die_freepbx($results->getMessage());
2642        }
2643        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2644                $mohsilence = $matches[1];
2645        } else {
2646                $mohsilence = "";
2647        }
2648        return $mohsilence;
2649 }
2650
2651 function general_get_zonelist() {
2652         return array(
2653  array ( "name" => "Austria",  "iso" => "at", "conf" => "ringcadence = 1000,5000\ndial = 420\nbusy = 420/400,0/400\nring = 420/1000,0/5000\ncongestion = 420/200,0/200\ncallwaiting = 420/40,0/1960\ndialrecall = 420\nrecord = 1400/80,0/14920\ninfo = 950/330,1450/330,1850/330,0/1000\nstutter = 380+420\n"),
2654  array ( "name" => "Australia",  "iso" => "au", "conf" => "ringcadence = 400,200,400,2000\ndial = 413+438\nbusy = 425/375,0/375\nring = 413+438/400,0/200,413+438/400,0/2000\ncongestion = 425/375,0/375,420/375,0/375\ncallwaiting = 425/200,0/200,425/200,0/4400\ndialrecall = 413+438\nrecord = !425/1000,!0/15000,425/360,0/15000\ninfo = 425/2500,0/500\nstd = !525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100\nfacility = 425\nstutter = 413+438/100,0/40\nringmobile = 400+450/400,0/200,400+450/400,0/2000\n"),
2655  array ( "name" => "Brazil",  "iso" => "br", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250,425/750,0/250\ncallwaiting = 425/50,0/1000\ndialrecall = 350+440\nrecord = 425/250,0/250\ninfo = 950/330,1400/330,1800/330\nstutter = 350+440\n"),
2656  array ( "name" => "Belgium",  "iso" => "be", "conf" => "ringcadence = 1000,3000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/3000\ncongestion = 425/167,0/167\ncallwaiting = 1400/175,0/175,1400/175,0/3500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 900/330,1400/330,1800/330,0/1000\nstutter = 425/1000,0/250\n"),
2657  array ( "name" => "Switzerland",  "iso" => "ch", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/200,425/200,0/4000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+340/1100,0/1100\n"),
2658  array ( "name" => "Chile",  "iso" => "cl", "conf" => "ringcadence = 1000,3000\ndial = 400\nbusy = 400/500,0/500\nring = 400/1000,0/3000\ncongestion = 400/200,0/200\ncallwaiting = 400/250,0/8750\ndialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/500,0/15000\ninfo = 950/333,1400/333,1800/333,0/1000\nstutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\n"),
2659  array ( "name" => "China",  "iso" => "cn", "conf" => "ringcadence = 1000,4000\ndial = 450\nbusy = 450/350,0/350\nring = 450/1000,0/4000\ncongestion = 450/700,0/700\ncallwaiting = 450/400,0/4000\ndialrecall = 450\nrecord = 950/400,0/10000\ninfo = 450/100,0/100,450/100,0/100,450/100,0/100,450/400,0/400\nstutter = 450+425\n"),
2660  array ( "name" => "Czech Republic",  "iso" => "cz", "conf" => "ringcadence = 1000,4000\ndial = 425/330,0/330,425/660,0/660\nbusy = 425/330,0/330\nring = 425/1000,0/4000\ncongestion = 425/165,0/165\ncallwaiting = 425/330,0/9000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425/330,0/330,425/660,0/660\nrecord = 1400/500,0/14000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = 425/450,0/50\n"),
2661  array ( "name" => "Germany",  "iso" => "de", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/480,0/480\nring = 425/1000,0/4000\ncongestion = 425/240,0/240\ncallwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+400\n"),
2662  array ( "name" => "Denmark",  "iso" => "dk", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = !425/200,!0/600,!425/200,!0/3000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/450,0/50\n"),
2663  array ( "name" => "Estonia",  "iso" => "ee", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 950/650,0/325,950/325,0/30,1400/1300,0/2600\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2664  array ( "name" => "Spain",  "iso" => "es", "conf" => "ringcadence = 1500,3000\ndial = 425\nbusy = 425/200,0/200\nring = 425/1500,0/3000\ncongestion = 425/200,0/200,425/200,0/200,425/200,0/600\ncallwaiting = 425/175,0/175,425/175,0/3500\ndialrecall = !425/200,!0/200,!425/200,!0/200,!425/200,!0/200,425\nrecord = 1400/500,0/15000\ninfo = 950/330,0/1000\ndialout = 500\n\n"),
2665  array ( "name" => "Finland",  "iso" => "fi", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = 425/650,0/25\n"),
2666  array ( "name" => "France",  "iso" => "fr", "conf" => "ringcadence = 1500,3500\ndial = 440\nbusy = 440/500,0/500\nring = 440/1500,0/3500\ncongestion = 440/250,0/250\ncallwait = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330\nstutter = !440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,440\n"),
2667  array ( "name" => "Greece",  "iso" => "gr", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/300,425/700,0/800\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 425/650,0/25\n"),
2668  array ( "name" => "Hungary",  "iso" => "hu", "conf" => "ringcadence = 1250,3750\ndial = 425\nbusy = 425/300,0/300\nring = 425/1250,0/3750\ncongestion = 425/300,0/300\ncallwaiting = 425/40,0/1960\ndialrecall = 425+450\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 350+375+400\n"),
2669  array ( "name" => "India",  "iso" => "in", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*25\nbusy = 400/750,0/750\nring = 400*25/400,0/200,400*25/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400/200,0/100,400/200,0/7500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2670  array ( "name" => "Israel",  "iso" => "il", "conf" => "ringcadence = 1000,3000\ndial = 414\nbusy = 414/500,0/500\nring = 414/1000,0/3000\ncongestion = 414/250,0/250\ncallwaiting = 414/100,0/100,414/100,0/100,414/600,0/3000 \ndialrecall = !414/100,!0/100,!414/100,!0/100,!414/100,!0/100,414\nrecord = 1400/500,0/15000\ninfo = 1000/330,1400/330,1800/330,0/1000\nstutter = !414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,414 \n"),
2671  array ( "name" => "Italy",  "iso" => "it", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/200,425/600,0/1000\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/400,0/100,425/250,0/100,425/150,0/14000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"),
2672  array ( "name" => "Lithuania",  "iso" => "lt", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/350,0/350\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2673  array ( "name" => "Mexico",  "iso" => "mx", "conf" => "ringcadence = 2000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2674  array ( "name" => "Netherlands",  "iso" => "nl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/500,0/9500\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/500,0/50\n"),
2675  array ( "name" => "Norway",  "iso" => "no", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"),
2676  array ( "name" => "New Zealand",  "iso" => "nz", "conf" => "ringcadence = 400,200,400,2000\ndial = 400\nbusy = 400/250,0/250\nring = 400+450/400,0/200,400+450/400,0/2000\ncongestion = 400/375,0/375\ncallwaiting = !400/200,!0/3000,!400/200,!0/3000,!400/200,!0/3000,!400/200\ndialrecall = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/425,0/15000\ninfo = 400/750,0/100,400/750,0/100,400/750,0/100,400/750,0/400\nstutter = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,!400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\n"),
2677  array ( "name" => "Poland",  "iso" => "pl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/500,0/500\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2678  array ( "name" => "Portugal",  "iso" => "pt", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/5000\ncongestion = 425/200,0/200\ncallwaiting = 440/300,0/10000\ndialrecall = 425/1000,0/200\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2679  array ( "name" => "Russia / ex Soviet Union",  "iso" => "ru", "conf" => "ringcadence = 800,3200\ndial = 425\nbusy = 425/350,0/350\nring = 425/800,0/3200\ncongestion = 425/350,0/350\ncallwaiting = 425/200,0/5000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\n"),
2680  array ( "name" => "Singapore",  "iso" => "sg", "conf" => "ringcadence = 400,200,400,2000\ndial = 425\nring = 425*24/400,0/200,425*24/400,0/2000 ; modulation should be 100%, not 90%\nbusy = 425/750,0/750\ncongestion = 425/250,0/250\ncallwaiting = 425*24/300,0/200,425*24/300,0/3200\nstutter = !425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,425\ninfo = 950/330,1400/330,1800/330,0/1000 ; not currently in use acc. to reference\ndialrecall = 425*24/500,0/500,425/500,0/2500 ; unspecified in IDA reference, use repeating Holding Tone A,B\nrecord = 1400/500,0/15000 ; unspecified in IDA reference, use 0.5s tone every 15s\nnutone = 425/2500,0/500\nintrusion = 425/250,0/2000\nwarning = 425/624,0/4376 ; end of period tone, warning\nacceptance = 425/125,0/125\nholdinga = !425*24/500,!0/500 ; followed by holdingb\nholdingb = !425/500,!0/2500\n"),
2681  array ( "name" => "South Africa",  "iso" => "za", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*33\nbusy = 400/500,0/500\nring = 400*33/400,0/200,400*33/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400*33/250,0/250,400*33/250,0/250,400*33/250,0/250,400*33/250,0/250\ndialrecall = 350+440\nrecord = 1400/500,0/10000\ninfo = 950/330,1400/330,1800/330,0/330\nstutter =!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,400*33 \n"),
2682  array ( "name" => "Sweden",  "iso" => "se", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/5000\ncongestion = 425/250,0/750\ncallwaiting = 425/200,0/500,425/200,0/9100\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/500,0/15000\ninfo = !950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2683  array ( "name" => "United Kingdom",  "iso" => "uk", "conf" => "ringcadence = 400,200,400,2000\ndial = 350+440\nspecialdial = 350+440/750,440/750\nbusy = 400/375,0/375\ncongestion = 400/400,0/350,400/225,0/525\nspecialcongestion = 400/200,1004/300\nunobtainable = 400\nring = 400+450/400,0/200,400+450/400,0/2000\ncallwaiting = 400/100,0/4000\nspecialcallwaiting = 400/250,0/250,400/250,0/250,400/250,0/5000\ncreditexpired = 400/125,0/125\nconfirm = 1400\nswitching = 400/200,0/400,400/2000,0/400\ninfo = 950/330,0/15,1400/330,0/15,1800/330,0/1000\nrecord = 1400/500,0/60000\nstutter = 350+440/750,440/750\n"),
2684  array ( "name" => "United States / North America",  "iso" => "us", "conf" => "ringcadence = 2000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/2000,0/4000\ncongestion = 480+620/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2685  array ( "name" => "United States Circa 1950/ North America",  "iso" => "us-old", "conf" => "ringcadence = 2000,4000\ndial = 600*120\nbusy = 500*100/500,0/500\nring = 420*40/2000,0/4000\ncongestion = 500*100/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\n"),
2686  array ( "name" => "Taiwan",  "iso" => "tw", "conf" => "ringcadence = 1000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/1000,0/2000\ncongestion = 480+620/250,0/250\ncallwaiting = 350+440/250,0/250,350+440/250,0/3250\ndialrecall = 300/1500,0/500\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2687  array ( "name" => "Venezuela / South America",  "iso" => "ve", "conf" => "; Tone definition source for ve found on\n; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf\nringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 400+450/300,0/6000\ndialrecall = 425\nrecord =  1400/500,0/15000\ninfo = !950/330,!1440/330,!1800/330,0/1000\n"),);
2688 }
2689
2690 function general_display_zones($curzone) {
2691         $zonelist = general_get_zonelist();
2692         echo "<select name='TONEZONE'>\n";
2693         foreach ($zonelist as $zone) {
2694                 if ($zone['iso'] == $curzone)
2695                         echo "<option selected value='{$zone['iso']}'>{$zone['name']}</option>\n";
2696                 else   
2697                         echo "<option value='{$zone['iso']}'>{$zone['name']}</option>\n";
2698         }
2699         echo "</select>";
2700        
2701 }
2702
2703 function general_generate_indications() {
2704         global $db;
2705         global $asterisk_conf;
2706
2707         $sql = "SELECT value FROM globals WHERE variable='TONEZONE'";
2708         $result = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2709
2710         $filename = isset($asterisk_conf["astetcdir"]) && $asterisk_conf["astetcdir"] != '' ? rtrim($asterisk_conf["astetcdir"],DIRECTORY_SEPARATOR) : "/etc/asterisk";
2711         $filename .= "/indications.conf";
2712         $fd = fopen($filename, "w");
2713         fwrite($fd, "[general]\ncountry=".$result['value']."\n\n");
2714
2715         $zonelist = general_get_zonelist();
2716         foreach ($zonelist as $zone) {
2717                 fwrite($fd, "[{$zone['iso']}]\n{$zone['conf']}\n\n");
2718         }
2719         fclose($fd);
2720 }
2721 /* end page.routing.php functions */
2722
2723
2724
2725 // init registered 'your' config load and config process functions
2726 function core_users_configpageinit($dispnum) {
2727         global $currentcomponent;
2728         global $amp_conf;
2729
2730         if ( $dispnum == 'users' || $dispnum == 'extensions' ) {
2731                 // Setup option list we need
2732                 $currentcomponent->addoptlistitem('recordoptions', 'Adhoc', _("On Demand"));
2733                 $currentcomponent->addoptlistitem('recordoptions', 'Always', _("Always"));
2734                 $currentcomponent->addoptlistitem('recordoptions', 'Never', _("Never"));
2735                 $currentcomponent->setoptlistopts('recordoptions', 'sort', false);
2736
2737                 $currentcomponent->addoptlistitem('faxdetecttype', '0', _("None"));
2738                 $currentcomponent->addoptlistitem('faxdetecttype', '1', 'Zaptel');
2739                 $currentcomponent->addoptlistitem('faxdetecttype', '2', 'NVFax');
2740                 $currentcomponent->setoptlistopts('faxdetecttype', 'sort', false);
2741
2742                 $currentcomponent->addoptlistitem('privyn', '0', _("No"));
2743                 $currentcomponent->addoptlistitem('privyn', '1', _("Yes"));
2744                 $currentcomponent->setoptlistopts('privyn', 'sort', false);
2745
2746                 $currentcomponent->addoptlistitem('callwaiting', 'enabled', _("Enable"));
2747                 $currentcomponent->addoptlistitem('callwaiting', 'disabled', _("Disable"));
2748                 $currentcomponent->setoptlistopts('callwaiting', 'sort', false);
2749
2750                 $currentcomponent->addoptlistitem('ringtime', '0', 'Default');
2751                 for ($i=1; $i <= 120; $i++) {
2752                         $currentcomponent->addoptlistitem('ringtime', "$i", "$i");
2753                 }
2754                 $currentcomponent->setoptlistopts('ringtime', 'sort', false);
2755
2756                 $currentcomponent->addoptlistitem('faxdestoptions', 'default', _("FreePBX default"));
2757                 $currentcomponent->addoptlistitem('faxdestoptions', 'disabled', _("disabled"));
2758                 $currentcomponent->addoptlistitem('faxdestoptions', 'system', _("system"));
2759                 $currentcomponent->setoptlistopts('faxdestoptions', 'sort', false);
2760
2761                 if (function_exists('music_list')) {
2762                                 $tresults = music_list($amp_conf['ASTVARLIBDIR']."/mohmp3");
2763                     if (isset($tresults[0])) {
2764                         foreach ($tresults as $tresult) {
2765                             $currentcomponent->addoptlistitem('mohclass', $tresult, $tresult);
2766                         }
2767                     $currentcomponent->setoptlistopts('mohclass', 'sort', false);
2768                     }
2769                 }
2770
2771                 //get unique devices to finishoff faxdestoptions list
2772                 $devices = core_devices_list();
2773                 if (isset($devices)) {
2774                         foreach ($devices as $device) {
2775                                 $currentcomponent->addoptlistitem('faxdestoptions', $device[0], "$device[1] <$device[0]>");
2776                         }
2777                 }
2778
2779                 // Add the 'proces' functions
2780                 $currentcomponent->addguifunc('core_users_configpageload');
2781                 // Ensure users is called in middle order ($sortorder = 5), this is to allow
2782                 // other modules to call stuff before / after the processing of users if needed
2783                 // e.g. Voicemail module needs to create mailbox BEFORE the users as the mailbox
2784                 // context is needed by the add users function
2785                 $currentcomponent->addprocessfunc('core_users_configprocess', 5);                       
2786         }
2787 }
2788
2789 function core_users_configpageload() {
2790         global $currentcomponent;
2791         global $amp_conf;
2792
2793         // Ensure variables possibly extracted later exist
2794         $name = $directdid = $didalert = $outboundcid = $answer = null;
2795         $record_in = $record_out = $faxexten = $faxemail = $mohclass = $sipname = $cid_masquerade = null;
2796
2797         // Init vars from $_REQUEST[]
2798         $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
2799         $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
2800         $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
2801         $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
2802
2803         if ( $action == 'del' ) { // Deleted
2804
2805                 $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
2806
2807         } elseif ( $display == 'extensions' && ($extdisplay == '' && $tech_hardware == '') ) { // Adding
2808
2809                 // do nothing as you want the Devices to handle this bit
2810
2811         } else {
2812
2813                 $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
2814        
2815                 if ( is_string($extdisplay) ) {
2816                         $extenInfo=core_users_get($extdisplay);
2817                         extract($extenInfo);
2818                         if (isset($deviceInfo) && is_array($deviceInfo))
2819                                 extract($deviceInfo);
2820        
2821                         if ( $display == 'extensions' ) {
2822                                 $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Extension").": $extdisplay", false), 0);
2823                                 $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Extension")." $extdisplay", $delURL, true, false), 0);
2824                         } else {
2825                                 $currentcomponent->addguielem('_top', new gui_pageheading('title', _("User").": $extdisplay", false), 0);
2826                                 $currentcomponent->addguielem('_top', new gui_link('del', _("Delete User")." $extdisplay", $delURL, true, false), 0);
2827                         }
2828
2829                 } elseif ( $display != 'extensions' ) {
2830                         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add User/Extension")), 0);
2831                 }
2832                
2833                 // Setup vars for use in the gui later on                                                       
2834                 $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
2835                 $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
2836                
2837                 $msgInvalidExtNum = _("Please enter a valid extension number.");
2838                 $msgInvalidCidNum = _("Please enter a valid CID Num Alias (must be a valid number).");
2839                 $msgInvalidExtPwd = _("Please enter valid User Password using numbers only");
2840                 $msgInvalidDispName = _("Please enter a valid Display Name");
2841                 $msgInvalidOutboundCID = _("Please enter a valid Outbound CID");
2842                 $msgInvalidPause = _("Please enter a valid pause time in seconds, using digits only");
2843
2844                 // This is the actual gui stuff
2845                 $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
2846                 $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
2847                
2848                 if ( $display == 'extensions' ) {
2849                         $section = ($extdisplay ? _("Edit Extension") : _("Add Extension"));                   
2850                 } else {
2851                         $section = ($extdisplay ? _("Edit User") : _("Add User"));
2852                 }
2853                 if ( $extdisplay ) {
2854                         $currentcomponent->addguielem($section, new gui_hidden('extension', $extdisplay), 2);
2855                 } else {
2856                         $currentcomponent->addguielem($section, new gui_textbox('extension', $extdisplay, 'User Extension', 'The extension number to dial to reach this user.', '!isInteger()', $msgInvalidExtNum, false), 3);
2857                 }
2858                 if ( $display != 'extensions' ) {
2859                         $currentcomponent->addguielem($section, new gui_password('password', $password, 'User Password', _("A user will enter this password when logging onto a device.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), '!isInteger() && !isWhitespace()', $msgInvalidExtPwd, true));
2860                         // extra JS function check required for blank password warning -- call last in the onsubmit() function
2861                         $currentcomponent->addjsfunc('onsubmit()', "\treturn checkBlankUserPwd();\n", 9);
2862                 }
2863                 $currentcomponent->addguielem($section, new gui_textbox('name', $name, 'Display Name', 'The caller id name for calls from this user will be set to this name. Only enter the name, NOT the number.', '!isCallerID()', $msgInvalidDispName, false));
2864                 $cid_masquerade = (trim($cid_masquerade) == $extdisplay)?"":$cid_masquerade;
2865                 $currentcomponent->addguielem($section, new gui_textbox('cid_masquerade', $cid_masquerade, 'CID Num Alias', 'The CID Number to use for internal calls, if different from the extension number. This is used to masquerade as a different user. A common example is a team of support people who would like their internal callerid to display the general support number (a ringgroup or queue). There will be no effect on external calls.', '!isWhitespace() && !isInteger()', $msgInvalidCidNum, false));
2866                 $currentcomponent->addguielem($section, new gui_textbox('sipname', $sipname, 'SIP Alias', "If you want to support direct sip dialing of users internally or through anonymous sip calls, you can supply a friendly name that can be used in addition to the users extension to call them."));
2867                
2868                 $section = 'Extension Options';
2869                 $currentcomponent->addguielem($section, new gui_textbox('directdid', $directdid, 'Direct DID', "The direct DID that is associated with this extension. The DID should be in the same format as provided by the provider (e.g. full number, 4 digits for 10x4, etc).<br><br>Format should be: <b>XXXXXXXXXX</b><br><br>Leave this field blank to disable the direct DID feature for this extension. All non-numeric characters will be stripped."), 3);
2870                 $currentcomponent->addguielem($section, new gui_textbox('didalert', $didalert, 'DID Alert Info', "Alert Info can be used for distinctive ring on SIP phones. Set this value to the desired Alert Info to be sent to the phone when this DID is called. Leave blank to use default values. Will have no effect if no Direct DID is set"));
2871                 if (function_exists('music_list')) {
2872                     $currentcomponent->addguielem($section, new gui_selectbox('mohclass', $currentcomponent->getoptlist('mohclass'), $mohclass, 'Music on Hold', "Set the MoH class that will be used for calls that come in on this Direct DID. For example, choose a type appropriate for a originating country which may have announcements in their language. Only effects MoH class when the call came in from the Direct DID.", false));
2873                 }
2874                 $currentcomponent->addguielem($section, new gui_textbox('outboundcid', $outboundcid, 'Outbound CID', "Overrides the caller id when dialing out a trunk. Any setting here will override the common outbound caller id set in the Trunks admin.<br><br>Format: <b>\"caller name\" &lt;#######&gt;</b><br><br>Leave this field blank to disable the outbound callerid feature for this user.", '!isCallerID()', $msgInvalidOutboundCID, true));
2875                 $ringtimer = (isset($ringtimer) ? $ringtimer : '0');
2876                 $currentcomponent->addguielem($section, new gui_selectbox('ringtimer', $currentcomponent->getoptlist('ringtime'), $ringtimer, 'Ring Time', "Number of seconds to ring prior to going to voicemail. Default will use the value set in the General Tab. If no voicemail is configured this will be ignored.", false));
2877                 if (!isset($callwaiting)) {
2878                         if ($amp_conf['ENABLECW']) {
2879                                 $callwaiting = 'enabled';
2880                         } else {
2881                                 $callwaiting = 'disabled';
2882                         }
2883                 }
2884                 $currentcomponent->addguielem($section, new gui_selectbox('callwaiting', $currentcomponent->getoptlist('callwaiting'), $callwaiting, 'Call Waiting', "Set the initial/current Call Waiting state for this user's extension", false));
2885
2886                 $section = 'Recording Options';
2887                 $currentcomponent->addguielem($section, new gui_selectbox('record_in', $currentcomponent->getoptlist('recordoptions'), $record_in, 'Record Incoming', "Record all inbound calls received at this extension.", false));
2888                 $currentcomponent->addguielem($section, new gui_selectbox('record_out', $currentcomponent->getoptlist('recordoptions'), $record_out, 'Record Outgoing', "Record all outbound calls received at this extension.", false));
2889
2890                 $section = 'Fax Handling';
2891                 $wait = (isset($wait) ? $wait : '0');
2892                 $currentcomponent->addguielem($section, new gui_selectbox('faxexten', $currentcomponent->getoptlist('faxdestoptions'), $faxexten, 'Fax Extension', "Select 'system' to have the system receive and email faxes.<br><br>The FreePBX default is defined in General Settings.", false), 4);
2893                 $currentcomponent->addguielem($section, new gui_textbox('faxemail', $faxemail, 'Fax Email', "Email address is used if 'system' has been chosen for the fax extension above.<br><br>Leave this blank to use the FreePBX default in General Settings"));
2894                 $currentcomponent->addguielem($section, new gui_selectbox('answer', $currentcomponent->getoptlist('faxdetecttype'), $answer, 'Fax Detection Type', "Selecting Zaptel or NVFax will immediately answer the call and play ringing tones to the caller for the number of seconds in Pause below. Use NVFax on SIP or IAX trunks.", false));
2895                 $currentcomponent->addguielem($section, new gui_textbox('wait', $wait, 'Pause after answer', 'The number of seconds we should wait after performing an Immediate Answer. The primary purpose of this is to pause and listen for a fax tone before allowing the call to proceed.', '!isInteger()', $msgInvalidPause, false));
2896
2897                 $section = 'Privacy';
2898                 $privacyman = (isset($privacyman) ? $privacyman : '0');
2899                 $currentcomponent->addguielem($section, new gui_selectbox('privacyman', $currentcomponent->getoptlist('privyn'), $privacyman, 'Privacy Manager', "If no Caller ID is sent, Privacy Manager will asks the caller to enter their 10 digit phone number. The caller is given 3 attempts.", false), 4);
2900
2901         }
2902 }
2903
2904 function core_users_configprocess() {
2905         if ( !class_exists('agi_asteriskmanager') )
2906                 include 'common/php-asmanager.php';
2907        
2908         //create vars from the request
2909         extract($_REQUEST);
2910        
2911         //make sure we can connect to Asterisk Manager
2912         if (!checkAstMan()) {
2913                 return false;
2914         }
2915
2916         //check if the extension is within range for this user
2917         if (isset($extension) && !checkRange($extension)){
2918                 echo "<script>javascript:alert('". _("Warning! Extension")." ".$extension." "._("is not allowed for your account").".');</script>";
2919                 $GLOBALS['abort'] = true;
2920         } else {
2921                 //if submitting form, update database
2922                 if (!isset($action)) $action = null;
2923                 switch ($action) {
2924                         case "add":
2925                                 if (core_users_add($_REQUEST)) {
2926                                         needreload();
2927                                         redirect_standard_continue();
2928                                 } else {
2929                                         // really bad hack - but if core_users_add fails, want to stop core_devices_add
2930                                         $GLOBALS['abort'] = true;
2931                                 }
2932                         break;
2933                         case "del":
2934                                 core_users_del($extdisplay);
2935                                 core_users_cleanastdb($extdisplay);
2936                                 if (function_exists('findmefollow_del')) {
2937                                     findmefollow_del($extdisplay);
2938                                 }
2939                                 needreload();
2940                                 redirect_standard_continue();
2941                         break;
2942                         case "edit":
2943                                 if (core_users_edit($extdisplay,$_REQUEST)) {
2944                                         needreload();
2945                                         redirect_standard_continue('extdisplay');
2946                                 } else {
2947                                         // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
2948                                         $GLOBALS['abort'] = true;
2949                                 }
2950                         break;
2951                 }
2952         }
2953         return true;
2954 }
2955
2956
2957 function core_devices_configpageinit($dispnum) {
2958         global $currentcomponent;
2959
2960         if ( $dispnum == 'devices' || $dispnum == 'extensions' ) {
2961                 // Setup arrays for device types
2962                 $currentcomponent->addgeneralarray('devtechs');
2963                
2964                 // Some errors for the validation bits
2965                 $msgInvalidDTMFMODE = _("Please enter the dtmfmode for this device");
2966                 $msgInvalidChannel = _("Please enter the channel for this device");
2967                 $msgConfirmSecret = _("You have not entered a Secret for this device, although this is possible it is generally bad practice to not assign a Secret to a device. Are you sure you want to leave the Secret empty?");
2968                 $msgInvalidSecret = _("Please enter a Secret for this device");
2969                
2970                 // zap
2971                 $tmparr = array();
2972                 $tmparr['channel'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidChannel);
2973                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2974                 $tmparr['immediate'] = array('value' => 'no', 'level' => 1);
2975                 $tmparr['signalling'] = array('value' => 'fxo_ks', 'level' => 1);
2976                 $tmparr['echocancel'] = array('value' => 'yes', 'level' => 1);
2977                 $tmparr['echocancelwhenbridged'] = array('value' => 'no', 'level' => 1);
2978                 $tmparr['echotraining'] = array('value' => '800', 'level' => 1);
2979                 $tmparr['busydetect'] = array('value' => 'no', 'level' => 1);
2980                 $tmparr['busycount'] = array('value' => '7', 'level' => 1);
2981                 $tmparr['callprogress'] = array('value' => 'no', 'level' => 1);
2982                 $tmparr['dial'] = array('value' => '', 'level' => 1);
2983                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2984                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2985                 $currentcomponent->addgeneralarrayitem('devtechs', 'zap', $tmparr);
2986                 unset($tmparr);
2987                
2988                 // iax2
2989                 $tmparr = array();
2990                 $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
2991                 $tmparr['notransfer'] = array('value' => 'yes', 'level' => 1);
2992                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2993                 $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
2994                 $tmparr['type'] = array('value' => 'friend', 'level' => 1);
2995                 $tmparr['port'] = array('value' => '4569', 'level' => 1);
2996                 $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
2997                 $tmparr['disallow'] = array('value' => '', 'level' => 1);
2998                 $tmparr['allow'] = array('value' => '', 'level' => 1);
2999                 $tmparr['dial'] = array('value' => '', 'level' => 1);
3000                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3001                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3002                 $currentcomponent->addgeneralarrayitem('devtechs', 'iax2', $tmparr);
3003                 unset($tmparr);
3004
3005                 // sip
3006                 $tmparr = array();
3007                 $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
3008                 $tmparr['dtmfmode'] = array('value' => 'rfc2833', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidDTMFMODE );
3009                 $tmparr['canreinvite'] = array('value' => 'no', 'level' => 1);
3010                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
3011                 $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
3012                 $tmparr['type'] = array('value' => 'friend', 'level' => 1);
3013                 $tmparr['nat'] = array('value' => 'yes', 'level' => 1);
3014                 $tmparr['port'] = array('value' => '5060', 'level' => 1);
3015                 $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
3016                 $tmparr['callgroup'] = array('value' => '', 'level' => 1);
3017                 $tmparr['pickupgroup'] = array('value' => '', 'level' => 1);
3018                 $tmparr['disallow'] = array('value' => '', 'level' => 1);
3019                 $tmparr['allow'] = array('value' => '', 'level' => 1);
3020                 $tmparr['dial'] = array('value' => '', 'level' => 1);
3021                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3022                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3023                 $currentcomponent->addgeneralarrayitem('devtechs', 'sip', $tmparr);
3024                 unset($tmparr);
3025
3026                 // custom
3027                 $tmparr = array();
3028                 $tmparr['dial'] = array('value' => '', 'level' => 0);
3029                 $currentcomponent->addgeneralarrayitem('devtechs', 'custom', $tmparr);
3030                 unset($tmparr);
3031                
3032                 // Devices list
3033                 $currentcomponent->addoptlistitem('devicelist', 'sip_generic', _("Generic S