Ticket #2498: functions.inc.php.new.txt

File functions.inc.php.new.txt, 136.7 kB (added by flewid, 5 years ago)

Modified functions.inc.php for md5secret

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" ? "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){
739   global $amp_conf;
740   global $currentFile;
741   global $astman;
742
743   $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
744  
745   //ensure this id is not already in use
746   $devices = core_devices_list();
747   if (is_array($devices)) {
748     foreach($devices as $device) {
749       if ($device[0] === $id) {
750         if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
751         return false;
752       }
753     }
754   }
755   //unless defined, $dial is TECH/id
756   if ( $dial == '' ) {
757     //zap is an exception
758     if ( strtolower($tech) == "zap" ) {
759       $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
760       $dial = 'ZAP/'.$zapchan;
761     } else {
762       $dial = strtoupper($tech)."/".$id;
763     }
764   }
765   //if (empty($dial) && strtolower($tech) == "zap")
766   //  $dial = "ZAP/".($_REQUEST['channel'] != '' ? $_REQUEST['channel'] : $_REQUEST['devinfo_channel']);
767   //if (empty($dial))
768   //  $dial = strtoupper($tech)."/".$id;
769  
770   //check to see if we are requesting a new user
771   if ($user == "new") {
772     $user = $id;
773     $jump = true;
774   }
775  
776   if(!get_magic_quotes_gpc()) {
777     if(!empty($emergency_cid))
778       $emergency_cid = addslashes($emergency_cid);
779     if(!empty($description))
780       $description = addslashes($description);
781   }
782  
783   //insert into devices table
784   $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
785   sql($sql);
786  
787   //add details to astdb
788   if ($astman) {
789     $astman->database_put("DEVICE",$id."/dial",$dial);
790     $astman->database_put("DEVICE",$id."/type",$devicetype);
791     $astman->database_put("DEVICE",$id."/user",$user);
792     if(!empty($emergency_cid))
793       $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
794     if($user != "none") {
795       $existingdevices = $astman->database_get("AMPUSER",$user."/device");
796       if (empty($existingdevices)) {
797         $astman->database_put("AMPUSER",$user."/device",$id);
798       } else {
799         $existingdevices .= "&";
800         //only append device value if this id doesn't exist in it already
801         if(strpos($existingdevices,$id."&") === false) // if not containing $id
802           $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
803       }
804     }
805   } else {
806     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
807   }
808  
809   // create a voicemail symlink if needed
810   $thisUser = core_users_get($user);
811   if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
812     if(empty($thisUser['voicemail']))
813       $vmcontext = "default";
814     else
815       $vmcontext = $thisUser['voicemail'];
816    
817     //voicemail symlink
818     exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
819     exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
820   }
821    
822   //take care of sip/iax/zap config
823   $funct = "core_devices_add".strtolower($tech);
824   if(function_exists($funct)){
825     $funct($id);
826   }
827  
828 /*  if($user != "none") {
829     core_hint_add($user);
830   }*/
831  
832   //if we are requesting a new user, let's jump to users.php
833   if (isset($jump)) {
834     echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
835   }
836   return true;
837 }
838
839 function core_devices_del($account){
840   global $amp_conf;
841   global $currentFile;
842   global $astman;
843  
844   //get all info about device
845   $devinfo = core_devices_get($account);
846  
847   //delete details to astdb
848   if ($astman) {
849     // If a user was selected, remove this device from the user
850     $deviceuser = $astman->database_get("DEVICE",$account."/user");
851     if (isset($deviceuser) && $deviceuser != "none") {
852       // Remove the device record from the user's device list
853       $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
854       /*$userdevices = str_replace($account."&", "", $userdevices."&");
855      
856       // If there was more than one device, remove the extra "&" at the end.
857       if (substr($userdevices, -1, 1) == "&") {
858         $userdevices = substr($userdevices, 0, -1);
859       }*/
860       $userdevicesarr = explode("&", $userdevices);
861       array_splice($userdevicesarr, array_search($account, $userdevicesarr), 1);
862       $userdevices = implode("&", $userdevicesarr);
863      
864       if (empty($userdevices)) {
865           $astman->database_del("AMPUSER",$deviceuser."/device");
866       } else {
867           $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
868       }
869     }
870     $astman->database_del("DEVICE",$account."/dial");
871     $astman->database_del("DEVICE",$account."/type");
872     $astman->database_del("DEVICE",$account."/user");
873     $astman->database_del("DEVICE",$account."/emergency_cid");
874
875     //delete from devices table
876     $sql="DELETE FROM devices WHERE id = \"$account\"";
877     sql($sql);
878
879     //voicemail symlink
880     exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
881   } else {
882     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
883   }
884  
885   //take care of sip/iax/zap config
886   $funct = "core_devices_del".strtolower($devinfo['tech']);
887   if(function_exists($funct)){
888     $funct($account);
889   }
890 }
891
892 function core_devices_get($account){
893   //get all the variables for the meetme
894   $sql = "SELECT * FROM devices WHERE id = '$account'";
895   $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
896  
897   //take care of sip/iax/zap config
898   $funct = "core_devices_get".strtolower($results['tech']);
899   if (!empty($results['tech']) && function_exists($funct)) {
900     $devtech = $funct($account);
901     if (is_array($devtech)){
902       $results = array_merge($results,$devtech);
903     }
904   }
905  
906   return $results;
907 }
908
909 // this function rebuilds the astdb based on device table contents
910 // used on devices.php if action=resetall
911 function core_devices2astdb(){
912   global $astman;
913   global $amp_conf;
914
915   $sql = "SELECT * FROM devices";
916   $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
917
918   //add details to astdb
919   if ($astman) {
920     $astman->database_deltree("DEVICE");
921     foreach ($devresults as $dev) {
922       extract($dev); 
923       $astman->database_put("DEVICE",$id."/dial",$dial);
924       $astman->database_put("DEVICE",$id."/type",$devicetype);
925       $astman->database_put("DEVICE",$id."/user",$user);   
926       // If a user is selected, add this device to the user
927       if ($user != "none") {
928           $existingdevices = $astman->database_get("AMPUSER",$user."/device");
929           if (!empty($existingdevices)) {
930               $existingdevices .= "&";
931           }
932           $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
933       }
934      
935       // create a voicemail symlink if needed
936       $thisUser = core_users_get($user);
937       if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
938         if(empty($thisUser['voicemail']))
939           $vmcontext = "default";
940         else
941           $vmcontext = $thisUser['voicemail'];
942         //voicemail symlink
943         exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
944         exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
945       }
946     }
947     return true;
948   } else {
949     return false;
950   }
951 }
952
953 // this function rebuilds the astdb based on users table contents
954 // used on devices.php if action=resetall
955 function core_users2astdb(){
956   global $amp_conf;
957   global $astman;
958
959   $sql = "SELECT * FROM users";
960   $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
961  
962   //add details to astdb
963   if ($astman) {
964     foreach($userresults as $usr) {
965       extract($usr);
966       $astman->database_put("AMPUSER",$extension."/password",$password);
967       $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
968       $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
969       $astman->database_put("AMPUSER",$extension."/recording",$recording);
970       $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
971       $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
972       $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
973     }
974     return true;
975   } else {
976     return false;
977   }
978
979 //  TODO: this was...
980 //  return $astman->disconnect();
981 //  is "true" the correct value...?
982 }
983
984 //add to sip table
985 function core_devices_addsip($account) {
986   global $db;
987   global $currentFile;
988
989   foreach ($_REQUEST as $req=>$data) {
990     if ( substr($req, 0, 8) == 'devinfo_' ) {
991       $keyword = substr($req, 8);
992       if ( $keyword == 'dial' && $data == '' ) {
993         $sipfields[] = array($account, $keyword, 'SIP/'.$account);
994       } elseif ($keyword == 'mailbox' && $data == '') {
995         $sipfields[] = array($account,'mailbox',$account.'@device');
996       } elseif ($keyword == 'md5secret' && $data != '' && strlen($data) != 32) {
997         $sipfields[] = array($account, 'md5secret', md5($account.':asterisk:'.$data));
998       } else {
999         $sipfields[] = array($account, $keyword, $data);
1000       }
1001     }
1002   }
1003  
1004   if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
1005     $sipfields = array(
1006       //array($account,'account',$account),
1007       array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1008       array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
1009       array($account,'md5secret', (isset($_REQUEST['md5secret']))? $_REQUEST['md5secret']:''),
1010       array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
1011       array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
1012       array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
1013       array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
1014       array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
1015       array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
1016       array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
1017       array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
1018       array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
1019       array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
1020       array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
1021       array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
1022       array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
1023       array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
1024       //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
1025       //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
1026       //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1027     );
1028   }
1029
1030   // Very bad
1031   $sipfields[] = array($account,'account',$account); 
1032   $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1033  
1034   // Where is this in the interface ??????
1035   $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1036   $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1037
1038   $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
1039   $result = $db->executeMultiple($compiled,$sipfields);
1040   if(DB::IsError($result)) {
1041     die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table'); 
1042   }
1043 }
1044
1045 function core_devices_delsip($account) {
1046   global $db;
1047   global $currentFile;
1048  
1049   $sql = "DELETE FROM sip WHERE id = '$account'";
1050   $result = $db->query($sql);
1051  
1052   if(DB::IsError($result)) {
1053     die_freepbx($result->getMessage().$sql);
1054   }
1055 }
1056
1057 function core_devices_getsip($account) {
1058   global $db;
1059   $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
1060   $results = $db->getAssoc($sql);
1061   if(DB::IsError($results)) {
1062     $results = null;
1063   }
1064  
1065   return $results;
1066 }
1067
1068 //add to iax table
1069 function core_devices_addiax2($account) {
1070   global $db;
1071   global $currentFile;
1072  
1073   foreach ($_REQUEST as $req=>$data) {
1074     if ( substr($req, 0, 8) == 'devinfo_' ) {
1075       $keyword = substr($req, 8);
1076       if ( $keyword == 'dial' && $data == '' ) {
1077         $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
1078       } elseif ($keyword == 'mailbox' && $data == '') {
1079         $iaxfields[] = array($account,'mailbox',$account.'@device');
1080       } else {
1081         $iaxfields[] = array($account, $keyword, $data);
1082       }
1083     }
1084   }
1085  
1086   if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
1087     $iaxfields = array(
1088       //array($account,'account',$account),
1089       array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
1090       array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
1091       array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1092       array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
1093       array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
1094       array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1095       array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
1096       array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
1097       array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
1098       array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
1099       array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
1100       array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
1101       //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
1102       //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1103       //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1104     );
1105   }
1106
1107   // Very bad
1108   $iaxfields[] = array($account,'account',$account); 
1109   $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1110   // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
1111   // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
1112   // callerid as a variable which gets picked up in macro-callerid.
1113   // Ref - http://bugs.digium.com/view.php?id=456
1114   $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
1115  
1116   // Where is this in the interface ??????
1117   $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1118   $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1119  
1120   $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
1121   $result = $db->executeMultiple($compiled,$iaxfields);
1122   if(DB::IsError($result)) {
1123     die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
1124   }
1125 }
1126
1127 function core_devices_deliax2($account) {
1128   global $db;
1129   global $currentFile;
1130  
1131   $sql = "DELETE FROM iax WHERE id = '$account'";
1132   $result = $db->query($sql);
1133  
1134   if(DB::IsError($result)) {
1135     die_freepbx($result->getMessage().$sql);
1136   }
1137 }
1138
1139 function core_devices_getiax2($account) {
1140   global $db;
1141   $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
1142   $results = $db->getAssoc($sql);
1143   if(DB::IsError($results)) {
1144     $results = null;
1145   }
1146  
1147   return $results;
1148 }
1149
1150 function core_devices_addzap($account) {
1151   global $db;
1152   global $currentFile;
1153  
1154   foreach ($_REQUEST as $req=>$data) {
1155     if ( substr($req, 0, 8) == 'devinfo_' ) {
1156       $keyword = substr($req, 8);
1157       if ( $keyword == 'dial' && $data == '' ) {
1158         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1159         $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
1160       } elseif ($keyword == 'mailbox' && $data == '') {
1161         $zapfields[] = array($account,'mailbox',$account.'@device');
1162       } else {
1163         $zapfields[] = array($account, $keyword, $data);
1164       }
1165     }
1166   }
1167  
1168   if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
1169     $zapfields = array(
1170       //array($account,'account',$account),
1171       array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1172       array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1173       //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
1174       array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1175       array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
1176       array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
1177       array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
1178       array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1179       array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
1180       array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
1181       array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
1182       array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
1183       //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'), 
1184       //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1185       array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1186       array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
1187     );
1188   }
1189
1190   // Very bad
1191   $zapfields[] = array($account,'account',$account); 
1192   $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1193  
1194   // Where is this in the interface ??????
1195   $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1196   $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1197
1198   $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
1199   $result = $db->executeMultiple($compiled,$zapfields);
1200   if(DB::IsError($result)) {
1201     die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
1202   }
1203 }
1204
1205 function core_devices_delzap($account) {
1206   global $db;
1207   global $currentFile;
1208  
1209   $sql = "DELETE FROM zap WHERE id = '$account'";
1210   $result = $db->query($sql);
1211   if(DB::IsError($result)) {
1212     die_freepbx($result->getMessage().$sql);
1213   }
1214 }
1215
1216 function core_devices_getzap($account) {
1217   global $db;
1218   $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
1219   $results = $db->getAssoc($sql);
1220   if(DB::IsError($results)) {
1221     $results = null;
1222   }
1223   return $results;
1224 }
1225 /* end page.devices.php functions */
1226
1227
1228
1229
1230 function core_hint_get($account){
1231   //determine what devices this user is associated with
1232   $sql = "SELECT dial from devices where user = '{$account}'";
1233   $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1234   //print_r($results);
1235  
1236   //create an array of strings
1237   if (is_array($results)){
1238     foreach ($results as $result) {
1239       $dial[] = $result['dial'];
1240     }
1241   }
1242  
1243   //create a string with & delimiter
1244   if (isset($dial) && is_array($dial)){
1245     $hint = implode($dial,"&");
1246   } else {
1247     if (isset($results[0]['dial'])) {
1248       $hint = $results[0]['dial'];
1249     } else {
1250       $hint = null;
1251     }
1252   }
1253  
1254   return $hint;
1255 }
1256
1257
1258
1259 /* begin page.users.php functions */
1260
1261 // get the existing extensions
1262 // the returned arrays contain [0]:extension [1]:name
1263 function core_users_list() {
1264   $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
1265
1266   //only allow extensions that are within administrator's allowed range
1267   foreach($results as $result){
1268     if (checkRange($result[0])){
1269       $extens[] = array($result[0],$result[1]);
1270     }
1271   }
1272  
1273   if (isset($extens)) {
1274     sort($extens);
1275     return $extens;
1276   } else {
1277     return null;
1278   }
1279 }
1280
1281 function core_sipname_check($sipname, $extension) {
1282   global $db;
1283   if (!isset($sipname) || trim($sipname)=='')
1284     return true;
1285
1286   $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
1287   $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1288   if(DB::IsError($results)) {
1289         die_freepbx($results->getMessage().$sql);
1290   }
1291  
1292   if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
1293     return false;
1294   else
1295     return true;
1296 }
1297
1298 function core_users_add($vars) {
1299   extract($vars);
1300  
1301   global $db;
1302   global $amp_conf;
1303   global $astman;
1304
1305   $thisexten = isset($thisexten) ? $thisexten : '';
1306
1307   //ensure this id is not already in use
1308   $extens = core_users_list();
1309   if(is_array($extens)) {
1310     foreach($extens as $exten) {
1311       if ($exten[0]===$extension) {
1312         echo "<script>javascript:alert('"._("This user")." ({$thisexten}) "._("or extension")." ({$extension}) "._("is already in use")."');</script>";
1313         return false;
1314       }
1315     }
1316   }
1317
1318   // clean and check the did to make sure it is not being used by another extension or in did routing
1319   //
1320   $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1321   if (trim($directdid) != "") {
1322     $existing=core_did_get($directdid,"","");
1323     $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1324     if (!empty($existing) || !empty($existing_directdid)) {
1325       if (!empty($existing)) {
1326         echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1327       } else {
1328         echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1329       }
1330       return false;
1331     }
1332   }
1333
1334   $sipname = preg_replace("/\s/" ,"", trim($sipname));
1335   if (! core_sipname_check($sipname, $extension)) {
1336     echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
1337     return false;
1338   }
1339  
1340   //build the recording variable
1341   $recording = "out=".$record_out."|in=".$record_in;
1342  
1343   //escape quotes and any other bad chars:
1344   if(!get_magic_quotes_gpc()) {
1345     $outboundcid = addslashes($outboundcid);
1346     $name = addslashes($name);
1347   }
1348
1349   //if voicemail is enabled, set the box@context to use
1350   //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
1351   if ( function_exists('voicemail_mailbox_get') ) {
1352     $vmbox = voicemail_mailbox_get($extension);
1353     if ( $vmbox == null ) {
1354       $voicemail = "novm";
1355       $vmx_state = "false";
1356     } else {
1357       $voicemail = $vmbox['vmcontext'];
1358     }
1359   }
1360
1361   // MODIFICATION: (PL)
1362   // Added for directdid and didalert l for Alert Info distinctive ring)
1363   //
1364   // cleanup any non dial pattern characters prior to inserting into the database
1365   // then add directdid to the insert command.
1366   //
1367   // Clean replace any <> with () in display name - should have javascript stopping this but ...
1368   //
1369   $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
1370  
1371   //insert into users table
1372   $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
1373   $sql.= "$extension\", \"";
1374   $sql.= isset($password)?$password:'';
1375   $sql.= "\", \"";
1376   $sql.= isset($name)?$name:'';
1377   $sql.= "\", \"";
1378   $sql.= isset($voicemail)?$voicemail:'default';
1379   $sql.= "\", \"";
1380   $sql.= isset($ringtimer)?$ringtimer:'';
1381   $sql.= "\", \"";
1382   $sql.= isset($noanswer)?$noanswer:'';
1383   $sql.= "\", \"";
1384   $sql.= isset($recording)?$recording:'';
1385   $sql.= "\", \"";
1386   $sql.= isset($outboundcid)?$outboundcid:'';
1387   $sql.= "\", \"";
1388   $sql.= isset($directdid)?$directdid:'';
1389   $sql.= "\", \"";
1390   $sql.= isset($didalert)?$didalert:'';
1391
1392   $sql.= "\", \"";
1393   $sql.= isset($faxexten)?$faxexten:'';
1394   $sql.= "\", \"";
1395   $sql.= isset($faxemail)?$faxemail:'';
1396   $sql.= "\", \"";
1397   $sql.= isset($answer)?$answer:'';
1398   $sql.= "\", \"";
1399   $sql.= isset($wait)?$wait:'';
1400   $sql.= "\", \"";
1401   $sql.= isset($privacyman)?$privacyman:'';
1402   $sql.= "\", \"";
1403   $sql.= isset($mohclass)?$mohclass:'';
1404   $sql.= "\", \"";
1405   $sql.= isset($sipname)?$sipname:'';
1406   $sql.= "\")";
1407   sql($sql);
1408
1409   //write to astdb
1410   if ($astman) {
1411     $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
1412     $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
1413     $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
1414     $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
1415     $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
1416     $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
1417     $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
1418     $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
1419     $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
1420     $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
1421
1422     if (trim($callwaiting) == 'enabled') {
1423       $astman->database_put("CW",$extension,"\"ENABLED\"");
1424     } else if (trim($callwaiting) == 'disabled') {
1425       $astman->database_del("CW",$extension);
1426     } else {
1427       echo "ERROR: this state should not exist<br>";
1428     }
1429
1430     if ($vmx_state && $voicemail != "novm") {
1431
1432       $unavail_mode="enabled";
1433       $busy_mode="disabled";
1434       $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1435
1436       if (trim($vmx_state) == 'blocked') {
1437
1438         $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
1439         $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
1440
1441       } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
1442
1443         $repeat="1";
1444         $timeout="2";
1445         $vmxopts_timeout="";
1446         $loops="1";
1447
1448         $mode="unavail";
1449         $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
1450         $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1451         $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1452         $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1453         $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1454
1455         $mode="busy";
1456         $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
1457         $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1458         $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1459         $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1460         $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1461        
1462       }
1463     } else {
1464       $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1465       if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
1466         $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
1467         $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
1468       }
1469     }
1470   } else {
1471     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1472   }
1473   return true;
1474 }
1475
1476 function core_users_get($extension){
1477   global $db;
1478   global $amp_conf;
1479   global $astman;
1480   //get all the variables for the meetme
1481   $sql = "SELECT * FROM users WHERE extension = '$extension'";
1482   $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1483   if(DB::IsError($results)) {
1484     die_freepbx($results->getMessage().$sql);
1485   }
1486  
1487   //explode recording vars
1488   $recording = explode("|",$results['recording']);
1489   if (isset($recording[1])) {
1490     $recout = substr($recording[0],4);
1491     $recin = substr($recording[1],3);
1492     $results['record_in']=$recin;
1493     $results['record_out']=$recout;
1494   } else {
1495     $results['record_in']='Adhoc';
1496     $results['record_out']='Adhoc';
1497   }
1498   if ($astman) {
1499     $cw = $astman->database_get("CW",$extension);
1500     $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
1501     $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1502     $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
1503     $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
1504   } else {
1505     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1506   }
1507
1508   return $results;
1509 }
1510
1511 function core_users_del($extension){
1512   global $db;
1513   global $amp_conf;
1514   global $astman;
1515  
1516   //delete from devices table
1517   $sql="DELETE FROM users WHERE extension = \"$extension\"";
1518   $results = $db->query($sql);
1519   if(DB::IsError($results)) {
1520     die_freepbx($results->getMessage().$sql);
1521   }
1522
1523   //delete details to astdb
1524   if ($astman) {
1525     $astman->database_del("AMPUSER",$extension."/password");
1526     $astman->database_del("AMPUSER",$extension."/ringtimer");
1527     $astman->database_del("AMPUSER",$extension."/noanswer");
1528     $astman->database_del("AMPUSER",$extension."/recording");
1529     $astman->database_del("AMPUSER",$extension."/outboundcid");
1530     $astman->database_del("AMPUSER",$extension."/cidname");
1531     $astman->database_del("AMPUSER",$extension."/cidnum");
1532     $astman->database_del("AMPUSER",$extension."/voicemail");
1533     $astman->database_del("AMPUSER",$extension."/device");
1534   } else {
1535     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1536   }
1537 }
1538
1539 function core_users_directdid_get($directdid=""){
1540   if (empty($directdid)) {
1541     return array();
1542   } else {
1543     $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
1544     return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1545   }
1546 }
1547
1548 function core_users_cleanastdb($extension) {
1549   // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
1550   // call forwarding, call waiting settings could hang around and bite someone if they
1551   // recycle an extension. Is called from page.xtns and page.users.
1552   global $amp_conf;
1553   global $astman;
1554
1555   if ($astman) {
1556     $astman->database_del("CW",$extension);
1557     $astman->database_del("CF",$extension);
1558     $astman->database_del("CFB",$extension);
1559     $astman->database_del("CFU",$extension);
1560     $astman->database_deltree("AMPUSER/".$extension."/vmx");
1561
1562   } else {
1563     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1564   }
1565 }
1566
1567 function core_users_edit($extension,$vars){
1568   global $db;
1569   global $amp_conf;
1570   global $astman;
1571  
1572   //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
1573   if ($astman) {
1574     $ud = $astman->database_get("AMPUSER",$extension."/device");
1575     $vars['device'] = $ud;
1576   } else {
1577     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1578   }
1579  
1580   $directdid=$vars['directdid'];
1581   $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1582   // clean and check the did to make sure it is not being used by another extension or in did routing
1583   //
1584   if (trim($directdid) != "") {
1585     $existing=core_did_get($directdid,"","");
1586     $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1587     if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
1588       if (!empty($existing)) {
1589         echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1590       } else {
1591         echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1592       }
1593       return false;
1594     }
1595   }
1596
1597   //delete and re-add
1598   if (core_sipname_check($vars['sipname'],$extension)) {
1599     core_users_del($extension);
1600     core_users_add($vars);
1601   }
1602   return true;
1603  
1604 }
1605
1606 function core_directdid_list(){
1607   $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
1608   return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1609 }
1610
1611
1612
1613 /* end page.users.php functions */
1614
1615
1616
1617
1618
1619 /* begin page.trunks.php functions */
1620
1621 // we're adding ,don't require a $trunknum
1622 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1623   global $db;
1624  
1625   // find the next available ID
1626   $trunknum = 1;
1627   foreach(core_trunks_list() as $trunk) {
1628     if ($trunknum == ltrim($trunk[0],"OUT_")) {
1629       $trunknum++;
1630     }
1631   }
1632  
1633   core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1634  
1635   return $trunknum;
1636 }
1637
1638 function core_trunks_del($trunknum, $tech = null) {
1639   global $db;
1640  
1641   if ($tech === null) { // in EditTrunk, we get this info anyways
1642     $tech = core_trunks_getTrunkTech($trunknum);
1643   }
1644
1645   //delete from globals table
1646   sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
1647  
1648   //write outids
1649   core_trunks_writeoutids();
1650
1651   // conditionally, delete from iax or sip
1652   switch (strtolower($tech)) {
1653     case "iax":
1654     case "iax2":
1655       sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1656     break;
1657     case "sip":
1658       sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1659     break;
1660   }
1661 }
1662
1663 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1664   //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1665   $tech = core_trunks_getTrunkTech($trunknum);
1666   core_trunks_del($trunknum, $tech);
1667   core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1668 }
1669
1670 // just used internally by addTrunk() and editTrunk()
1671 //obsolete
1672 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1673   global $db;
1674  
1675   if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
1676  
1677   //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1678  
1679   // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
1680   $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
1681   $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
1682  
1683   $glofields = array(
1684       array('OUT_'.$trunknum, $outval),
1685       array('OUTPREFIX_'.$trunknum, $dialoutprefix),
1686       array('OUTMAXCHANS_'.$trunknum, $maxchans),
1687       array('OUTCID_'.$trunknum, $outcid),
1688       array('OUTKEEPCID_'.$trunknum, $keepcid),
1689       array('OUTFAIL_'.$trunknum, $failtrunk),
1690       array('OUTDISABLE_'.$trunknum, $disabletrunk),
1691       );
1692      
1693   unset($techtemp);
1694  
1695   $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1696   $result = $db->executeMultiple($compiled,$glofields);
1697   if(DB::IsError($result)) {
1698     die_freepbx($result->getMessage()."<br><br>".$sql);
1699   }
1700  
1701   core_trunks_writeoutids();
1702
1703   $disable_flag = ($disabletrunk == "on")?1:0;
1704  
1705   switch (strtolower($tech)) {
1706     case "iax":
1707     case "iax2":
1708       core_trunks_addSipOrIax($peerdetails,'iax',$channelid,$trunknum,$disable_flag);
1709       if ($usercontext != ""){
1710         core_trunks_addSipOrIax($userconfig,'iax',$usercontext,'9'.$trunknum,$disable_flag);
1711       }
1712       if ($register != ""){
1713         core_trunks_addRegister($trunknum,'iax',$register,$disable_flag);
1714       }
1715     break;
1716     case "sip":
1717       core_trunks_addSipOrIax($peerdetails,'sip',$channelid,$trunknum,$disable_flag);
1718       if ($usercontext != ""){
1719         core_trunks_addSipOrIax($userconfig,'sip',$usercontext,'9'.$trunknum,$disable_flag);
1720       }
1721       if ($register != ""){
1722         core_trunks_addRegister($trunknum,'sip',$register,$disable_flag);
1723       }
1724     break;
1725   }
1726 }
1727
1728 function core_trunks_getTrunkTech($trunknum) {
1729
1730   $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1731   if (!$results) {
1732     return false;
1733   }
1734   if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1735     $tech = "custom";
1736   } else {
1737     $tech = strtolower( strtok($results[0][0],'/') ); // the technology.  ie: ZAP/g0 is ZAP
1738    
1739     if ($tech == "iax2") $tech = "iax"; // same thing, here
1740   }
1741   return $tech;
1742 }
1743
1744 //add trunk info to sip or iax table
1745 function core_trunks_addSipOrIax($config,$table,$channelid,$trunknum,$disable_flag=0) {
1746   global $db;
1747  
1748   $confitem['account'] = $channelid;
1749   $gimmieabreak = nl2br($config);
1750   $lines = split('<br />',$gimmieabreak);
1751   foreach ($lines as $line) {
1752     $line = trim($line);
1753     if (count(split('=',$line)) > 1) {
1754       $tmp = split('=',$line,2);
1755       $key=trim($tmp[0]);
1756       $value=trim($tmp[1]);
1757       if (isset($confitem[$key]) && !empty($confitem[$key]))
1758         $confitem[$key].="&".$value;
1759       else
1760         $confitem[$key]=$value;
1761     }
1762   }
1763   foreach($confitem as $k=>$v) {
1764     $dbconfitem[]=array($k,$v);
1765   }
1766   $compiled = $db->prepare("INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')");
1767   $result = $db->executeMultiple($compiled,$dbconfitem);
1768   if(DB::IsError($result)) {
1769     die_freepbx($result->getMessage()."<br><br>INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')"); 
1770   }
1771 }
1772
1773 //get unique trunks
1774 function core_trunks_list($assoc = false) {
1775   // TODO: $assoc default to true, eventually..
1776
1777   global $db;
1778   global $amp_conf;
1779  
1780   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
1781   {
1782     // TODO: sqlite work arround - diego
1783     // TODO: WILL NOT WORK, need to remove the usage of SUBSTRING
1784     // need to reorder the trunks in PHP code
1785     $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1786     $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\_%') d ";
1787     $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\_%' ";
1788     $sqlstr .= "UNION ALL ";
1789     $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1790     $sqlstr .= "WHERE v.variable LIKE 'OUT\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1791     $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\_%' ) ";
1792     $sqlstr .= "ORDER BY variable";
1793
1794     //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT_%' ORDER BY variable","getAll");
1795     $unique_trunks = sql($sqlstr,"getAll");
1796   }
1797   else
1798   {
1799     // we have to escape _ for mysql: normally a wildcard
1800     $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1801     $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\\\_%') d ";
1802     $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\\\_%' ";
1803     $sqlstr .= "UNION ALL ";
1804     $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1805     $sqlstr .= "WHERE v.variable LIKE 'OUT\\\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1806     $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\\\_%' ) ";
1807     $sqlstr .= "ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0";
1808
1809     //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT\\\_%' ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0","getAll");
1810     $unique_trunks = sql($sqlstr,"getAll");
1811   }
1812
1813   //if no trunks have ever been defined, then create the proper variables with the default zap trunk
1814   if (count($unique_trunks) == 0)
1815   {
1816     //If all trunks have been deleted from admin, dialoutids might still exist
1817     sql("DELETE FROM globals WHERE variable = 'DIALOUTIDS'");
1818  
1819     $glofields = array(array('OUT_1','ZAP/g0'),
1820               array('DIAL_OUT_1','9'),
1821               array('DIALOUTIDS','1'));
1822     $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1823     $result = $db->executeMultiple($compiled,$glofields);
1824     if(DB::IsError($result))
1825     {
1826       die_freepbx($result->getMessage()."<br><br>".$sql);
1827     }
1828     $unique_trunks[] = array('OUT_1','ZAP/g0');
1829   }
1830   // asort($unique_trunks);
1831
1832   if ($assoc) {
1833     $trunkinfo = array();
1834
1835     foreach ($unique_trunks as $trunk) {
1836       list($tech,$name) = explode('/',$trunk[1]);
1837       $trunkinfo[$name] = array(
1838         'name' => $name,
1839         'tech' => $tech,
1840         'globalvar' => $trunk[0], // ick
1841         'value' => $trunk[2], // ??  no idea what this is.
1842       ); 
1843     }
1844     return $trunkinfo;
1845   } else {
1846     return $unique_trunks;
1847   }
1848 }
1849
1850 //write the OUTIDS global variable (used in dialparties.agi)
1851 function core_trunks_writeoutids() {
1852   // we have to escape _ for mysql: normally a wildcard
1853   $unique_trunks = sql("SELECT variable FROM globals WHERE variable LIKE 'OUT\\\_%'","getAll");
1854
1855   $outids = null; // Start off with nothing
1856   foreach ($unique_trunks as $unique_trunk) {
1857     $outid = strtok($unique_trunk[0],"_");
1858     $outid = strtok("_");
1859     $outids .= $outid ."/";
1860   }
1861  
1862   sql("UPDATE globals SET value = '$outids' WHERE variable = 'DIALOUTIDS'");
1863 }
1864
1865 function core_trunks_addRegister($trunknum,$tech,$reg,$disable_flag=0) {
1866   sql("INSERT INTO $tech (id, keyword, data, flags) values ('9999999$trunknum','register','$reg','$disable_flag')");
1867 }
1868
1869
1870 function core_trunks_addDialRules($trunknum, $dialrules) {
1871   $values = array();
1872   $i = 1;
1873   foreach ($dialrules as $rule) {
1874     $values["rule".$i++] = $rule;
1875   }
1876  
1877   $conf = core_trunks_readDialRulesFile();
1878  
1879   // rewrite for this trunk
1880   $conf["trunk-".$trunknum] = $values;
1881  
1882   core_trunks_writeDialRulesFile($conf);
1883 }
1884
1885 function core_trunks_readDialRulesFile() {
1886   global $amp_conf;
1887   $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1888  
1889   core_trunks_parse_conf($localPrefixFile, $conf, $section);
1890  
1891   return $conf;
1892 }
1893
1894 function core_trunks_writeDialRulesFile($conf) {
1895   global $amp_conf;
1896   $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1897  
1898   $fd = fopen($localPrefixFile,"w");
1899   foreach ($conf as $section=>$values) {
1900     fwrite($fd, "[".$section."]\n");
1901     foreach ($values as $key=>$value) {
1902       fwrite($fd, $key."=".$value."\n");
1903     }
1904     fwrite($fd, "\n");
1905   }
1906   fclose($fd);
1907 }
1908
1909 function core_trunks_parse_conf($filename, &$conf, &$section) {
1910   if (is_null($conf)) {
1911     $conf = array();
1912   }
1913   if (is_null($section)) {
1914     $section = "general";
1915   }
1916  
1917   if (file_exists($filename)) {
1918     $fd = fopen($filename, "r");
1919     while ($line = fgets($fd, 1024)) {
1920       if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
1921         // name = value
1922         // option line
1923         $conf[$section][ $matches[1] ] = $matches[2];
1924       } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
1925         // section name
1926         $section = strtolower($matches[1]);
1927       } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
1928         // include another file
1929        
1930         if ($matches[1][0] == "/") {
1931           // absolute path
1932           $filename = $matches[1];
1933         } else {
1934           // relative path
1935           $filename =  dirname($filename)."/".$matches[1];
1936         }
1937        
1938         core_trunks_parse_conf($filename, $conf, $section);
1939       }
1940     }
1941   }
1942 }
1943
1944 function core_trunks_getTrunkTrunkName($trunknum) {
1945   $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1946   if (!$results) {
1947     return false;
1948   }
1949  
1950   if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1951     $tname = substr($results[0][0],4);
1952   } else {
1953   strtok($results[0][0],'/');
1954     $tname = strtok('/'); // the text _after_ technology.  ie: ZAP/g0 is g0
1955   }
1956   return $tname;
1957 }
1958
1959 //get and print peer details (prefixed with 4 9's)
1960 function core_trunks_getTrunkPeerDetails($trunknum) {
1961   global $db;
1962  
1963   $tech = core_trunks_getTrunkTech($trunknum);
1964  
1965   if ($tech == "zap") return ""; // zap has no details
1966  
1967   $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999$trunknum' ORDER BY id","getAll");
1968  
1969   foreach ($results as $result) {
1970     if ($result[0] != 'account') {
1971       if (isset($confdetail))
1972         $confdetail .= $result[0] .'='. $result[1] . "\n";
1973       else
1974         $confdetail = $result[0] .'='. $result[1] . "\n";
1975     }
1976   }
1977   return $confdetail;
1978 }
1979
1980 //get trunk user context (prefixed with 5 9's)
1981 function core_trunks_getTrunkUserContext($trunknum) {
1982   $tech = core_trunks_getTrunkTech($trunknum);
1983   if ($tech == "zap") return ""; // zap has no account
1984  
1985   $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
1986
1987   foreach ($results as $result) {
1988     if ($result[0] == 'account') {
1989       $account = $result[1];
1990     }
1991   }
1992   return isset($account)?$account:null;
1993 }
1994
1995 //get and print user config (prefixed with 5 9's)
1996 function core_trunks_getTrunkUserConfig($trunknum) {
1997   global $db;
1998  
1999   $tech = core_trunks_getTrunkTech($trunknum);
2000  
2001   if ($tech == "zap") return ""; // zap has no details
2002  
2003   $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
2004
2005   foreach ($results as $result) {
2006     if ($result[0] != 'account') {
2007       if (isset($confdetail))
2008         $confdetail .= $result[0] .'='. $result[1] . "\n";
2009       else
2010         $confdetail = $result[0] .'='. $result[1] . "\n";
2011     }
2012   }
2013   return isset($confdetail)?$confdetail:null;
2014 }
2015
2016 //get trunk account register string
2017 function core_trunks_getTrunkRegister($trunknum) {
2018   $tech = core_trunks_getTrunkTech($trunknum);
2019  
2020   if ($tech == "zap") return ""; // zap has no register
2021  
2022   $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999999$trunknum'","getAll");
2023
2024   foreach ($results as $result) {
2025       $register = $result[1];
2026   }
2027   return isset($register)?$register:null;
2028 }
2029
2030 function core_trunks_getDialRules($trunknum) {
2031   $conf = core_trunks_readDialRulesFile();
2032   if (isset($conf["trunk-".$trunknum])) {
2033     return $conf["trunk-".$trunknum];
2034   }
2035   return false;
2036 }
2037
2038 //get outbound routes for a given trunk
2039 function core_trunks_gettrunkroutes($trunknum) {
2040   global $amp_conf;
2041
2042   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2043     $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";
2044   else
2045     $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";
2046
2047   $results = sql( $sql_code, "getAll" );
2048
2049   foreach ($results as $row) {
2050     // original code was:
2051     //  $routes[$row[0]] = $row[1];
2052     // but substring is not supported in sqlite3.
2053     // how about we remove the 2nd part of the "if"? and use the same code on all DB's?
2054
2055     $t = ($amp_conf["AMPDBENGINE"] == "sqlite3") ? substr( $row[0], 7 ) : $row[0];
2056     $r = $row[1];
2057     $routes[ $r ] = $t;
2058
2059   }
2060   // array(routename=>priority)
2061   return isset($routes)?$routes:null;
2062 }
2063
2064 function core_trunks_deleteDialRules($trunknum) {
2065   $conf = core_trunks_readDialRulesFile();
2066  
2067   // remove rules for this trunk
2068   unset($conf["trunk-".$trunknum]);
2069  
2070   core_trunks_writeDialRulesFile($conf);
2071 }
2072
2073 /* end page.trunks.php functions */
2074
2075
2076 /* begin page.routing.php functions */
2077
2078 //get unique outbound route names
2079 function core_routing_getroutenames()
2080 {
2081   global $amp_conf;
2082  
2083   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2084   {
2085     // SUBSTRING is not supported under sqlite3, we need to filter
2086     // this in php. I am not sure why "6" and not "7"
2087     // but I don't really care -> it works :)
2088     $results = sql("SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2089     foreach( array_keys($results) as $idx )
2090     {
2091        $results[$idx][0] = substr( $results[$idx][0], 6);
2092     }
2093   }
2094   else
2095   {
2096     // we SUBSTRING() to remove "outrt-"
2097     $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2098   }
2099
2100
2101   if (count($results) == 0) {
2102     // see if they're still using the old dialprefix method
2103     $results = sql("SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\\\_OUT\\\_%'","getAll");
2104     // we SUBSTRING() to remove "outrt-"
2105    
2106     if (count($results) > 0) {
2107       // yes, they are using old method, let's update
2108      
2109       // get the default trunk
2110       $results_def = sql("SELECT value FROM globals WHERE variable = 'OUT'","getAll");
2111      
2112       if (preg_match("/{OUT_(\d+)}/", $results_def[0][0], $matches)) {
2113         $def_trunk = $matches[1];
2114       } else {
2115         $def_trunk = "";
2116       }
2117      
2118       $default_patterns = array(  // default patterns that used to be in extensions.conf
2119             "NXXXXXX",
2120             "NXXNXXXXXX",
2121             "1800NXXXXXX",
2122             "1888NXXXXXX",
2123             "1877NXXXXXX",
2124             "1866NXXXXXX",
2125             "1NXXNXXXXXX",
2126             "011.",
2127             "911",
2128             "411",
2129             "311",
2130             );
2131      
2132       foreach ($results as $temp) {
2133         // temp[0] is "DIAL_OUT_1"
2134         // temp[1] is the dial prefix
2135        
2136         $trunknum = substr($temp[0],9);
2137        
2138         $name = "route".$trunknum;
2139        
2140         $trunks = array(1=>"OUT_".$trunknum); // only one trunk to use
2141        
2142         $patterns = array();
2143         foreach ($default_patterns as $pattern) {
2144           $patterns[] = $temp[1]."|".$pattern;
2145         }
2146        
2147         if ($trunknum == $def_trunk) {
2148           // this is the default trunk, add the patterns with no prefix
2149           $patterns = array_merge($patterns, $default_patterns);
2150         }
2151        
2152         // add this as a new route
2153         core_routing_add($name, $patterns, $trunks,"new");
2154       }
2155      
2156      
2157       // delete old values
2158       sql("DELETE FROM globals WHERE (variable LIKE 'DIAL\\\_OUT\\\_%') OR (variable = 'OUT') ");
2159
2160       // we need to re-generate extensions_additional.conf
2161       // i'm not sure how to do this from here
2162      
2163       // re-run our query
2164       $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2165       // we SUBSTRING() to remove "outrt-"
2166     }
2167    
2168   } // else, it just means they have no routes.
2169  
2170   return $results;
2171 }
2172
2173 function core_routing_setroutepriority($routepriority, $reporoutedirection, $reporoutekey)
2174 {
2175   global $db, $amp_conf;
2176   $counter=-1;
2177   foreach ($routepriority as $tresult)
2178   {
2179     $counter++;
2180     if (($counter==($reporoutekey-1)) && ($reporoutedirection=="up")) {
2181       // swap this one with the one before (move up)
2182       $temproute = $routepriority[$counter];
2183       $routepriority[ $counter ] = $routepriority[ $counter+1 ];
2184       $routepriority[ $counter+1 ] = $temproute;
2185      
2186     } else if (($counter==($reporoutekey)) && ($reporoutedirection=="down")) {
2187       // swap this one with the one after (move down)
2188       $temproute = $routepriority[ $counter+1 ];
2189       $routepriority[ $counter+1 ] = $routepriority[ $counter ];
2190       $routepriority[ $counter ] = $temproute;
2191     }
2192   }
2193   unset($temptrunk);
2194   $routepriority = array_values($routepriority); // resequence our numbers
2195   $counter=0;
2196   foreach ($routepriority as $tresult) {
2197     $order=core_routing_setroutepriorityvalue($counter++);
2198     $sql = sprintf("Update extensions set context='outrt-%s-%s' WHERE context='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2199     $result = $db->query($sql);
2200     if(DB::IsError($result)) {     
2201       die_freepbx($result->getMessage());
2202     }
2203   }
2204  
2205   // Delete and readd the outbound-allroutes entries
2206   $sql = "delete from  extensions WHERE context='outbound-allroutes'";
2207   $result = $db->query($sql);
2208   if(DB::IsError($result)) {
2209           die_freepbx($result->getMessage().$sql);
2210   }
2211  
2212   $sql = "SELECT DISTINCT context FROM extensions WHERE context like 'outrt-%' ORDER BY context";
2213   $results = $db->getAll($sql);
2214   if(DB::IsError($results)) {
2215     die_freepbx($results->getMessage());
2216   }
2217
2218   $priority_loops=1; 
2219   foreach ($results as $row) {
2220     $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2221     $sql .= "('outbound-allroutes', ";
2222     $sql .= "'include', ";
2223     $sql .= "'".$priority_loops++."', ";
2224     $sql .= "'".$row[0]."', ";
2225     $sql .= "'', ";
2226     $sql .= "'', ";
2227     $sql .= "'2')";
2228  
2229     //$sql = sprintf("Update extensions set application='outrt-%s-%s' WHERE context='outbound-allroutes' and  application='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2230     $result = $db->query($sql);
2231     if(DB::IsError($result)) {     
2232       die_freepbx($result->getMessage(). $sql);
2233     }
2234   }
2235  
2236   if ( $amp_conf["AMPDBENGINE"] == "sqlite3")
2237     $sql = "SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2238   else
2239     $sql = "SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2240
2241         // we SUBSTRING() to remove "outrt-"
2242         $routepriority = $db->getAll($sql);
2243         if(DB::IsError($routepriority)) {
2244                 die_freepbx($routepriority->getMessage());
2245         }
2246
2247   // TODO: strip the context on the sqlite3 backend
2248   // not sure where does it effects, since this is working on my setup...
2249   // welcome to funky town
2250         return ($routepriority);
2251 }
2252
2253 function core_routing_setroutepriorityvalue($key)
2254 {
2255   $key=$key+1;
2256   if ($key<10)
2257     $prefix = sprintf("00%d",$key);
2258   else if ((9<$key)&&($key<100))
2259     $prefix = sprintf("0%d",$key);
2260   else if ($key>100)
2261     $prefix = sprintf("%d",$key);
2262   return ($prefix);
2263 }
2264
2265
2266 function core_routing_add($name, $patterns, $trunks, $method, $pass, $emergency = "", $intracompany = "", $mohsilence = "") {
2267
2268   global $db;
2269
2270   $trunktech=array();
2271
2272   //Retrieve each trunk tech for later lookup
2273   $sql="select * from globals WHERE variable LIKE 'OUT\\_%'";
2274         $result = $db->getAll($sql);
2275         if(DB::IsError($result)) {
2276     die_freepbx($result->getMessage());
2277   }
2278   foreach($result as $tr) {
2279     $tech = strtok($tr[1], "/");
2280     $trunktech[$tr[0]]=$tech;
2281   }
2282  
2283   if ($method=="new") {
2284     $sql="select DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context";
2285     $routepriority = $db->getAll($sql);
2286     if(DB::IsError($result)) {
2287       die_freepbx($result->getMessage());
2288     }
2289     $order=core_routing_setroutepriorityvalue(count($routepriority));
2290     $name = sprintf ("%s-%s",$order,$name);
2291   }
2292   $trunks = array_values($trunks); // probably already done, but it's important for our dialplan
2293
2294  
2295   foreach ($patterns as $pattern) {
2296     if (false !== ($pos = strpos($pattern,"|"))) {
2297       // we have a | meaning to not pass the digits on
2298       // (ie, 9|NXXXXXX should use the pattern _9NXXXXXX but only pass NXXXXXX, not the leading 9)
2299      
2300       $pattern = str_replace("|","",$pattern); // remove all |'s
2301       $exten = "EXTEN:".$pos; // chop off leading digit
2302     } else {
2303       // we pass the full dialed number as-is
2304       $exten = "EXTEN";
2305     }
2306    
2307     if (!preg_match("/^[0-9*]+$/",$pattern)) {
2308       // note # is not here, as asterisk doesn't recoginize it as a normal digit, thus it requires _ pattern matching
2309      
2310       // it's not strictly digits, so it must have patterns, so prepend a _
2311       $pattern = "_".$pattern;
2312     }
2313    
2314     // 1st priority is emergency dialing variable (if set)
2315     if(!empty($emergency)) {
2316       $startpriority = 1;
2317       $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2318       $sql .= "('outrt-".$name."', ";
2319       $sql .= "'".$pattern."', ";
2320       $sql .= "'".$startpriority."', ";
2321       $sql .= "'SetVar', ";
2322       $sql .= "'EMERGENCYROUTE=YES', ";
2323       $sql .= "'Use Emergency CID for device')";
2324       $result = $db->query($sql);
2325       if(DB::IsError($result)) {
2326         die_freepbx($result->getMessage());
2327       }
2328     } else {
2329       $startpriority = 0;
2330     }
2331
2332     // Next Priority (either first or second depending on above)
2333     if(!empty($intracompany)) {
2334          $startpriority += 1;
2335          $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2336          $sql .= "('outrt-".$name."', ";
2337          $sql .= "'".$pattern."', ";
2338          $sql .= "'".$startpriority."', ";
2339          $sql .= "'SetVar', ";
2340          $sql .= "'INTRACOMPANYROUTE=YES', ";
2341          $sql .= "'Preserve Intenal CID Info')";
2342          $result = $db->query($sql);
2343         if(DB::IsError($result)) {
2344              die_freepbx($result->getMessage());
2345         }
2346     }
2347
2348     // Next Priority (either first, second or third depending on above)
2349     if(!empty($mohsilence) && trim($mohsilence) != 'default') {
2350          $startpriority += 1;
2351          $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2352          $sql .= "('outrt-".$name."', ";
2353          $sql .= "'".$pattern."', ";
2354          $sql .= "'".$startpriority."', ";
2355          $sql .= "'SetVar', ";
2356          $sql .= "'MOHCLASS=".$mohsilence."', ";
2357          $sql .= "'Do not play moh on this route')";
2358          $result = $db->query($sql);
2359         if(DB::IsError($result)) {
2360              die_freepbx($result->getMessage());
2361         }
2362     }
2363
2364     $first_trunk = 1;
2365     foreach ($trunks as $priority => $trunk) {
2366       $priority += $startpriority;
2367       $priority += 1; // since arrays are 0-based, but we want priorities to start at 1
2368      
2369       $sql = "INSERT INTO extensions (context, extension, priority, application, args) VALUES ";
2370       $sql .= "('outrt-".$name."', ";
2371       $sql .= "'".$pattern."', ";
2372       $sql .= "'".$priority."', ";
2373       $sql .= "'Macro', ";
2374       if ($first_trunk)
2375         $pass_str = $pass;
2376       else
2377         $pass_str = "";
2378
2379       if ($trunktech[$trunk] == "ENUM")
2380         $sql .= "'dialout-enum,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2381       else
2382         $sql .= "'dialout-trunk,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2383       $sql .= ")";
2384      
2385       $result = $db->query($sql);
2386       if(DB::IsError($result)) {
2387         die_freepbx($result->getMessage());
2388       }
2389       //To identify the first trunk in a pattern
2390       //so that passwords are in the first trunk in
2391       //each pattern
2392       $first_trunk = 0;
2393     }
2394    
2395     $priority += 1;
2396     $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2397     $sql .= "('outrt-".$name."', ";
2398     $sql .= "'".$pattern."', ";
2399     $sql .= "'".$priority."', ";
2400     $sql .= "'Macro', ";
2401     $sql .= "'outisbusy', ";
2402     $sql .= "'No available circuits')";
2403    
2404     $result = $db->query($sql);
2405     if(DB::IsError($result)) {
2406       die_freepbx($result->getMessage());
2407     }
2408   }
2409
2410  
2411   // add an include=>outrt-$name  to [outbound-allroutes]:
2412  
2413   // we have to find the first available priority.. priority doesn't really matter for the include, but
2414   // there is a unique index on (context,extension,priority) so if we don't do this we can't put more than
2415   // one route in the outbound-allroutes context.
2416   $sql = "SELECT priority FROM extensions WHERE context = 'outbound-allroutes' AND extension = 'include'";
2417   $results = $db->getAll($sql);
2418   if(DB::IsError($results)) {
2419     die_freepbx($results->getMessage());
2420   }
2421   $priorities = array();
2422   foreach ($results as $row) {
2423     $priorities[] = $row[0];
2424   }
2425   for ($priority = 1; in_array($priority, $priorities); $priority++);
2426  
2427   // $priority should now be the lowest available number
2428  
2429   $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2430   $sql .= "('outbound-allroutes', ";
2431   $sql .= "'include', ";
2432   $sql .= "'".$priority."', ";
2433   $sql .= "'outrt-".$name."', ";
2434   $sql .= "'', ";
2435   $sql .= "'', ";
2436   $sql .= "'2')";
2437  
2438   $result = $db->query($sql);
2439   if(DB::IsError($result)) {
2440     die_freepbx($priority.$result->getMessage());
2441   }
2442  
2443 }
2444
2445 function core_routing_edit($name, $patterns, $trunks, $pass, $emergency="", $intracompany = "", $mohsilence="") {
2446   core_routing_del($name);
2447   core_routing_add($name, $patterns, $trunks,"edit", $pass, $emergency, $intracompany, $mohsilence);
2448 }
2449
2450 function core_routing_del($name) {
2451   global $db;
2452   $sql = "DELETE FROM extensions WHERE context = 'outrt-".$name."'";
2453   $result = $db->query($sql);
2454   if(DB::IsError($result)) {
2455     die_freepbx($result->getMessage());
2456   }
2457  
2458   $sql = "DELETE FROM extensions WHERE context = 'outbound-allroutes' AND application = 'outrt-".$name."' ";
2459   $result = $db->query($sql);
2460   if(DB::IsError($result)) {
2461     die_freepbx($result->getMessage());
2462   }
2463  
2464   return $result;
2465 }
2466
2467 function core_routing_rename($oldname, $newname) {
2468   global $db;
2469
2470   $route_prefix=substr($oldname,0,4);
2471   $newname=$route_prefix.$newname;
2472   $sql = "SELECT context FROM extensions WHERE context = 'outrt-".$newname."'";
2473   $results = $db->getAll($sql);
2474   if (count($results) > 0) {
2475     // there's already a route with this name
2476     return false;
2477   }
2478  
2479   $sql = "UPDATE extensions SET context = 'outrt-".$newname."' WHERE context = 'outrt-".$oldname."'";
2480   $result = $db->query($sql);
2481   if(DB::IsError($result)) {
2482     die_freepbx($result->getMessage());
2483   }
2484         $mypriority=sprintf("%d",$route_prefix); 
2485   $sql = "UPDATE extensions SET application = 'outrt-".$newname."', priority = '$mypriority' WHERE context = 'outbound-allroutes' AND application = 'outrt-".$oldname."' ";
2486   $result = $db->query($sql);
2487   if(DB::IsError($result)) {
2488     die_freepbx($result->getMessage());
2489   }
2490  
2491   return true;
2492 }
2493
2494 //get unique outbound route patterns for a given context
2495 function core_routing_getroutepatterns($route) {
2496   global $db;
2497   $sql = "SELECT extension, args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk%' OR args LIKE'dialout-enum%') ORDER BY extension ";
2498   $results = $db->getAll($sql);
2499   if(DB::IsError($results)) {
2500     die_freepbx($results->getMessage());
2501   }
2502  
2503   $patterns = array();
2504   foreach ($results as $row) {
2505     if ($row[0][0] == "_") {
2506       // remove leading _
2507       $pattern = substr($row[0],1);
2508     } else {
2509       $pattern = $row[0];
2510     }
2511    
2512     if (preg_match("/{EXTEN:(\d+)}/", $row[1], $matches)) {
2513       // this has a digit offset, we need to insert a |
2514       $pattern = substr($pattern,0,$matches[1])."|".substr($pattern,$matches[1]);
2515     }
2516    
2517     $patterns[] = $pattern;
2518   }
2519   return array_unique($patterns);
2520 }
2521
2522 //get unique outbound route trunks for a given context
2523 function core_routing_getroutetrunks($route) {
2524   global $db;
2525   $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) ";
2526   $results = $db->getAll($sql);
2527   if(DB::IsError($results)) {
2528     die_freepbx($results->getMessage());
2529   }
2530  
2531   $trunks = array();
2532   foreach ($results as $row) {
2533     if (preg_match('/^dialout-trunk,(\d+)/', $row[0], $matches)) {
2534       // check in_array -- even though we did distinct
2535       // we still might get ${EXTEN} and ${EXTEN:1} if they used | to split a pattern
2536       if (!in_array("OUT_".$matches[1], $trunks)) {
2537         $trunks[] = "OUT_".$matches[1];
2538       }
2539     } else if (preg_match('/^dialout-enum,(\d+)/', $row[0], $matches)) {
2540       if (!in_array("OUT_".$matches[1], $trunks)) {
2541         $trunks[] = "OUT_".$matches[1];
2542       }
2543     }
2544   }
2545   return $trunks;
2546 }
2547
2548
2549 //get password for this route
2550 function core_routing_getroutepassword($route) {
2551   global $db;
2552   $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) ";
2553   $results = $db->getOne($sql);
2554   if(DB::IsError($results)) {
2555     die_freepbx($results->getMessage());
2556   }
2557   if (preg_match('/^.*,.*,.*,(\d+|\/\S+)/', $results, $matches)) {
2558     $password = $matches[1];
2559   } else {
2560     $password = "";
2561   }
2562  
2563   return $password;
2564 }
2565
2566 //get emergency state for this route
2567 function core_routing_getrouteemergency($route) {
2568   global $db;
2569   $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'EMERGENCYROUTE%') ";
2570   $results = $db->getOne($sql);
2571   if(DB::IsError($results)) {
2572     die_freepbx($results->getMessage());
2573   }
2574   if (preg_match('/^.*=(.*)/', $results, $matches)) {
2575     $emergency = $matches[1];
2576   } else {
2577     $emergency = "";
2578   }
2579  
2580   return $emergency;
2581 }
2582
2583 //get intracompany routing status for this route
2584 function core_routing_getrouteintracompany($route) {
2585
2586        global $db;
2587        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'INTRACOMPANYROUTE%') ";
2588        $results = $db->getOne($sql);
2589        if(DB::IsError($results)) {
2590                die_freepbx($results->getMessage());
2591        }
2592        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2593                $intracompany = $matches[1];
2594        } else {
2595                $intracompany = "";
2596        }
2597        return $intracompany;
2598 }
2599
2600 //get mohsilence routing status for this route
2601 function core_routing_getroutemohsilence($route) {
2602
2603        global $db;
2604        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'MOHCLASS%') ";
2605        $results = $db->getOne($sql);
2606        if(DB::IsError($results)) {
2607                die_freepbx($results->getMessage());
2608        }
2609        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2610                $mohsilence = $matches[1];
2611        } else {
2612                $mohsilence = "";
2613        }
2614        return $mohsilence;
2615 }
2616
2617 function general_get_zonelist() {
2618   return array(
2619  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"),
2620  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"),
2621  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"),
2622  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"),
2623  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"),
2624  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"),
2625  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"),
2626  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"),
2627  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"),
2628  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"),
2629  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"),
2630  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"),
2631  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"),
2632  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"),
2633  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"),
2634  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"),
2635  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"),
2636  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"),
2637  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"),
2638  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"),
2639  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"),
2640  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"),
2641  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"),
2642  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"),
2643  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"),
2644  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"),
2645  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"),
2646  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"),
2647  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"),
2648  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"),
2649  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"),
2650  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"),
2651  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"),
2652  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"),
2653  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"),);
2654 }
2655
2656 function general_display_zones($curzone) {
2657   $zonelist = general_get_zonelist();
2658   echo "<select name='TONEZONE'>\n";
2659   foreach ($zonelist as $zone) {
2660     if ($zone['iso'] == $curzone)
2661       echo "<option selected value='{$zone['iso']}'>{$zone['name']}</option>\n";
2662     else 
2663       echo "<option value='{$zone['iso']}'>{$zone['name']}</option>\n";
2664   }
2665   echo "</select>";
2666  
2667 }
2668
2669 function general_generate_indications() {
2670   global $db;
2671   global $asterisk_conf;
2672
2673   $sql = "SELECT value FROM globals WHERE variable='TONEZONE'";
2674   $result = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2675
2676   $filename = isset($asterisk_conf["astetcdir"]) && $asterisk_conf["astetcdir"] != '' ? rtrim($asterisk_conf["astetcdir"],DIRECTORY_SEPARATOR) : "/etc/asterisk";
2677   $filename .= "/indications.conf";
2678   $fd = fopen($filename, "w");
2679   fwrite($fd, "[general]\ncountry=".$result['value']."\n\n");
2680
2681   $zonelist = general_get_zonelist();
2682   foreach ($zonelist as $zone) {
2683     fwrite($fd, "[{$zone['iso']}]\n{$zone['conf']}\n\n");
2684   }
2685   fclose($fd);
2686 }
2687 /* end page.routing.php functions */
2688
2689
2690
2691 // init registered 'your' config load and config process functions
2692 function core_users_configpageinit($dispnum) {
2693   global $currentcomponent;
2694   global $amp_conf;
2695
2696   if ( $dispnum == 'users' || $dispnum == 'extensions' ) {
2697     // Setup option list we need
2698     $currentcomponent->addoptlistitem('recordoptions', 'Adhoc', _("On Demand"));
2699     $currentcomponent->addoptlistitem('recordoptions', 'Always', _("Always"));
2700     $currentcomponent->addoptlistitem('recordoptions', 'Never', _("Never"));
2701     $currentcomponent->setoptlistopts('recordoptions', 'sort', false);
2702
2703     $currentcomponent->addoptlistitem('faxdetecttype', '0', _("None"));
2704     $currentcomponent->addoptlistitem('faxdetecttype', '1', 'Zaptel');
2705     $currentcomponent->addoptlistitem('faxdetecttype', '2', 'NVFax');
2706     $currentcomponent->setoptlistopts('faxdetecttype', 'sort', false);
2707
2708     $currentcomponent->addoptlistitem('privyn', '0', _("No"));
2709     $currentcomponent->addoptlistitem('privyn', '1', _("Yes"));
2710     $currentcomponent->setoptlistopts('privyn', 'sort', false);
2711
2712     $currentcomponent->addoptlistitem('callwaiting', 'enabled', _("Enable"));
2713     $currentcomponent->addoptlistitem('callwaiting', 'disabled', _("Disable"));
2714     $currentcomponent->setoptlistopts('callwaiting', 'sort', false);
2715
2716     $currentcomponent->addoptlistitem('ringtime', '0', 'Default');
2717     for ($i=1; $i <= 120; $i++) {
2718       $currentcomponent->addoptlistitem('ringtime', "$i", "$i");
2719     }
2720     $currentcomponent->setoptlistopts('ringtime', 'sort', false);
2721
2722     $currentcomponent->addoptlistitem('faxdestoptions', 'default', _("FreePBX default"));
2723     $currentcomponent->addoptlistitem('faxdestoptions', 'disabled', _("disabled"));
2724     $currentcomponent->addoptlistitem('faxdestoptions', 'system', _("system"));
2725     $currentcomponent->setoptlistopts('faxdestoptions', 'sort', false);
2726
2727     if (function_exists('music_list')) {
2728         $tresults = music_list($amp_conf['ASTVARLIBDIR']."/mohmp3");
2729         if (isset($tresults[0])) {
2730       foreach ($tresults as $tresult) {
2731           $currentcomponent->addoptlistitem('mohclass', $tresult, $tresult);
2732       }
2733         $currentcomponent->setoptlistopts('mohclass', 'sort', false);
2734         }
2735     }
2736
2737     //get unique devices to finishoff faxdestoptions list
2738     $devices = core_devices_list();
2739     if (isset($devices)) {
2740       foreach ($devices as $device) {
2741         $currentcomponent->addoptlistitem('faxdestoptions', $device[0], "$device[1] <$device[0]>");
2742       }
2743     }
2744
2745     // Add the 'proces' functions
2746     $currentcomponent->addguifunc('core_users_configpageload');
2747     // Ensure users is called in middle order ($sortorder = 5), this is to allow
2748     // other modules to call stuff before / after the processing of users if needed
2749     // e.g. Voicemail module needs to create mailbox BEFORE the users as the mailbox
2750     // context is needed by the add users function
2751     $currentcomponent->addprocessfunc('core_users_configprocess', 5);     
2752   }
2753 }
2754
2755 function core_users_configpageload() {
2756   global $currentcomponent;
2757   global $amp_conf;
2758
2759   // Ensure variables possibly extracted later exist
2760   $name = $directdid = $didalert = $outboundcid = $answer = null;
2761   $record_in = $record_out = $faxexten = $faxemail = $mohclass = $sipname = $cid_masquerade = null;
2762
2763   // Init vars from $_REQUEST[]
2764   $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
2765   $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
2766   $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
2767   $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
2768
2769   if ( $action == 'del' ) { // Deleted
2770
2771     $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
2772
2773   } elseif ( $display == 'extensions' && ($extdisplay == '' && $tech_hardware == '') ) { // Adding
2774
2775     // do nothing as you want the Devices to handle this bit
2776
2777   } else {
2778
2779     $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
2780  
2781     if ( is_string($extdisplay) ) {
2782       $extenInfo=core_users_get($extdisplay);
2783       extract($extenInfo);
2784       if (isset($deviceInfo) && is_array($deviceInfo))
2785         extract($deviceInfo);
2786  
2787       if ( $display == 'extensions' ) {
2788         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Extension").": $extdisplay", false), 0);
2789         $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Extension")." $extdisplay", $delURL, true, false), 0);
2790       } else {
2791         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("User").": $extdisplay", false), 0);
2792         $currentcomponent->addguielem('_top', new gui_link('del', _("Delete User")." $extdisplay", $delURL, true, false), 0);
2793       }
2794
2795     } elseif ( $display != 'extensions' ) {
2796       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add User/Extension")), 0);
2797     }
2798    
2799     // Setup vars for use in the gui later on             
2800     $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
2801     $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
2802    
2803     $msgInvalidExtNum = _("Please enter a valid extension number.");
2804     $msgInvalidCidNum = _("Please enter a valid CID Num Alias (must be a valid number).");
2805     $msgInvalidExtPwd = _("Please enter valid User Password using numbers only");
2806     $msgInvalidDispName = _("Please enter a valid Display Name");
2807     $msgInvalidOutboundCID = _("Please enter a valid Outbound CID");
2808     $msgInvalidPause = _("Please enter a valid pause time in seconds, using digits only");
2809
2810     // This is the actual gui stuff
2811     $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
2812     $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
2813    
2814     if ( $display == 'extensions' ) {
2815       $section = ($extdisplay ? _("Edit Extension") : _("Add Extension"));     
2816     } else {
2817       $section = ($extdisplay ? _("Edit User") : _("Add User"));
2818     }
2819     if ( $extdisplay ) {
2820       $currentcomponent->addguielem($section, new gui_hidden('extension', $extdisplay), 2);
2821     } else {
2822       $currentcomponent->addguielem($section, new gui_textbox('extension', $extdisplay, 'User Extension', 'The extension number to dial to reach this user.', '!isInteger()', $msgInvalidExtNum, false), 3);
2823     }
2824     if ( $display != 'extensions' ) {
2825       $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));
2826       // extra JS function check required for blank password warning -- call last in the onsubmit() function
2827       $currentcomponent->addjsfunc('onsubmit()', "\treturn checkBlankUserPwd();\n", 9);
2828     }
2829     $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));
2830     $cid_masquerade = (trim($cid_masquerade) == $extdisplay)?"":$cid_masquerade;
2831     $currentcomponent->addguielem($section, new gui_textbox('cid_masquerade', $cid_masquerade, 'CID Num Alias', 'The CID Number to user for internal calls, if different then the extension number. This is used to masquerade as a different user. A common example is a team support persons who would like their internal callerid to display the general support number (a ringgroup or queue). There will be no efffect on external calls.', '!isWhitespace() && !isInteger()', $msgInvalidCidNum, false));
2832     $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."));
2833    
2834     $section = 'Extension Options';
2835     $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);
2836     $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"));
2837     if (function_exists('music_list')) {
2838         $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));
2839     }
2840     $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));
2841     $ringtimer = (isset($ringtimer) ? $ringtimer : '0');
2842     $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));
2843     if (!isset($callwaiting)) {
2844       if ($amp_conf['ENABLECW']) {
2845         $callwaiting = 'enabled';
2846       } else {
2847         $callwaiting = 'disabled';
2848       }
2849     }
2850     $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));
2851
2852     $section = 'Recording Options';
2853     $currentcomponent->addguielem($section, new gui_selectbox('record_in', $currentcomponent->getoptlist('recordoptions'), $record_in, 'Record Incoming', "Record all inbound calls received at this extension.", false));
2854     $currentcomponent->addguielem($section, new gui_selectbox('record_out', $currentcomponent->getoptlist('recordoptions'), $record_out, 'Record Outgoing', "Record all outbound calls received at this extension.", false));
2855
2856     $section = 'Fax Handling';
2857     $wait = (isset($wait) ? $wait : '0');
2858     $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);
2859     $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"));
2860     $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));
2861     $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));
2862
2863     $section = 'Privacy';
2864     $privacyman = (isset($privacyman) ? $privacyman : '0');
2865     $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);
2866
2867   }
2868 }
2869
2870 function core_users_configprocess() {
2871   if ( !class_exists('agi_asteriskmanager') )
2872     include 'common/php-asmanager.php';
2873  
2874   //create vars from the request
2875   extract($_REQUEST);
2876  
2877   //make sure we can connect to Asterisk Manager
2878   if (!checkAstMan()) {
2879     return false;
2880   }
2881
2882   //check if the extension is within range for this user
2883   if (isset($extension) && !checkRange($extension)){
2884     echo "<script>javascript:alert('". _("Warning! Extension")." ".$extension." "._("is not allowed for your account").".');</script>";
2885   } else {
2886     //if submitting form, update database
2887     if (!isset($action)) $action = null;
2888     switch ($action) {
2889       case "add":
2890         if (core_users_add($_REQUEST)) {
2891           needreload();
2892           redirect_standard_continue();
2893         } else {
2894           // really bad hack - but if core_users_add fails, want to stop core_devices_add
2895           $GLOBALS['abort'] = true;
2896         }
2897       break;
2898       case "del":
2899         core_users_del($extdisplay);
2900         core_users_cleanastdb($extdisplay);
2901         if (function_exists('findmefollow_del')) {
2902             findmefollow_del($extdisplay);
2903         }
2904         needreload();
2905         redirect_standard_continue();
2906       break;
2907       case "edit":
2908         if (core_users_edit($extdisplay,$_REQUEST)) {
2909           needreload();
2910           redirect_standard_continue('extdisplay');
2911         } else {
2912           // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
2913           $GLOBALS['abort'] = true;
2914         }
2915       break;
2916     }
2917   }
2918   return true;
2919 }
2920
2921
2922 function core_devices_configpageinit($dispnum) {
2923   global $currentcomponent;
2924
2925   if ( $dispnum == 'devices' || $dispnum == 'extensions' ) {
2926     // Setup arrays for device types
2927     $currentcomponent->addgeneralarray('devtechs');
2928    
2929     // Some errors for the validation bits
2930     $msgInvalidDTMFMODE = _("Please enter the dtmfmode for this device");
2931     $msgInvalidChannel = _("Please enter the channel for this device");
2932     $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.\n\nAre you sure you want to leave the Secret empty?");
2933     $msgInvalidSecret = _("Please enter a Secret for this device");
2934    
2935     // zap
2936     $tmparr = array();
2937     $tmparr['channel'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidChannel);
2938     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2939     $tmparr['immediate'] = array('value' => 'no', 'level' => 1);
2940     $tmparr['signalling'] = array('value' => 'fxo_ks', 'level' => 1);
2941     $tmparr['echocancel'] = array('value' => 'yes', 'level' => 1);
2942     $tmparr['echocancelwhenbridged'] = array('value' => 'no', 'level' => 1);
2943     $tmparr['echotraining'] = array('value' => '800', 'level' => 1);
2944     $tmparr['busydetect'] = array('value' => 'no', 'level' => 1);
2945     $tmparr['busycount'] = array('value' => '7', 'level' => 1);
2946     $tmparr['callprogress'] = array('value' => 'no', 'level' => 1);
2947     $tmparr['dial'] = array('value' => '', 'level' => 1);
2948     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2949     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2950     $currentcomponent->addgeneralarrayitem('devtechs', 'zap', $tmparr);
2951     unset($tmparr);
2952    
2953     // iax2
2954     $tmparr = array();
2955     $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
2956     $tmparr['notransfer'] = array('value' => 'yes', 'level' => 1);
2957     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2958     $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
2959     $tmparr['type'] = array('value' => 'friend', 'level' => 1);
2960     $tmparr['port'] = array('value' => '4569', 'level' => 1);
2961     $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
2962     $tmparr['disallow'] = array('value' => '', 'level' => 1);
2963     $tmparr['allow'] = array('value' => '', 'level' => 1);
2964     $tmparr['dial'] = array('value' => '', 'level' => 1);
2965     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2966     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2967     $currentcomponent->addgeneralarrayitem('devtechs', 'iax2', $tmparr);
2968     unset($tmparr);
2969
2970     // sip
2971     $tmparr = array();
2972     $tmparr['secret'] = array('value' => '', 'level' => 0);
2973     $tmparr['md5secret'] = array('value' => '', 'level' => 0);
2974     $tmparr['dtmfmode'] = array('value' => 'rfc2833', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidDTMFMODE );
2975     $tmparr['canreinvite'] = array('value' => 'no', 'level' => 1);
2976     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2977     $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
2978     $tmparr['type'] = array('value' => 'friend', 'level' => 1);
2979     $tmparr['nat'] = array('value' => 'yes', 'level' => 1);
2980     $tmparr['port'] = array('value' => '5060', 'level' => 1);
2981     $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
2982     $tmparr['callgroup'] = array('value' => '', 'level' => 1);
2983     $tmparr['pickupgroup'] = array('value' => '', 'level' => 1);
2984     $tmparr['disallow'] = array('value' => '', 'level' => 1);
2985     $tmparr['allow'] = array('value' => '', 'level' => 1);
2986     $tmparr['dial'] = array('value' => '', 'level' => 1);
2987     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2988     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2989     $currentcomponent->addgeneralarrayitem('devtechs', 'sip', $tmparr);
2990     unset($tmparr);
2991
2992     // custom
2993     $tmparr = array();
2994     $tmparr['dial'] = array('value' => '', 'level' => 0);
2995     $currentcomponent->addgeneralarrayitem('devtechs', 'custom', $tmparr);
2996     unset($tmparr);
2997    
2998     // Devices list
2999     $currentcomponent->addoptlistitem('devicelist', 'sip_generic', _("Generic SIP Device"));
3000     $currentcomponent->addoptlistitem('devicelist', 'iax2_generic', _("Generic IAX2 Device"));
3001     $currentcomponent->addoptlistitem('devicelist', 'zap_generic', _("Generic ZAP Device"));
3002     $currentcomponent->addoptlistitem('devicelist', 'custom_custom', _("Other (Custom) Device"));
3003     $currentcomponent->setoptlistopts('devicelist', 'sort', false);
3004
3005
3006     // Option lists used by the gui
3007     $currentcomponent->addoptlistitem('devicetypelist', 'fixed', _("Fixed"));
3008     $currentcomponent->addoptlistitem('devicetypelist', 'adhoc', _("Adhoc"));
3009     $currentcomponent->setoptlistopts('devicetypelist', 'sort', false);
3010    
3011     $currentcomponent->addoptlistitem('deviceuserlist', 'none', _("none"));
3012     $currentcomponent->addoptlistitem('deviceuserlist', 'new', _("New User"));
3013     $users = core_users_list();
3014     if (isset($users)) {
3015       foreach ($users as $auser) {
3016         $currentcomponent->addoptlistitem('deviceuserlist', $auser[0], $auser[0]);
3017       }
3018     }
3019     $currentcomponent->setoptlistopts('deviceuserlist', 'sort', false);
3020
3021     // Add the 'proces' functions
3022     $currentcomponent->addguifunc('core_devices_configpageload');
3023     $currentcomponent->addprocessfunc('core_devices_configprocess');
3024   }
3025 }
3026
3027 function core_devices_configpageload() {
3028   global $currentcomponent;
3029
3030   // Init vars from $_REQUEST[]
3031   $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
3032   $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
3033   $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
3034   $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
3035  
3036   if ( $action == 'del' ) { // Deleted
3037
3038     if ( $display != 'extensions' )
3039       $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
3040
3041   } elseif ( $extdisplay == '' && $tech_hardware == '' ) { // Adding
3042
3043     if ( $display != 'extensions') {
3044       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add Device")), 0);
3045     } else {
3046       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add an Extension")), 0);
3047     }
3048     $currentcomponent->addguielem('_top', new gui_label('instructions', _("Please select your Device below then click Submit")));
3049     $currentcomponent->addguielem('Device', new gui_selectbox('tech_hardware', $currentcomponent->getoptlist('devicelist'), '', 'Device', '', false));
3050
3051   } else {
3052
3053     $deviceInfo = array();
3054     if ( $extdisplay ) { // Editing
3055
3056       $deviceInfo = core_devices_get($extdisplay);
3057
3058       if ( $display != 'extensions' ) {
3059         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Device").": $extdisplay", false), 0);
3060
3061         $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
3062         $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Device")." $extdisplay", $delURL, true, false), 0);
3063       }
3064  
3065     } else {
3066
3067       $tmparr = explode('_', $tech_hardware);
3068       $deviceInfo['tech'] = $tmparr[0];
3069       $deviceInfo['hardware'] = $tmparr[1];
3070       unset($tmparr);
3071      
3072       if ( $display != 'extensions' ) {
3073         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Device")), 0);
3074       } else {
3075         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Extension")), 0);
3076       }
3077
3078     }
3079
3080     // Ensure they exist before the extract
3081     $devinfo_description = $devinfo_emergency_cid = null;
3082     $devinfo_devicetype = $devinfo_user = $devinfo_hardware = null;
3083     if ( is_array($deviceInfo) )
3084       extract($deviceInfo, EXTR_PREFIX_ALL, 'devinfo');
3085
3086     // Setup vars for use in the gui later on             
3087     $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
3088     $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
3089
3090     $msgInvalidDevID = _("Please enter a device id.");
3091     $msgInvalidDevDesc = _("Please enter a valid Description for this device");
3092     $msgInvalidEmergCID = _("Please enter a valid Emergency CID");
3093     $msgInvalidExtNum = _("Please enter a valid extension number.");
3094    
3095     // Actual gui
3096     $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
3097     $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
3098
3099     if ( $display != 'extensions' ) {
3100       $section = 'Device Info';
3101       if ( $extdisplay ) { // Editing
3102         $currentcomponent->addguielem($section, new gui_hidden('deviceid', $extdisplay));
3103       } else { // Adding
3104         $currentcomponent->addguielem($section, new gui_textbox('deviceid', $extdisplay, 'Device ID', 'Give your device a unique integer ID.  The device will use this ID to authenicate to the system.', '!isInteger()', $msgInvalidDevID, false));
3105       }
3106       $currentcomponent->addguielem($section, new gui_textbox('description', $devinfo_description, 'Description', 'The caller id name for this device will be set to this description until it is logged into.', '!isAlphanumeric() || isWhitespace()', $msgInvalidDevDesc, false));
3107       $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, 'Emergency CID', 'This caller id will always be set when dialing out an Outbound Route flagged as Emergency.  The Emergency CID overrides all other caller id settings.', '!isCallerID()', $msgInvalidEmergCID));
3108       $currentcomponent->addguielem($section, new gui_selectbox('devicetype', $currentcomponent->getoptlist('devicetypelist'), $devinfo_devicetype, 'Device Type', _("Devices can be fixed or adhoc. Fixed devices are always associated to the same extension/user. Adhoc devices can be logged into and logged out of by users.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), false));
3109       $currentcomponent->addguielem($section, new gui_selectbox('deviceuser', $currentcomponent->getoptlist('deviceuserlist'), $devinfo_user, 'Default User', 'Fixed devices will always mapped to this user.  Adhoc devices will be mapped to this user by default.<br><br>If selecting "New User", a new User Extension of the same Device ID will be set as the Default User.', false));
3110     } else {
3111       $section = 'Extension Options';
3112       $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, 'Emergency CID', 'This caller id will always be set when dialing out an Outbound Route flagged as Emergency.  The Emergency CID overrides all other caller id settings.', '!isCallerID()', $msgInvalidEmergCID));
3113     }
3114     $currentcomponent->addguielem($section, new gui_hidden('tech', $devinfo_tech));
3115     $currentcomponent->addguielem($section, new gui_hidden('hardware', $devinfo_hardware));
3116
3117     $section = 'Device Options';
3118     $currentcomponent->addguielem($section, new gui_label('techlabel', sprintf(_("This device uses %s technology."),$devinfo_tech)),4);
3119     $devopts = $currentcomponent->getgeneralarrayitem('devtechs', $devinfo_tech);
3120     foreach ($devopts as $devopt=>$devoptarr) {
3121       $devopname = 'devinfo_'.$devopt;
3122       $devoptcurrent = isset($$devopname) ? $$devopname : $devoptarr['value'];
3123       $devoptjs = isset($devoptarr['jsvalidation']) ? $devoptarr['jsvalidation'] : '';
3124       $devoptfailmsg = isset($devoptarr['failvalidationmsg']) ? $devoptarr['failvalidationmsg'] : '';
3125      
3126       if ( $devoptarr['level'] == 0 || ($extdisplay && $devoptarr['level'] == 1) ) { // editing to show advanced as well
3127         $currentcomponent->addguielem($section, new gui_textbox($devopname, $devoptcurrent, $devopt, '', $devoptjs, $devoptfailmsg), 4);
3128       } else { // add so only basic
3129         $currentcomponent->addguielem($section, new gui_hidden($devopname, $devoptcurrent), 4);
3130       }
3131     }
3132   }
3133 }
3134
3135 function core_devices_configprocess() {
3136   if ( !class_exists('agi_asteriskmanager') )
3137     include 'common/php-asmanager.php';
3138
3139   //make sure we can connect to Asterisk Manager
3140   if (!checkAstMan()) {
3141     return false;
3142   }
3143  
3144   //create vars from the request
3145   extract($_REQUEST);
3146
3147   $extension = isset($extension)?$extension:null;
3148   $deviceid = isset($deviceid)?$deviceid:null;
3149   $name = isset($name)?$name:null;
3150   $action = isset($action)?$action:null;
3151
3152   // fixed users only in extensions mode
3153   if ( $display == 'extensions' ) {
3154     $devicetype = 'fixed';
3155     $deviceid = $deviceuser = $extension;
3156         $description = $name;
3157   }
3158  
3159   //if submitting form, update database
3160   switch ($action) {
3161     case "add":
3162     // really bad hack - but if core_users_add fails, want to stop core_devices_add
3163     if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3164       if (core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid)) {
3165         needreload();
3166         if ($deviceuser != 'new') {
3167           redirect_standard_continue();
3168         }
3169       }
3170     }
3171     break;
3172     case "del":
3173       core_devices_del($extdisplay);
3174       needreload();
3175       redirect_standard_continue();
3176     break;
3177     case "edit":  //just delete and re-add
3178       // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
3179       if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3180         core_devices_del($extdisplay);
3181         core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid);
3182         needreload();
3183         redirect_standard_continue('extdisplay');
3184       }
3185       break;
3186       case "resetall":  //form a url with this option to nuke the AMPUSER & DEVICE trees and start over.
3187         core_users2astdb();
3188         core_devices2astdb();
3189       break;
3190   }
3191   return true;
3192 }
3193
3194 ?>