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

Revision 5563, 176.1 kB (checked in by p_lindheimer, 5 years ago)

#2560 - convert iax notransfer to transfer in 1.4+; ad blindxfer, atxfer and automon to featurecode admin panel

  • Property svn:mime-type set to text/plain
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2
3 class core_conf {
4   var $_sip_general    = array();
5   var $_iax_general    = array();
6   var $_featuregeneral = array();
7   var $_featuremap     = array();
8   var $_applicationmap = array();
9   // return an array of filenames to write
10   function get_filename() {
11     $files = array(
12       'sip_additional.conf',
13       'sip_registrations.conf',
14       'iax_additional.conf',
15       'iax_registrations.conf',
16       'zapata_additional.conf',
17       'sip_general_additional.conf',
18       'iax_general_additional.conf',
19       'features_general_additional.conf',
20       'features_applicationmap_additional.conf',
21       'features_featuremap_additional.conf',
22       );
23     return $files;
24   }
25  
26   // return the output that goes in each of the files
27   function generateConf($file) {
28     global $version;
29
30     switch ($file) {
31       case 'sip_general_additional.conf':
32         return $this->generate_sip_general_additional($version);
33         break;
34       case 'sip_additional.conf':
35         return $this->generate_sip_additional($version);
36         break;
37       case 'sip_registrations.conf':
38         return $this->generate_sip_registrations($version);
39         break;
40       case 'iax_general_additional.conf':
41         return $this->generate_iax_general_additional($version);
42         break;
43       case 'iax_additional.conf':
44         return $this->generate_iax_additional($version);
45         break;
46       case 'iax_registrations.conf':
47         return $this->generate_iax_registrations($version);
48         break;
49       case 'zapata_additional.conf':
50         return $this->generate_zapata_additional($version);
51         break;
52       case 'features_general_additional.conf':
53         return $this->generate_featuregeneral_additional($version);
54         break;
55       case 'features_applicationmap_additional.conf':
56         return $this->generate_applicationmap_additional($version);
57         break;
58       case 'features_featuremap_additional.conf':
59         return $this->generate_featuremap_additional($version);
60         break;
61     }
62   }
63
64   function addSipGeneral($key, $value) {
65     $this->_sip_general[] = array('key' => $key, 'value' => $value);
66   }
67
68   function generate_sip_general_additional($ast_version) {
69     $output = '';
70
71     if (isset($this->_sip_general) && is_array($this->_sip_general)) {
72       foreach ($this->_sip_general as $values) {
73         $output .= $values['key']."=".$values['value']."\n";
74       }
75     }
76     return $output;
77   }
78
79   function addIaxGeneral($key, $value) {
80     $this->_iax_general[] = array('key' => $key, 'value' => $value);
81   }
82
83   function generate_iax_general_additional($ast_version) {
84     $output = '';
85
86     if (isset($this->_iax_general) && is_array($this->_iax_general)) {
87       foreach ($this->_iax_general as $values) {
88         $output .= $values['key']."=".$values['value']."\n";
89       }
90     }
91     return $output;
92   }
93
94   function addFeatureGeneral($key, $value) {
95     $this->_featuregeneral[] = array('key' => $key, 'value' => $value);
96   }
97
98   function generate_featuregeneral_additional($ast_version) {
99     $output = '';
100
101     if (isset($this->_featuregeneral) && is_array($this->_featuregeneral)) {
102       foreach ($this->_featuregeneral as $values) {
103         $output .= $values['key']."=".$values['value']."\n";
104       }
105     }
106     return $output;
107   }
108
109   function addFeatureMap($key, $value) {
110     $this->_featuremap[] = array('key' => $key, 'value' => $value);
111   }
112
113   function generate_featuremap_additional($ast_version) {
114     $output = '';
115
116     if (isset($this->_featuremap) && is_array($this->_featuremap)) {
117       foreach ($this->_featuremap as $values) {
118         $output .= $values['key']."=".$values['value']."\n";
119       }
120     }
121     return $output;
122   }
123
124   function addApplicationMap($key, $value) {
125     $this->_applicationmap[] = array('key' => $key, 'value' => $value);
126   }
127
128   function generate_applicationmap_additional($ast_version) {
129     $output = '';
130
131     if (isset($this->_applicationmap) && is_array($this->_applicationmap)) {
132       foreach ($this->_applicationmap as $values) {
133         $output .= $values['key']."=".$values['value']."\n";
134       }
135     }
136     return $output;
137   }
138
139   function generate_sip_additional($ast_version) {
140     global $db;
141
142     $table_name = "sip";
143     $additional = "";
144     $output = "";
145
146     // Asterisk 1.4 requires call-limit be set for hints to work properly
147     //
148     if (version_compare($ast_version, "1.4", "ge")) {
149       $call_limit = "call-limit=50\n";
150     } else {
151       $call_limit = "";
152     }
153
154     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
155     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
156     if(DB::IsError($results)) {
157       die($results->getMessage());
158     }
159     foreach ($results as $result) {
160       $additional .= $result['keyword']."=".$result['data']."\n";
161     }
162
163     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
164     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
165     if(DB::IsError($results)) {
166       die($results->getMessage());
167     }
168
169     foreach ($results as $result) {
170       $account = $result['data'];
171       $id = $result['id'];
172       $output .= "[$account]\n";
173  
174       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
175       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
176       if(DB::IsError($results2)) {
177         die($results2->getMessage());
178       }
179       foreach ($results2 as $result2) {
180         $options = explode("&", $result2['data']);
181         foreach ($options as $option) {
182           $output .= $result2['keyword']."=$option\n";
183         }
184       }
185       if ($call_limit && ($id < 999900)) {
186         $output .= $call_limit;
187       }
188       $output .= $additional."\n";
189     }
190     return $output;
191   }
192
193   function generate_sip_registrations($ast_version) {
194     global $db;
195
196     $table_name = "sip";
197     $output = "";
198
199     // items with id like 9999999% get put in registrations file
200     //
201     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
202     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
203     if(DB::IsError($results)) {
204       die($results->getMessage());
205     }
206
207     foreach ($results as $result) {
208       $output .= $result['keyword']."=".$result['data']."\n";
209     }
210
211     return $output;
212   }
213
214   function generate_iax_additional($ast_version) {
215     global $db;
216
217     $table_name = "iax";
218     $additional = "";
219     $output = "";
220
221     $ver12 = version_compare($ast_version, '1.4', 'lt');
222
223     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
224     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
225     if(DB::IsError($results)) {
226       die($results->getMessage());
227     }
228     foreach ($results as $result) {
229       if ($ver12) {
230         $additional .= $result['keyword']."=".$result['data']."\n";
231       } else {
232         $option = $result['data'];
233         switch ($result['keyword']) {
234           case 'notransfer':
235             if (strtolower($option) == 'yes') {
236               $additional .= "transfer=no\n";
237             } else if (strtolower($option) == 'no') {
238               $additional .= "transfer=yes\n";
239             } else if (strtolower($option) == 'mediaonly') {
240               $additional .= "transfer=mediaonly\n";
241             } else {
242               $additional .= $result['keyword']."=$option\n";
243             }
244             break;
245           default:
246             $additional .= $result['keyword']."=$option\n";
247         }
248       }
249     }
250
251     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
252     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
253     if(DB::IsError($results)) {
254       die($results->getMessage());
255     }
256
257     foreach ($results as $result) {
258       $account = $result['data'];
259       $id = $result['id'];
260       $output .= "[$account]\n";
261  
262       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
263       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
264       if(DB::IsError($results2)) {
265         die($results2->getMessage());
266       }
267       foreach ($results2 as $result2) {
268         $options = explode("&", $result2['data']);
269         if ($ver12) {
270           foreach ($options as $option) {
271             $output .= $result2['keyword']."=$option\n";
272           }
273         } else {
274           foreach ($options as $option) {
275             switch ($result2['keyword']) {
276               case 'notransfer':
277                 if (strtolower($option) == 'yes') {
278                   $output .= "transfer=no\n";
279                 } else if (strtolower($option) == 'no') {
280                   $output .= "transfer=yes\n";
281                 } else if (strtolower($option) == 'mediaonly') {
282                   $output .= "transfer=mediaonly\n";
283                 } else {
284                   $output .= $result2['keyword']."=$option\n";
285                 }
286                 break;
287               default:
288                 $output .= $result2['keyword']."=$option\n";
289             }
290           }
291         }
292       }
293       $output .= $additional."\n";
294     }
295     return $output;
296   }
297
298   function generate_iax_registrations($ast_version) {
299     global $db;
300
301     $table_name = "iax";
302     $output = "";
303
304     // items with id like 9999999% get put in the registration file
305     //
306     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
307     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
308     if(DB::IsError($results)) {
309       die($results->getMessage());
310     }
311
312     foreach ($results as $result) {
313       $output .= $result['keyword']."=".$result['data']."\n";
314     }
315
316     return $output;
317   }
318
319   function generate_zapata_additional($ast_version) {
320     global $db;
321
322     $table_name = "zap";
323
324     $additional = "";
325     $output = '';
326
327     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
328     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
329     if(DB::IsError($results)) {
330       die($results->getMessage());
331     }
332     foreach ($results as $result) {
333       $additional .= $result['keyword']."=".$result['data']."\n";
334     }
335
336     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
337     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
338     if(DB::IsError($results)) {
339       die($results->getMessage());
340     }
341
342     foreach ($results as $result) {
343       $account = $result['data'];
344       $id = $result['id'];
345       $output .= ";;;;;;[$account]\n";
346  
347       $sql = "SELECT keyword,data from $table_name where id=$id and keyword <> 'account' and flags <> 1 order by keyword DESC";
348       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
349       if(DB::IsError($results2)) {
350         die($results2->getMessage());
351       }
352       $zapchannel="";
353       foreach ($results2 as $result2) {
354         if ($result2['keyword'] == 'channel') {
355           $zapchannel = $result2['data'];
356         } else {
357           $output .= $result2['keyword']."=".$result2['data']."\n";
358         }
359       }
360       $output .= "channel=>$zapchannel\n";
361       $output .= $additional."\n";
362     }
363     return $output;
364   }
365 }
366
367 // The destinations this module provides
368 // returns a associative arrays with keys 'destination' and 'description'
369 function core_destinations() {
370   //static destinations
371   $extens = array();
372   $category = 'Terminate Call';
373   $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category);
374   $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category);
375   $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category);
376   $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category);
377   $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category);
378   $extens[] = array('destination' => 'app-blackhole,ring,1', 'description' => 'Play ringtones to caller until they hangup', 'category' => $category);
379  
380   //get the list of meetmes
381   $results = core_users_list();
382  
383   if (isset($results) && function_exists('voicemail_getVoicemail')) {
384     //get voicemail
385     $uservm = voicemail_getVoicemail();
386     $vmcontexts = array_keys($uservm);
387     foreach ($results as $thisext) {
388       $extnum = $thisext[0];
389       // search vm contexts for this extensions mailbox
390       foreach ($vmcontexts as $vmcontext) {
391         if(isset($uservm[$vmcontext][$extnum])){
392           //$vmname = $uservm[$vmcontext][$extnum]['name'];
393           //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>');
394           $vmboxes[$extnum] = true;
395         }
396       }
397     }
398   }
399  
400   // return an associative array with destination and description
401   // core provides both users and voicemail boxes as destinations
402   if (isset($results)) {
403     foreach($results as $result) {
404       $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions');
405       if(isset($vmboxes[$result['0']])) {
406         $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail');
407         $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail');
408         $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail');
409       }
410     }
411   }
412  
413   if (isset($extens))
414     return $extens;
415   else
416     return null;
417 }
418
419 function core_getdest($exten) {
420   $dests[] = 'from-did-direct,'.$exten.',1';
421   if (!function_exists('voicemail_mailbox_get')) {
422     return $dests;
423   }
424   $box = voicemail_mailbox_get($exten);
425   if ($box == null) {
426     return $dests;
427   }
428   $dests[] = 'ext-local,vmb'.$exten.',1';
429   $dests[] = 'ext-local,vmu'.$exten.',1';
430   $dests[] = 'ext-local,vms'.$exten.',1';
431
432   return $dests;
433 }
434
435 function core_getdestinfo($dest) {
436   global $active_modules;
437
438   // Check for Extension Number Destinations
439   //
440   if (substr(trim($dest),0,16) == 'from-did-direct,') {
441     $exten = explode(',',$dest);
442     $exten = $exten[1];
443     $thisexten = core_users_get($exten);
444     if (empty($thisexten)) {
445       return array();
446     } else {
447       //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
448       $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
449       return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
450                    'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
451                   );
452     }
453
454   // Check for voicemail box destinations
455   //
456   } else if (substr(trim($dest),0,12) == 'ext-local,vm') {
457     $exten = explode(',',$dest);
458     $exten = substr($exten[1],3);
459     if (!function_exists('voicemail_mailbox_get')) {
460       return array();
461     }
462     $thisexten = core_users_get($exten);
463     if (empty($thisexten)) {
464       return array();
465     }
466     $box = voicemail_mailbox_get($exten);
467     if ($box == null) {
468       return array();
469     }
470     $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
471     return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
472                  'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
473                 );
474
475   // Check for blackhole Termination Destinations
476   //
477   } else if (substr(trim($dest),0,14) == 'app-blackhole,') {
478     $exten = explode(',',$dest);
479     $exten = $exten[1];
480
481     switch ($exten) {
482       case 'hangup':
483         $description = 'Hangup';
484         break;
485       case 'congestion':
486         $description = 'Congestion';
487         break;
488       case 'busy':
489         $description = 'Busy';
490         break;
491       case 'zapateller':
492         $description = 'Play SIT Tone (Zapateller)';
493         break;
494       case 'musiconhold':
495         $description = 'Put caller on hold forever';
496         break;
497       case 'ring':
498         $description = 'Play ringtones to caller';
499         break;
500       default:
501         $description = false;
502     }
503     if ($description) {
504       return array('description' => 'Core: '.$description,
505                    'edit_url' => false,
506                    );
507     } else {
508       return array();
509     }
510
511   // None of the above, so not one of ours
512   //
513   } else {
514     return false;
515   }
516 }
517 /*  Generates dialplan for "core" components (extensions & inbound routing)
518   We call this with retrieve_conf
519 */
520 function core_get_config($engine) {
521   global $ext;  // is this the best way to pass this?
522   global $version;  // this is not the best way to pass this, this should be passetd together with $engine
523   global $amp_conf;
524   global $core_conf;
525
526   $modulename = "core";
527  
528   switch($engine) {
529     case "asterisk":
530
531       // Now add to sip_general_addtional.conf
532       //
533       if (isset($core_conf) && is_a($core_conf, "core_conf")) {
534         $core_conf->addSipGeneral('bindport','5060');
535         $core_conf->addSipGeneral('bindaddr','0.0.0.0');
536         $core_conf->addSipGeneral('disallow','all');
537         $core_conf->addSipGeneral('allow','ulaw');
538         $core_conf->addSipGeneral('allow','alaw');
539         $core_conf->addSipGeneral('context','from-sip-external');
540         $core_conf->addSipGeneral('callerid','Unknown');
541         $core_conf->addSipGeneral('notifyringing','yes');
542         if (version_compare($version, '1.4', 'ge')) {
543           $core_conf->addSipGeneral('notifyhold','yes');
544           $core_conf->addSipGeneral('limitonpeers','yes');
545           $core_conf->addSipGeneral('tos_sip','cs3');    // Recommended setting from doc/ip-tos.txt
546           $core_conf->addSipGeneral('tos_audio','ef');   // Recommended setting from doc/ip-tos.txt
547           $core_conf->addSipGeneral('tos_video','af41'); // Recommended setting from doc/ip-tos.txt
548         } else {
549           $core_conf->addSipGeneral('tos','0x68'); // This really doesn't do anything with astersk not running as root
550         }
551         $core_conf->addIaxGeneral('bindport','4569');
552         $core_conf->addIaxGeneral('bindaddr','0.0.0.0');
553         $core_conf->addIaxGeneral('disallow','all');
554         $core_conf->addIaxGeneral('allow','ulaw');
555         $core_conf->addIaxGeneral('allow','alaw');
556         $core_conf->addIaxGeneral('allow','gsm');
557         $core_conf->addIaxGeneral('mailboxdetail','yes');
558         if (version_compare($version, '1.4', 'ge')) {
559           $core_conf->addIaxGeneral('tos','ef'); // Recommended setting from doc/ip-tos.txt
560         }
561
562         $fcc = new featurecode($modulename, 'blindxfer');
563         $code = $fcc->getCodeActive();
564         unset($fcc);
565         if ($code != '') {
566           $core_conf->addFeatureMap('blindxfer',$code);
567         }
568
569         $fcc = new featurecode($modulename, 'atxfer');
570         $code = $fcc->getCodeActive();
571         unset($fcc);
572         if ($code != '') {
573           $core_conf->addFeatureMap('atxfer',$code);
574         }
575
576         $fcc = new featurecode($modulename, 'automon');
577         $code = $fcc->getCodeActive();
578         unset($fcc);
579         if ($code != '') {
580           $core_conf->addFeatureMap('automon',$code);
581         }
582
583         $core_conf->addFeatureMap('disconnect','**');
584       }
585
586       // FeatureCodes
587       $fcc = new featurecode($modulename, 'userlogon');
588       $fc_userlogon = $fcc->getCodeActive();
589       unset($fcc);
590
591       $fcc = new featurecode($modulename, 'userlogoff');
592       $fc_userlogoff = $fcc->getCodeActive();
593       unset($fcc);
594
595       $fcc = new featurecode($modulename, 'zapbarge');
596       $fc_zapbarge = $fcc->getCodeActive();
597       unset($fcc);
598
599       $fcc = new featurecode($modulename, 'chanspy');
600       $fc_chanspy = $fcc->getCodeActive();
601       unset($fcc);
602
603       $fcc = new featurecode($modulename, 'simu_pstn');
604       $fc_simu_pstn = $fcc->getCodeActive();
605       unset($fcc);
606
607       $fcc = new featurecode($modulename, 'simu_fax');
608       $fc_simu_fax = $fcc->getCodeActive();
609       unset($fcc);
610
611       $fcc = new featurecode($modulename, 'pickup');
612       $fc_pickup = $fcc->getCodeActive();
613       unset($fcc);
614
615       // Log on / off -- all in one context
616       if ($fc_userlogoff != '' || $fc_userlogon != '') {
617         $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal
618        
619         if ($fc_userlogoff != '') {
620           $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
621           $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup(''));
622         }
623  
624         if ($fc_userlogon != '') {
625           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
626           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
627          
628           $clen = strlen($fc_userlogon);
629           $fc_userlogon = "_$fc_userlogon.";
630           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}'));
631           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
632         }
633       }
634
635       // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
636       // when a user pushes a flashing BLF.
637       if ($fc_pickup != '') {
638         $ext->addInclude('from-internal-additional', 'app-pickup');
639         $fclen = strlen($fc_pickup);
640         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}'));
641         if (strstr($version, 'BRI'))
642           $ext->add('app-pickup', "_$fc_pickup.", '', new ext_dpickup('${EXTEN:'.$fclen.'}'));
643         else
644           $ext->add('app-pickup', "_$fc_pickup.", '', new ext_pickup('${EXTEN:'.$fclen.'}'));
645       }
646      
647      
648       // zap barge
649       if ($fc_zapbarge != '') {
650         $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal
651        
652         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
653         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}'));
654         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
655         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
656         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
657         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
658       }
659
660       // chan spy
661       if ($fc_chanspy != '') {
662         $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal
663         $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
664         $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
665         $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
666         $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
667         $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
668       }
669      
670       // Simulate options (ext-test)
671       if ($fc_simu_pstn != '' || $fc_simu_fax != '') {
672         $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal
673        
674         if ($fc_simu_pstn != '') {
675           $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
676         }
677
678         if ($fc_simu_fax != '') {
679           $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax'));
680         }
681
682         $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
683       }
684      
685       /* Always have Fax detection in ext-did, no matter what */
686       $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax'));
687
688       /* inbound routing extensions */
689       $didlist = core_did_list();
690       if(is_array($didlist)){
691         $catchall = false;
692         $catchall_context='ext-did-catchall';
693         foreach($didlist as $item) {
694           $did = core_did_get($item['extension'],$item['cidnum']);
695           $exten = $did['extension'];
696           $cidnum = $did['cidnum'];
697
698           $exten = (empty($exten)?"s":$exten);
699           $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it
700
701           $context = "ext-did";
702
703           $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
704           // always set callerID name
705           $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
706           $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
707           $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
708
709           if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
710             $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
711             $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
712           }
713
714           // If we require RINGING, signal it as soon as we enter.
715           if ($item['ringing'] === "CHECKED") {
716             $ext->add($context, $exten, '', new ext_ringing(''));
717           }
718
719           if ($exten == "s" && $context == "ext-did") { 
720             //if the exten is s, then also make a catchall for undefined DIDs
721             $catchaccount = "_.".(empty($cidnum)?"":"/".$cidnum);
722             if ($catchaccount =="_." && ! $catchall) {
723               $catchall = true;
724               $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
725               $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did'));
726             }
727           }
728          
729           if ($item['faxexten'] != "default") {
730             $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
731           }
732           if (!empty($item['faxemail'])) {
733             $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
734           }
735           if ($item['answer'] == "1") {
736             $ext->add($context, $exten, '', new ext_answer(''));
737             $ext->add($context, $exten, '', new ext_wait($item['wait']));
738           }
739           if ($item['answer'] == "2") { // NVFaxDetect
740             $ext->add($context, $exten, '', new ext_answer(''));
741             $ext->add($context, $exten, '', new ext_playtones('ring'));
742             $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
743           }
744           if ($item['privacyman'] == "1") {
745             $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
746           }
747           if (!empty($item['alertinfo'])) {
748             $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo'])));
749           }
750           // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should
751           // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different
752           // modules.
753           //
754           // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here.
755           //
756           // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX)
757           //
758           if (!empty($item['grppre'])) {
759             $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre']));
760             $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
761           }
762          
763           //the goto destination
764           // destination field in 'incoming' database is backwards from what ext_goto expects
765           $goto_context = strtok($did['destination'],',');
766           $goto_exten = strtok(',');
767           $goto_pri = strtok(',');
768           $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
769          
770         }
771         // If there's not a catchall, make one with an error message
772         if (!$catchall) {
773           $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
774           $ext->add($catchall_context, 's', '', new ext_answer(''));
775           $ext->add($catchall_context, 's', '', new ext_wait('2'));
776           $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
777           $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
778           $ext->add($catchall_context, '_[*#X].', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
779           $ext->add($catchall_context, '_[*#X].', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
780           $ext->add($catchall_context, '_[*#X].', '', new ext_goto('1','s','ext-did'));
781         }
782          
783       }
784
785       /* MODIFIED (PL)
786        *
787        * Add Direct DIDs
788        *
789        * This functions creates a new context, ext-did-direct, used to route an incoming DID directly to the specified user.
790        * The purpose is to use when a user has a personal external DID. This keeps it clean and easy to administer.
791        * Any conflict with those routes will depend on which of the two contexts are included first in the extensions.conf file.
792        *
793        * Calls are sent to context from-did-direct though this feature. You must create that context in extenions.conf or
794        * in extensions_custom.conf and it should look something like:
795        *
796        * [from-did-direct]
797        * include => ext-findmefollow
798        * include => ext-local
799        *
800        * This is so that personal ring groups are used if they exist for the direct did and if not, then the local extension.
801        * If the module is not implented, it will just go to the users extension.
802        */
803
804       $directdidlist = core_directdid_list();
805       if(is_array($directdidlist)){
806         $context = "ext-did";
807         if(!is_array($didlist)){
808           /* if not set above, add one here */
809           $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
810         }
811         foreach($directdidlist as $item) {
812           $exten = $item['directdid'];
813           $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
814           // always set callerID name
815           $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
816           $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
817           $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
818
819           if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
820             $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
821             $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
822           }
823          
824           if ($item['faxexten'] != "default") {
825             $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
826           }
827           if (!empty($item['faxemail'])) {
828             $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
829           }
830           if ($item['answer'] == "1") {
831             $ext->add($context, $exten, '', new ext_answer(''));
832             $ext->add($context, $exten, '', new ext_wait($item['wait']));
833           }
834           if ($item['answer'] == "2") { // NVFaxDetect
835             $ext->add($context, $exten, '', new ext_answer(''));
836             $ext->add($context, $exten, '', new ext_playtones('ring'));
837             $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
838           }
839           if ($item['privacyman'] == "1") {
840             $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
841           }
842
843
844           if (!empty($item['didalert'])) {
845             $ext->add($context, $exten, '', new ext_setvar("_ALERT_INFO", str_replace(';', '\;', $item['didalert'])));
846           }
847           $goto_context = 'from-did-direct';
848           $goto_exten = $item['extension'];
849           $goto_pri = 1;
850           $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
851
852         }
853       }
854
855       // Now create macro-from-zaptel-nnn for each defined channel to route it to the DID routing
856       // Send it to from-trunk so it is handled as other dids would be handled.
857       //
858       foreach (core_zapchandids_list() as $row) {
859         $channel = $row['channel'];
860         $did     = $row['did'];
861
862         $zap_context = "macro-from-zaptel-{$channel}";
863         $ext->add($zap_context, 's', '', new ext_noop('Entering '.$zap_context.' with DID = ${DID} and setting to: '.$did));
864         $ext->add($zap_context, 's', '', new ext_setvar('__FROM_DID',$did));
865         $ext->add($zap_context, 's', '', new ext_goto('1',$did,'from-trunk'));
866       }
867
868       /* user extensions */
869       $ext->addInclude('from-internal-additional','ext-local');
870
871       // If running in Dynamic mode, this will insert the hints through an Asterisk #exec call.
872       // which require "execincludes=yes" to be set in the [options] section of asterisk.conf
873       //
874       if ($amp_conf['DYNAMICHINTS']) {
875         $ext->addExec('ext-local',$amp_conf['AMPBIN'].'/generate_hints.php');
876       }
877       $userlist = core_users_list();
878       if (is_array($userlist)) {
879         foreach($userlist as $item) {
880           $exten = core_users_get($item[0]);
881           $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']);
882
883           if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0)
884             $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer']));
885          
886           $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension']));
887           $ext->add('ext-local', $exten['extension'], '', new ext_hangup(''));
888          
889           if($vm != "novm") {
890             $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',"$vm,DIRECTDIAL"));
891             $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_hangup(''));
892             $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',"$vm,BUSY"));
893             $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_hangup(''));
894             $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',"$vm,NOANSWER"));
895             $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_hangup(''));
896             $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',"$vm,NOMESSAGE"));
897             $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_hangup(''));
898           }
899            
900           // Create the hints if running in normal mode
901           //
902           if (!$amp_conf['DYNAMICHINTS']) {
903             $hint = core_hint_get($exten['extension']);
904             if (!empty($hint)) {
905               $ext->addHint('ext-local', $exten['extension'], $hint);
906             }
907           }
908           if ($exten['sipname']) {
909             $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal'));
910           }
911           // Now make a special context for the IVR inclusions of local extension dialing so that
912           // when people use the Queues breakout ability, and break out to someone's extensions, voicemail
913           // works.
914           //
915           $ivr_context = 'from-did-direct-ivr';
916           $ext->add($ivr_context, $exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
917           $ext->add($ivr_context, $exten['extension'],'', new ext_setvar('__NODEST', ''));
918           $ext->add($ivr_context, $exten['extension'],'', new ext_goto('1',$exten['extension'],'from-did-direct'));
919           if($vm != "novm") {
920             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
921             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_setvar('__NODEST', ''));
922             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_macro('vm',"$vm,DIRECTDIAL"));
923           }
924         }
925       }
926
927       // create from-trunk context for each trunk that adds counts to channels
928       //
929       $trunklist = core_trunks_list(true);
930       if (is_array($trunklist)) {
931         foreach ($trunklist as $trunkprops) {
932           if (trim($trunkprops['value']) == 'on') {
933             // value of on is disabled and for zap we don't create a context
934             continue;
935           }
936           switch ($trunkprops['tech']) {
937             case 'IAX':
938             case 'IAX2':
939             case 'SIP':
940               $trunkgroup = $trunkprops['globalvar'];
941               $trunkcontext  = "from-trunk-".$trunkprops['name'];
942               $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup));
943               $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk'));
944               break;
945             default:
946           }
947         }
948       }
949
950       /* dialplan globals */
951       // modules should NOT use the globals table to store anything!
952       // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
953       // I'm cheating for core functionality - do as I say, not as I do ;-)   
954
955       // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
956       //
957       $amp_conf_globals = array(
958         "ASTETCDIR",
959         "ASTMODDIR",
960         "ASTVARLIBDIR",
961         "ASTAGIDIR",
962         "ASTSPOOLDIR",
963         "ASTRUNDIR",
964         "ASTLOGDIR",
965         "CWINUSEBUSY",
966         "AMPMGRUSER",
967         "AMPMGRPASS"
968       );
969
970       $sql = "SELECT * FROM globals";
971       $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
972       foreach($globals as $global) {
973         $ext->addGlobal($global['variable'],$global['value']);
974
975         // now if for some reason we have a variable in the global table
976         // that is in our $amp_conf_globals list, then remove it so we
977         // don't duplicate, the sql table will take precedence
978         //
979         if (array_key_exists($global['variable'],$amp_conf_globals)) {
980           $rm_keys = array_keys($amp_conf_globals,$global['variable']);
981           foreach ($rm_keys as $index) {
982             unset($amp_conf_globals[$index]);
983           }
984         }
985       }
986       foreach ($amp_conf_globals as $global) {
987         if (isset($amp_conf[$global])) {
988           $value = $amp_conf[$global];
989           if ($value === true || $value === false) {
990             $value = ($value) ? 'true':'false';
991           }
992           $ext->addGlobal($global, $value);
993           out("Added to globals: $global = $value");
994         }
995       }
996       // Put the asterisk version in a global for agi etc.
997       $ext->addGlobal('ASTVERSION', $version);
998
999       /* outbound routes */
1000       // modules should use their own table for storage (and module_get_config() to add dialplan)
1001       // modules should NOT use the extension table to store anything!
1002       $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application";
1003       $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1004       $ext->addInclude('from-internal-additional','outbound-allroutes');
1005       $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
1006       foreach($outrts as $outrt) {
1007         $ext->addInclude('outbound-allroutes',$outrt['application']);
1008         $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC";
1009         $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1010         $lastexten = false;
1011         foreach($thisrt as $exten) {
1012           //if emergencyroute, then set channel var
1013           if(strpos($exten['args'],"EMERGENCYROUTE") !== false)
1014             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15)));
1015           if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false)
1016             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18)));
1017           // Don't set MOHCLASS if already set, threre may be a feature code that overrode it
1018           if(strpos($exten['args'],"MOHCLASS") !== false)
1019             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' ));
1020           if(strpos($exten['args'],"dialout-trunk") !== false || strpos($exten['args'],"dialout-enum") !== false) {
1021             if ($exten['extension'] !== $lastexten) {
1022
1023               // If NODEST is set, clear it. No point in remembering since dialout-trunk will just end in the
1024               // bit bucket. But if answered by an outside line with transfer capability, we want NODEST to be
1025               // clear so a subsequent transfer to an internal extension works and goes to voicmail or other
1026               // destinations.
1027               //
1028               // Then do one call to user-callerid and record-enable instead of each time as in the past
1029               //
1030               $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('user-callerid,SKIPTTL'));
1031               $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("_NODEST",""));
1032               $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('record-enable,${AMPUSER},OUT'));
1033               $lastexten = $exten['extension'];
1034             }
1035             $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
1036           }
1037           if(strpos($exten['args'],"outisbusy") !== false)
1038             $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy"));
1039         }
1040       }
1041       general_generate_indications();
1042
1043       // "blackhole" destinations
1044       $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
1045       $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
1046
1047       $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
1048       $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
1049       $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
1050       // Should hangup ?
1051       // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
1052          
1053       $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
1054       $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
1055       $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
1056
1057       $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
1058       $ext->add('app-blackhole', 'congestion', '', new ext_answer());
1059       $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
1060       $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
1061       $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
1062
1063       $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
1064       $ext->add('app-blackhole', 'busy', '', new ext_answer());
1065       $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy'));
1066       $ext->add('app-blackhole', 'busy', '', new ext_busy());
1067       $ext->add('app-blackhole', 'busy', '', new ext_hangup());
1068
1069       $ext->add('app-blackhole', 'ring', '', new ext_noop('Blackhole Dest: Ring'));
1070       $ext->add('app-blackhole', 'ring', '', new ext_answer());
1071       $ext->add('app-blackhole', 'ring', '', new ext_playtones('ring'));
1072       $ext->add('app-blackhole', 'ring', '', new ext_wait(300));
1073       $ext->add('app-blackhole', 'ring', '', new ext_hangup());
1074
1075       if ($amp_conf['AMPBADNUMBER'] !== false) {
1076         $context = 'bad-number';
1077         $exten = '_X.';
1078         $ext->add($context, $exten, '', new extension('ResetCDR()'));
1079         $ext->add($context, $exten, '', new extension('NoCDR()'));
1080         $ext->add($context, $exten, '', new ext_wait('1'));
1081         $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1082         $ext->add($context, $exten, '', new ext_wait('1'));
1083         $ext->add($context, $exten, '', new ext_congestion('20'));
1084         $ext->add($context, $exten, '', new ext_hangup());
1085
1086         $exten = '_*.';
1087         $ext->add($context, $exten, '', new extension('ResetCDR()'));
1088         $ext->add($context, $exten, '', new extension('NoCDR()'));
1089         $ext->add($context, $exten, '', new ext_wait('1'));
1090         $ext->add($context, $exten, '', new ext_playback('silence/1&feature-not-avail-line&silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1091         $ext->add($context, $exten, '', new ext_wait('1'));
1092         $ext->add($context, $exten, '', new ext_congestion('20'));
1093         $ext->add($context, $exten, '', new ext_hangup());
1094       }
1095
1096       $context = 'macro-dialout-trunk';
1097       $exten = 's';
1098      
1099       /*
1100        * dialout using a trunk, using pattern matching (don't strip any prefix)
1101        * arg1 = trunk number, arg2 = number, arg3 = route password
1102        *
1103        * MODIFIED (PL)
1104        *
1105        * Modified both Dial() commands to include the new TRUNK_OPTIONS from the general
1106        * screen of AMP
1107        */
1108       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1109       $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1110       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
1111       $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this
1112       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company
1113       $ext->add($context, $exten, '', new ext_set('GROUP()', 'OUT_${DIAL_TRUNK}'));
1114       $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
1115       $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} > ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
1116       $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));  // Set to YES if treated like internal
1117       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}'));
1118       $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
1119       $ext->add($context, $exten, 'skipoutcid', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1120       $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number
1121       $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}'));  // Custom trunks are prefixed with "AMP:"
1122    
1123       // Back to normal processing, whether intracompany or not.
1124       // But add the macro-setmusic if we don't want music on this outbound call
1125       $ext->add($context, $exten, '', new ext_gotoif('$[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]', 'gocall'));  // Set to YES if we should pump silence
1126       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', 'M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));  // set MoH or off
1127    
1128       // This macro call will always be blank and is provided as a hook for customization required prior to making a call
1129       // such as adding SIP header information or other requirements. All the channel variables from above are present
1130      
1131       $ext->add($context, $exten, 'gocall', new ext_macro('dialout-trunk-predial-hook'));
1132       $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
1133    
1134       $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
1135       $ext->add($context, $exten, '', new ext_dial('${OUT_${DIAL_TRUNK}}/${OUTNUM}', '300,${DIAL_TRUNK_OPTIONS}'));  // Regular Trunk Dial
1136       $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1137      
1138       $ext->add($context, $exten, 'customtrunk', new ext_set('pre_num', '${CUT(OUT_${DIAL_TRUNK},$,1)}'));
1139       $ext->add($context, $exten, '', new ext_set('the_num', '${CUT(OUT_${DIAL_TRUNK},$,2)}'));  // this is where we expect to find string OUTNUM
1140       $ext->add($context, $exten, '', new ext_set('post_num', '${CUT(OUT_${DIAL_TRUNK},$,3)}'));
1141       $ext->add($context, $exten, '', new ext_gotoif('$["${the_num}" = "OUTNUM"]', 'outnum', 'skipoutnum'));  // if we didn't find "OUTNUM", then skip to Dial
1142       $ext->add($context, $exten, 'outnum', new ext_set('the_num', '${OUTNUM}'));  // replace "OUTNUM" with the actual number to dial
1143       $ext->add($context, $exten, 'skipoutnum', new ext_dial('${pre_num:4}${the_num}${post_num}', '300,${DIAL_TRUNK_OPTIONS}'));
1144       $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1145      
1146       $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
1147    
1148       $exten = 's-BUSY';
1149       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
1150       $ext->add($context, $exten, '', new ext_playtones('busy'));
1151       $ext->add($context, $exten, '', new ext_busy(20));
1152    
1153       $exten = 's-NOANSWER';
1154       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
1155       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1156       $ext->add($context, $exten, '', new ext_congestion(20));
1157    
1158       $exten = 's-CANCEL';
1159       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up'));
1160       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1161       $ext->add($context, $exten, '', new ext_congestion(20));
1162    
1163       $exten = '_s-.';
1164       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport'));
1165       $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
1166       $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks'));
1167      
1168       $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
1169       $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook'));
1170    
1171       $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1172
1173
1174       /*
1175        * sets the callerid of the device to that of the logged in user
1176        *
1177        * ${AMPUSER} is set upon return to the real user despite any aliasing that may
1178        * have been set as a result of the AMPUSER/<nnn>/cidnum field. This is used by
1179        * features like DND, CF, etc. to set the proper structure on aliased instructions
1180        */
1181       $context = 'macro-user-callerid';
1182       $exten = 's';
1183      
1184       $ext->add($context, $exten, '', new ext_noop('user-callerid: ${CALLERID(name)} ${CALLERID(number)}'));
1185              
1186       // make sure AMPUSER is set if it doesn't get set below     
1187       $ext->add($context, $exten, '', new ext_set('AMPUSER', '${IF($["foo${AMPUSER}" = "foo"]?${CALLERID(number)}:${AMPUSER})}'));
1188       $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}" = "Local"]', 'report'));
1189       $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}'));
1190       $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1191       $ext->add($context, $exten, '', new ext_set('AMPUSER', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1192       $ext->add($context, $exten, '', new ext_set('AMPUSERCIDNAME', '${DB(AMPUSER/${AMPUSER}/cidname)}'));
1193       $ext->add($context, $exten, '', new ext_gotoif('$["x${AMPUSERCIDNAME:1:2}" = "x"]', 'report'));
1194
1195       // user may masquerade as a different user internally, so set the internal cid as indicated
1196       // but keep the REALCALLERID which is used to determine their true identify and lookup info
1197       // during outbound calls.
1198       $ext->add($context, $exten, '', new ext_set('AMPUSERCID', '${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}'));
1199       $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '"${AMPUSERCIDNAME}" <${AMPUSERCID}>'));
1200       $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1201       $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/language)}" != ""]', 'Set', 'LANGUAGE()=${DB(AMPUSER/${AMPUSER}/language)}'));
1202       $ext->add($context, $exten, 'report', new ext_noop('TTL: ${TTL} ARG1: ${ARG1}'));
1203       $ext->add($context, $exten, '', new ext_gotoif('$[ "${ARG1}" = "SKIPTTL" ]', 'continue'));
1204       $ext->add($context, $exten, 'report2', new ext_set('__TTL', '${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}'));
1205       $ext->add($context, $exten, '', new ext_gotoif('$[ ${TTL} > 0 ]', 'continue'));
1206       $ext->add($context, $exten, '', new ext_wait('${RINGTIMER}'));  // wait for a while, to give it a chance to be picked up by voicemail
1207       $ext->add($context, $exten, '', new ext_answer());
1208       $ext->add($context, $exten, '', new ext_wait('2'));
1209       $ext->add($context, $exten, '', new ext_playback('im-sorry&an-error-has-occured&with&call-forwarding'));
1210       $ext->add($context, $exten, '', new ext_macro('hangupcall'));
1211       $ext->add($context, $exten, '', new ext_congestion(20));
1212       $ext->add($context, $exten, 'continue', new ext_noop('Using CallerID ${CALLERID(all)}'));
1213       $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1214      
1215       /*
1216        * arg1 = trunk number, arg2 = number
1217        *
1218        * Re-written to use enumlookup.agi
1219        */
1220  
1221       $context = 'macro-dialout-enum';
1222       $exten = 's';
1223  
1224       $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1225       $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${ARG1}'));
1226       $ext->add($context, $exten, '', new ext_set('GROUP()', 'OUT_${ARG1}'));
1227       $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${ARG1}}foo" = "foo"]', 'nomax'));
1228       $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${ARG1})} > ${OUTMAXCHANS_${ARG1}} ]', 'nochans'));
1229       $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}'));
1230       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1231       $ext->add($context, $exten, '', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1232       //  Replacement for asterisk's ENUMLOOKUP function
1233       $ext->add($context, $exten, '', new ext_agi('enumlookup.agi'));
1234       // Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority
1235       // Loop through them trying them in order.
1236       $ext->add($context, $exten, 'dialloop', new ext_gotoif('$["foo${DIALARR}"="foo"]', 'end'));
1237       $ext->add($context, $exten, '', new ext_set('TRYDIAL', '${CUT(DIALARR,%,1)}'));
1238       $ext->add($context, $exten, '', new ext_set('DIALARR', '${CUT(DIALARR,%,2-)}'));
1239       $ext->add($context, $exten, '', new ext_dial('${TRYDIAL}', ''));
1240       $ext->add($context, $exten, '', new ext_noop('Dial exited in macro-enum-dialout with ${DIALSTATUS}'));
1241       // Now, if we're still here, that means the Dial failed for some reason.
1242       // If it's CONGESTION or CHANUNAVAIL we want to try again on a different
1243       // different channel. If there's no more left, the dialloop tag will exit.
1244       $ext->add($context, $exten, '', new ext_gotoif('$[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]', 'dialloop'));
1245       // If we're here, then it's BUSY or NOANSWER or something and well, deal with it.
1246       $ext->add($context, $exten, 'dialfailed', new ext_goto(1, 's-${DIALSTATUS}'));
1247       // Here are the exit points for the macro.
1248       $ext->add($context, $exten, 'nochans', new ext_noop('max channels used up'));
1249       $ext->add($context, $exten, 'end', new ext_noop('Exiting macro-dialout-enum'));
1250       $ext->add($context, 's-BUSY', '', new ext_noop('Trunk is reporting BUSY'));
1251       $ext->add($context, 's-BUSY', '', new ext_busy(20));
1252       $ext->add($context, '_s-.', '', new ext_noop('Dial failed due to ${DIALSTATUS}'));     
1253      
1254       /*
1255        * overrides callerid out trunks
1256        * arg1 is trunk
1257        * macro-user-callerid should be called _before_ using this macro
1258        */
1259
1260       $context = 'macro-outbound-callerid';
1261       $exten = 's';
1262      
1263       // Keep the original CallerID number, for failover to the next trunk.
1264       $ext->add($context, $exten, '', new ext_gotoif('$["${REALCALLERIDNUM:1:2}" != ""]', 'start'));
1265       $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${CALLERID(number)}'));
1266       $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1267
1268       // If this came through a ringgroup or CF, then we want to retain original CID unless
1269       // OUTKEEPCID_${trunknum} is set.
1270       // Save then CIDNAME while it is still intact in case we end up sending out this same CID
1271       $ext->add($context, $exten, '', new ext_gotoif('$["${KEEPCID}" != "TRUE"]', 'normcid'));  // Set to TRUE if coming from ringgroups, CF, etc.
1272       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTKEEPCID_${ARG1}}" = "xon"]', 'normcid'));
1273       $ext->add($context, $exten, '', new ext_gotoif('$["foo${REALCALLERIDNUM}" = "foo"]', 'normcid'));  // if not set to anything, go through normal processing
1274       $ext->add($context, $exten, '', new ext_set('USEROUTCID', '${REALCALLERIDNUM}'));
1275       $ext->add($context, $exten, '', new ext_set('REALCALLERIDNAME', '${CALLERID(name)}'));
1276
1277       // We now have to make sure the CID is valid. If we find an AMPUSER with the same CID, we assume it is an internal
1278       // call (would be quite a conincidence if not) and go through the normal processing to get that CID. If a device
1279       // is set for this CID, then it must be internal
1280       // If we end up using USEROUTCID at the end, it may still be the REALCALLERIDNUM we saved above. That is determined
1281       // if the two are equal, AND there is no CALLERID(name) present since it has been removed by the CALLERID(all)=${USEROUTCID}
1282       // setting. If this is the case, then we put the orignal name back in to send out. Although the CNAME is not honored by most
1283       // carriers, there are cases where it is so this preserves that information to be used by those carriers who do honor it.
1284       $ext->add($context, $exten, '', new ext_gotoif('$["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" = "foo"]', 'bypass', 'normcid'));
1285
1286       $ext->add($context, $exten, 'normcid', new ext_set('USEROUTCID', '${DB(AMPUSER/${REALCALLERIDNUM}/outboundcid)}'));
1287       $ext->add($context, $exten, 'bypass', new ext_set('EMERGENCYCID', '${DB(DEVICE/${REALCALLERIDNUM}/emergency_cid)}'));
1288       $ext->add($context, $exten, '', new ext_set('TRUNKOUTCID', '${OUTCID_${ARG1}}'));
1289       $ext->add($context, $exten, '', new ext_gotoif('$["${EMERGENCYROUTE:1:2}" = ""]', 'trunkcid'));  // check EMERGENCY ROUTE
1290       $ext->add($context, $exten, '', new ext_gotoif('$["${EMERGENCYCID:1:2}" = ""]', 'trunkcid'));  // empty EMERGENCY CID, so default back to trunk
1291       $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${EMERGENCYCID}'));  // emergency cid for device
1292       $ext->add($context, $exten, '', new ext_goto('report'));
1293       $ext->add($context, $exten, 'trunkcid', new ext_gotoif('$["${TRUNKOUTCID:1:2}" = ""]', 'usercid'));  // check for CID override for trunk (global var)
1294       $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${TRUNKOUTCID}'));
1295       $ext->add($context, $exten, 'usercid', new ext_gotoif('$["${USEROUTCID:1:2}" = ""]', 'report'));  // check CID override for extension
1296       $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${USEROUTCID}'));
1297       $ext->add($context, $exten, '', new ext_gotoif('$["x${CALLERID(name)}"!="xhidden"]', 'checkname', 'hidecid'));  // check CID blocking for extension
1298       $ext->add($context, $exten, 'hidecid', new ext_setcallerpres('prohib_passed_screen'));  // Only works with ISDN (T1/E1/BRI)
1299       $ext->add($context, $exten, 'checkname', new ext_execif('$[ $[ "${CALLERID(number)}" = "${REALCALLERIDNUM}" ] & $[ "${CALLERID(name)}" = "" ] ]', 'Set', 'CALLERID(name)=${REALCALLERIDNAME}'));
1300       $ext->add($context, $exten, 'report', new ext_noop('CallerID set to ${CALLERID(all)}'));     
1301
1302      
1303       /*
1304        * Adds a dynamic agent/member to a Queue
1305        * Prompts for call-back number - in not entered, uses CIDNum
1306        */
1307
1308       $context = 'macro-agent-add';
1309       $exten = 's';
1310      
1311       $ext->add($context, $exten, '', new ext_wait(1));
1312       $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
1313       $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-user'));  // get callback number from user
1314       $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" != ""]', 'a7'));  // if user just pressed # or timed out, use cidnum
1315       $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}'));
1316       $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}'));
1317       $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
1318       $ext->add($context, $exten, 'a7', new ext_gotoif('$["${CALLBACKNUM}" = "${ARG1}"]', 'invalid'));  // Error, they put in the queue number
1319       $ext->add($context, $exten, '', new ext_execif('$["${ARG2}" != ""]', 'Authenticate', '${ARG2}'));
1320       $ext->add($context, $exten, 'a9', new ext_addqueuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n'));  // using chan_local allows us to have agents over trunks
1321       $ext->add($context, $exten, '', new ext_userevent('Agentlogin', 'Agent: ${CALLBACKNUM}'));
1322       $ext->add($context, $exten, '', new ext_wait(1));
1323       $ext->add($context, $exten, '', new ext_playback('agent-loginok&with&extension'));
1324       $ext->add($context, $exten, '', new ext_saydigits('${CALLBACKNUM}'));
1325       $ext->add($context, $exten, '', new ext_hangup());
1326       $ext->add($context, $exten, '', new ext_macroexit());
1327       $ext->add($context, $exten, 'invalid', new ext_playback('pbx-invalid'));
1328       $ext->add($context, $exten, '', new ext_goto('a3'));
1329
1330       /*
1331        * Removes a dynamic agent/member from a Queue
1332        * Prompts for call-back number - in not entered, uses CIDNum
1333        */
1334
1335       $context = 'macro-agent-del';
1336      
1337       $ext->add($context, $exten, '', new ext_wait(1));
1338       $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
1339       $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-user'));  // get callback number from user
1340       $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a5', 'a7'));  // if user just pressed # or timed out, use cidnum
1341       $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}'));
1342       $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}'));
1343       $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
1344       $ext->add($context, $exten, 'a7', new ext_removequeuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n'));
1345       $ext->add($context, $exten, '', new ext_userevent('RefreshQueue'));
1346       $ext->add($context, $exten, '', new ext_wait(1));
1347       $ext->add($context, $exten, '', new ext_playback('agent-loggedoff'));
1348       $ext->add($context, $exten, '', new ext_hangup());
1349
1350     break;
1351   }
1352 }
1353
1354 /* begin page.ampusers.php functions */
1355
1356 function core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections) {
1357   $sql = "INSERT INTO ampusers (username, password, extension_low, extension_high, deptname, sections) VALUES (";
1358   $sql .= "'".$username."',";
1359   $sql .= "'".$password."',";
1360   $sql .= "'".$extension_low."',";
1361   $sql .= "'".$extension_high."',";
1362   $sql .= "'".$deptname."',";
1363   $sql .= "'".implode(";",$sections)."');";
1364  
1365   sql($sql,"query");
1366 }
1367
1368 function core_ampusers_del($username) {
1369   $sql = "DELETE FROM ampusers WHERE username = '".$username."'";
1370   sql($sql,"query");
1371 }
1372
1373 function core_ampusers_list() {
1374   $sql = "SELECT username FROM ampusers ORDER BY username";
1375   return sql($sql,"getAll");
1376 }
1377
1378 /* end page.ampusers.php functions */
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388 /* begin page.did.php functions */
1389
1390 function core_did_list($order='extension'){
1391   switch ($order) {
1392     case 'description':
1393       $sql = "SELECT * FROM incoming ORDER BY description,extension,cidnum";
1394       break;
1395     case 'extension':
1396     default:
1397       $sql = "SELECT * FROM incoming ORDER BY extension,cidnum";
1398   }
1399   return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1400 }
1401
1402 function core_did_get($extension="",$cidnum=""){
1403   $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1404   return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1405 }
1406
1407 function core_did_del($extension,$cidnum){
1408   $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1409   sql($sql);
1410 }
1411
1412 function core_did_edit($old_extension,$old_cidnum, $incoming){
1413
1414   $old_extension = addslashes(trim($old_extension));
1415   $old_cidnum = addslashes(trim($old_cidnum));
1416
1417   $incoming['extension'] = trim($incoming['extension']);
1418   $incoming['cidnum'] = trim($incoming['cidnum']);
1419
1420   $extension = addslashes($incoming['extension']);
1421   $cidnum = addslashes($incoming['cidnum']);
1422
1423   // if did or cid changed, then check to make sure that this pair is not already being used.
1424   //
1425   if (($extension != $old_extension) || ($cidnum != $old_cidnum)) {
1426     $existing=core_did_get($extension,$cidnum);
1427     if (empty($existing) && (trim($cidnum) == "")) {
1428       $existing_directdid = core_users_directdid_get($extension);
1429     } else {
1430       $existing_directdid = "";
1431     }
1432   } else {
1433     $existing = $existing_directdid = "";
1434   }
1435
1436   if (empty($existing) && empty($existing_directdid)) {
1437     core_did_del($old_extension,$old_cidnum);
1438     core_did_add($incoming);
1439     return true;
1440   } else {
1441     if (!empty($existing)) {
1442       echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1443     } else {
1444       echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1445     }
1446     return false;
1447   }
1448 }
1449
1450 function core_did_add($incoming){
1451   foreach ($incoming as $key => $val) { ${$key} = addslashes($val); } // create variables from request
1452
1453   // Check to make sure the did is not being used elsewhere
1454   //
1455   $existing=core_did_get($extension,$cidnum);
1456   if (empty($existing) && (trim($cidnum) == "")) {
1457     $existing_directdid = core_users_directdid_get($extension);
1458   } else {
1459     $existing_directdid = "";
1460   }
1461
1462   if (empty($existing) && empty($existing_directdid)) {
1463     $destination=${$goto0.'0'};
1464     $sql="INSERT INTO incoming (cidnum,extension,destination,faxexten,faxemail,answer,wait,privacyman,alertinfo, ringing, mohclass, description, grppre) values ('$cidnum','$extension','$destination','$faxexten','$faxemail','$answer','$wait','$privacyman','$alertinfo', '$ringing', '$mohclass', '$description', '$grppre')";
1465     sql($sql);
1466     return true;
1467   } else {
1468     if (!empty($existing)) {
1469       echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1470     } else {
1471       echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1472     }
1473     return false;
1474   }
1475 }
1476
1477 /* end page.did.php functions */
1478
1479
1480
1481
1482
1483
1484
1485 /* begin page.devices.php functions */
1486
1487 //get the existing devices
1488 function core_devices_list($tech="all") {
1489   $sql = "SELECT id,description FROM devices";
1490   switch (strtoupper($tech)) {
1491     case "IAX":
1492       $sql .= " WHERE tech = 'iax2'";
1493       break;
1494     case "IAX2":
1495     case "SIP":
1496     case "ZAP":
1497       $sql .= " WHERE tech = '".strtolower($tech)."'";
1498       break;
1499     case "ALL":
1500     default:
1501   }
1502   $sql .= ' ORDER BY id';
1503   $results = sql($sql,"getAll");
1504
1505   foreach($results as $result){
1506     if (checkRange($result[0])){
1507       $extens[] = array(
1508         0=>$result[0],  // for backwards compatibility
1509         1=>$result[1],
1510         'id'=>$result[0], // FETCHMODE_ASSOC emulation
1511         'description'=>$result[1],
1512       );
1513     }
1514   }
1515   if (isset($extens)) {
1516     return $extens;
1517   } else {
1518     return null;
1519   }
1520 }
1521
1522
1523 function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){
1524   global $amp_conf;
1525   global $currentFile;
1526   global $astman;
1527
1528   $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
1529
1530   if (trim($id) == '' ) {
1531     if ($display != 'extensions') {
1532       echo "<script>javascript:alert('"._("You must put in a device id")."');</script>";
1533     }
1534     return false;
1535   }
1536  
1537   //ensure this id is not already in use
1538   $devices = core_devices_list();
1539   if (is_array($devices)) {
1540     foreach($devices as $device) {
1541       if ($device[0] === $id) {
1542         if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
1543         return false;
1544       }
1545     }
1546   }
1547   //unless defined, $dial is TECH/id
1548   if ( $dial == '' ) {
1549     //zap is an exception
1550     if ( strtolower($tech) == "zap" ) {
1551       $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1552       $dial = 'ZAP/'.$zapchan;
1553     } else {
1554       $dial = strtoupper($tech)."/".$id;
1555     }
1556   }
1557  
1558   //check to see if we are requesting a new user
1559   if ($user == "new") {
1560     $user = $id;
1561     $jump = true;
1562   }
1563  
1564   if(!get_magic_quotes_gpc()) {
1565     if(!empty($emergency_cid))
1566       $emergency_cid = addslashes($emergency_cid);
1567     if(!empty($description))
1568       $description = addslashes($description);
1569   }
1570  
1571   //insert into devices table
1572   $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
1573   sql($sql);
1574  
1575   //add details to astdb
1576   if ($astman) {
1577     // if adding or editting a fixed device, user property should always be set
1578     if ($devicetype == 'fixed' || !$editmode) {
1579       $astman->database_put("DEVICE",$id."/user",$user);
1580     }
1581     // If changing from a fixed to an adhoc, the user property should be intialized
1582     // to the new default, not remain as the previous fixed user
1583     if ($editmode) {
1584       $previous_type = $astman->database_get("DEVICE",$id."/type");
1585       if ($previous_type == 'fixed' && $devicetype == 'adhoc') {
1586         $astman->database_put("DEVICE",$id."/user",$user);
1587       }
1588     }
1589     $astman->database_put("DEVICE",$id."/dial",$dial);
1590     $astman->database_put("DEVICE",$id."/type",$devicetype);
1591     $astman->database_put("DEVICE",$id."/default_user",$user);
1592     if($emergency_cid != '') {
1593       $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1594     }
1595
1596     if ($user != "none") {
1597       $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1598       if (empty($existingdevices)) {
1599         $astman->database_put("AMPUSER",$user."/device",$id);
1600       } else {
1601         $existingdevices_array = explode('&',$existingdevices);
1602         if (!in_array($id, $existingdevices_array)) {
1603           $existingdevices_array[]=$id;
1604           $existingdevices = implode('&',$existingdevices_array);
1605           $astman->database_put("AMPUSER",$user."/device",$existingdevices);
1606         }
1607       }
1608     }
1609
1610   } else {
1611     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1612   }
1613  
1614   // create a voicemail symlink if needed
1615   $thisUser = core_users_get($user);
1616   if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1617     if(empty($thisUser['voicemail']))
1618       $vmcontext = "default";
1619     else
1620       $vmcontext = $thisUser['voicemail'];
1621    
1622     //voicemail symlink
1623     exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1624     exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1625   }
1626    
1627   //take care of sip/iax/zap config
1628   $funct = "core_devices_add".strtolower($tech);
1629   if(function_exists($funct)){
1630     $funct($id);
1631   }
1632  
1633 /*  if($user != "none") {
1634     core_hint_add($user);
1635   }*/
1636  
1637   //if we are requesting a new user, let's jump to users.php
1638   if (isset($jump)) {
1639     echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
1640   }
1641   return true;
1642 }
1643
1644 function core_devices_del($account,$editmode=false){
1645   global $amp_conf;
1646   global $currentFile;
1647   global $astman;
1648  
1649   //get all info about device
1650   $devinfo = core_devices_get($account);
1651  
1652   //delete details to astdb
1653   if ($astman) {
1654     // If a user was selected, remove this device from the user
1655     $deviceuser = $astman->database_get("DEVICE",$account."/user");
1656     if (isset($deviceuser) && $deviceuser != "none") {
1657       // Remove the device record from the user's device list
1658       $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
1659
1660       // We need to remove just this user and leave the rest alone
1661       $userdevicesarr = explode("&", $userdevices);
1662       $userdevicesarr_hash = array_flip($userdevicesarr);
1663       unset($userdevicesarr_hash[$account]);
1664       $userdevicesarr = array_flip($userdevicesarr_hash);
1665       $userdevices = implode("&", $userdevicesarr);
1666      
1667       if (empty($userdevices)) {
1668           $astman->database_del("AMPUSER",$deviceuser."/device");
1669       } else {
1670           $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
1671       }
1672     }
1673     if (! $editmode) {
1674       $astman->database_del("DEVICE",$account."/dial");
1675       $astman->database_del("DEVICE",$account."/type");
1676       $astman->database_del("DEVICE",$account."/user");
1677       $astman->database_del("DEVICE",$account."/default_user");
1678       $astman->database_del("DEVICE",$account."/emergency_cid");
1679     }
1680
1681     //delete from devices table
1682     $sql="DELETE FROM devices WHERE id = \"$account\"";
1683     sql($sql);
1684
1685     //voicemail symlink
1686     exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
1687   } else {
1688     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1689   }
1690  
1691   //take care of sip/iax/zap config
1692   $funct = "core_devices_del".strtolower($devinfo['tech']);
1693   if(function_exists($funct)){
1694     $funct($account);
1695   }
1696 }
1697
1698 function core_devices_get($account){
1699   //get all the variables for the meetme
1700   $sql = "SELECT * FROM devices WHERE id = '$account'";
1701   $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1702  
1703   //take care of sip/iax/zap config
1704   $funct = "core_devices_get".strtolower($results['tech']);
1705   if (!empty($results['tech']) && function_exists($funct)) {
1706     $devtech = $funct($account);
1707     if (is_array($devtech)){
1708       $results = array_merge($results,$devtech);
1709     }
1710   }
1711  
1712   return $results;
1713 }
1714
1715 // this function rebuilds the astdb based on device table contents
1716 // used on devices.php if action=resetall
1717 function core_devices2astdb(){
1718   global $astman;
1719   global $amp_conf;
1720
1721   $sql = "SELECT * FROM devices";
1722   $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1723
1724   //add details to astdb
1725   if ($astman) {
1726     $astman->database_deltree("DEVICE");
1727     foreach ($devresults as $dev) {
1728       extract($dev); 
1729       $astman->database_put("DEVICE",$id."/dial",$dial);
1730       $astman->database_put("DEVICE",$id."/type",$devicetype);
1731       $astman->database_put("DEVICE",$id."/user",$user);   
1732       $astman->database_put("DEVICE",$id."/default_user",$user);
1733       if(trim($emergency_cid) != '') {
1734         $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1735       }
1736       // If a user is selected, add this device to the user
1737       if ($user != "none") {
1738           $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1739           if (!empty($existingdevices)) {
1740               $existingdevices .= "&";
1741           }
1742           $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
1743       }
1744      
1745       // create a voicemail symlink if needed
1746       $thisUser = core_users_get($user);
1747       if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1748         if(empty($thisUser['voicemail']))
1749           $vmcontext = "default";
1750         else
1751           $vmcontext = $thisUser['voicemail'];
1752         //voicemail symlink
1753         exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1754         exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1755       }
1756     }
1757     return true;
1758   } else {
1759     return false;
1760   }
1761 }
1762
1763 // this function rebuilds the astdb based on users table contents
1764 // used on devices.php if action=resetall
1765 function core_users2astdb(){
1766   global $amp_conf;
1767   global $astman;
1768
1769   $sql = "SELECT * FROM users";
1770   $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1771  
1772   //add details to astdb
1773   if ($astman) {
1774     foreach($userresults as $usr) {
1775       extract($usr);
1776       $astman->database_put("AMPUSER",$extension."/password",$password);
1777       $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
1778       $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
1779       $astman->database_put("AMPUSER",$extension."/recording",$recording);
1780       $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
1781       $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
1782       $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
1783     }
1784     return true;
1785   } else {
1786     return false;
1787   }
1788
1789 //  TODO: this was...
1790 //  return $astman->disconnect();
1791 //  is "true" the correct value...?
1792 }
1793
1794 //add to sip table
1795 function core_devices_addsip($account) {
1796   global $db;
1797   global $currentFile;
1798
1799   foreach ($_REQUEST as $req=>$data) {
1800     if ( substr($req, 0, 8) == 'devinfo_' ) {
1801       $keyword = substr($req, 8);
1802       if ( $keyword == 'dial' && $data == '' ) {
1803         $sipfields[] = array($account, $keyword, 'SIP/'.$account);
1804       } elseif ($keyword == 'mailbox' && $data == '') {
1805         $sipfields[] = array($account,'mailbox',$account.'@device');
1806       } else {
1807         $sipfields[] = array($account, $keyword, $data);
1808       }
1809     }
1810   }
1811  
1812   if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
1813     $sipfields = array(
1814       //array($account,'account',$account),
1815       array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1816       array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
1817       array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
1818       array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
1819       array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
1820       array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
1821       array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
1822       array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
1823       array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
1824       array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
1825       array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
1826       array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
1827       array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
1828       array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
1829       array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
1830       array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
1831       //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
1832       //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
1833       //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1834     );
1835   }
1836
1837   // Very bad
1838   $sipfields[] = array($account,'account',$account); 
1839   $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1840  
1841   // Where is this in the interface ??????
1842   $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1843   $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1844
1845   $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
1846   $result = $db->executeMultiple($compiled,$sipfields);
1847   if(DB::IsError($result)) {
1848     die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table'); 
1849   }
1850 }
1851
1852 function core_devices_delsip($account) {
1853   global $db;
1854   global $currentFile;
1855  
1856   $sql = "DELETE FROM sip WHERE id = '$account'";
1857   $result = $db->query($sql);
1858  
1859   if(DB::IsError($result)) {
1860     die_freepbx($result->getMessage().$sql);
1861   }
1862 }
1863
1864 function core_devices_getsip($account) {
1865   global $db;
1866   $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
1867   $results = $db->getAssoc($sql);
1868   if(DB::IsError($results)) {
1869     $results = null;
1870   }
1871  
1872   return $results;
1873 }
1874
1875 //add to iax table
1876 function core_devices_addiax2($account) {
1877   global $db;
1878   global $currentFile;
1879  
1880   foreach ($_REQUEST as $req=>$data) {
1881     if ( substr($req, 0, 8) == 'devinfo_' ) {
1882       $keyword = substr($req, 8);
1883       if ( $keyword == 'dial' && $data == '' ) {
1884         $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
1885       } elseif ($keyword == 'mailbox' && $data == '') {
1886         $iaxfields[] = array($account,'mailbox',$account.'@device');
1887       } else {
1888         $iaxfields[] = array($account, $keyword, $data);
1889       }
1890     }
1891   }
1892  
1893   if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
1894     $iaxfields = array(
1895       //array($account,'account',$account),
1896       array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
1897       array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
1898       array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1899       array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
1900       array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
1901       array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1902       array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
1903       array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
1904       array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
1905       array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
1906       array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
1907       array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
1908       //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
1909       //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1910       //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1911     );
1912   }
1913
1914   // Very bad
1915   $iaxfields[] = array($account,'account',$account); 
1916   $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1917   // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
1918   // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
1919   // callerid as a variable which gets picked up in macro-callerid.
1920   // Ref - http://bugs.digium.com/view.php?id=456
1921   $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
1922  
1923   // Where is this in the interface ??????
1924   $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1925   $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1926  
1927   $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
1928   $result = $db->executeMultiple($compiled,$iaxfields);
1929   if(DB::IsError($result)) {
1930     die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
1931   }
1932 }
1933
1934 function core_devices_deliax2($account) {
1935   global $db;
1936   global $currentFile;
1937  
1938   $sql = "DELETE FROM iax WHERE id = '$account'";
1939   $result = $db->query($sql);
1940  
1941   if(DB::IsError($result)) {
1942     die_freepbx($result->getMessage().$sql);
1943   }
1944 }
1945
1946 function core_devices_getiax2($account) {
1947   global $db;
1948   $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
1949   $results = $db->getAssoc($sql);
1950   if(DB::IsError($results)) {
1951     $results = null;
1952   }
1953  
1954   return $results;
1955 }
1956
1957 function core_devices_addzap($account) {
1958   global $db;
1959   global $currentFile;
1960  
1961   foreach ($_REQUEST as $req=>$data) {
1962     if ( substr($req, 0, 8) == 'devinfo_' ) {
1963       $keyword = substr($req, 8);
1964       if ( $keyword == 'dial' && $data == '' ) {
1965         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1966         $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
1967       } elseif ($keyword == 'mailbox' && $data == '') {
1968         $zapfields[] = array($account,'mailbox',$account.'@device');
1969       } else {
1970         $zapfields[] = array($account, $keyword, $data);
1971       }
1972     }
1973   }
1974  
1975   if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
1976     $zapfields = array(
1977       //array($account,'account',$account),
1978       array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1979       array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1980       //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
1981       array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1982       array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
1983       array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
1984       array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
1985       array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1986       array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
1987       array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
1988       array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
1989       array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
1990       //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'), 
1991       //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1992       array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1993       array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
1994     );
1995   }
1996
1997   // Very bad
1998   $zapfields[] = array($account,'account',$account); 
1999   $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2000  
2001   // Where is this in the interface ??????
2002   $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2003   $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2004
2005   $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
2006   $result = $db->executeMultiple($compiled,$zapfields);
2007   if(DB::IsError($result)) {
2008     die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
2009   }
2010 }
2011
2012 function core_devices_delzap($account) {
2013   global $db;
2014   global $currentFile;
2015  
2016   $sql = "DELETE FROM zap WHERE id = '$account'";
2017   $result = $db->query($sql);
2018   if(DB::IsError($result)) {
2019     die_freepbx($result->getMessage().$sql);
2020   }
2021 }
2022
2023 function core_devices_getzap($account) {
2024   global $db;
2025   $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
2026   $results = $db->getAssoc($sql);
2027   if(DB::IsError($results)) {
2028     $results = null;
2029   }
2030   return $results;
2031 }
2032 /* end page.devices.php functions */
2033
2034
2035
2036
2037 function core_hint_get($account){
2038   global $astman;
2039
2040   // We should always check the AMPUSER in case they logged into a device
2041   // but we will fall back to the old methond if $astman not open although
2042   // I'm pretty sure everything else will puke anyhow if not running
2043   //
2044   if ($astman) {
2045     $device=$astman->database_get("AMPUSER",$account."/device");
2046     $device_arr = explode('&',$device);
2047     $sql = "SELECT dial from devices where id in ('".implode("','",$device_arr)."')";
2048   } else {
2049     $sql = "SELECT dial from devices where user = '{$account}'";
2050   }
2051   $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2052  
2053   //create an array of strings
2054   if (is_array($results)){
2055     foreach ($results as $result) {
2056       $dial[] = $result['dial'];
2057     }
2058   }
2059  
2060   //create a string with & delimiter
2061   if (isset($dial) && is_array($dial)){
2062     $hint = implode($dial,"&");
2063   } else {
2064     if (isset($results[0]['dial'])) {
2065       $hint = $results[0]['dial'];
2066     } else {
2067       $hint = null;
2068     }
2069   }
2070  
2071   return $hint;
2072 }
2073
2074
2075
2076 /* begin page.users.php functions */
2077
2078 // get the existing extensions
2079 // the returned arrays contain [0]:extension [1]:name
2080 function core_users_list() {
2081   $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
2082
2083   //only allow extensions that are within administrator's allowed range
2084   foreach($results as $result){
2085     if (checkRange($result[0])){
2086       $extens[] = array($result[0],$result[1],$result[2]);
2087     }
2088   }
2089  
2090   if (isset($extens)) {
2091     sort($extens);
2092     return $extens;
2093   } else {
2094     return null;
2095   }
2096 }
2097
2098 function core_check_extensions($exten=true) {
2099   global $amp_conf;
2100
2101   $extenlist = array();
2102   if (is_array($exten) && empty($exten)) {
2103     return $extenlist;
2104   }
2105   $sql = "SELECT extension, name FROM users ";
2106   if (is_array($exten)) {
2107     $sql .= "WHERE extension in ('".implode("','",$exten)."')";
2108   }
2109   $sql .= " ORDER BY extension";
2110   $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2111
2112   foreach ($results as $result) {
2113     $thisexten = $result['extension'];
2114     $extenlist[$thisexten]['description'] = _("User Extension: ").$result['name'];
2115     $extenlist[$thisexten]['status'] = 'INUSE';
2116     $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
2117     $extenlist[$thisexten]['edit_url'] = "config.php?type=setup&display=$display&extdisplay=".urlencode($thisexten)."&skip=0";
2118   }
2119   return $extenlist;
2120 }
2121
2122 function core_check_destinations($dest=true) {
2123   global $active_modules;
2124
2125   $destlist = array();
2126   if (is_array($dest) && empty($dest)) {
2127     return $destlist;
2128   }
2129   $sql = "SELECT extension, cidnum, description, destination FROM incoming ";
2130   if ($dest !== true) {
2131     $sql .= "WHERE destination in ('".implode("','",$dest)."')";
2132   }
2133   $sql .= "ORDER BY extension, cidnum";
2134   $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2135
2136   //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
2137
2138   foreach ($results as $result) {
2139     $thisdest = $result['destination'];
2140     $thisid   = $result['extension'].'/'.$result['cidnum'];
2141     $destlist[] = array(
2142       'dest' => $thisdest,
2143       'description' => 'Inbound Route: '.$result['description'].' ('.$thisid.')',
2144       'edit_url' => 'config.php?display=did&extdisplay='.urlencode($thisid),
2145     );
2146   }
2147   return $destlist;
2148 }
2149
2150 function core_sipname_check($sipname, $extension) {
2151   global $db;
2152   if (!isset($sipname) || trim($sipname)=='')
2153     return true;
2154
2155   $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
2156   $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2157   if(DB::IsError($results)) {
2158         die_freepbx($results->getMessage().$sql);
2159   }
2160  
2161   if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
2162     return false;
2163   else
2164     return true;
2165 }
2166
2167 function core_users_add($vars, $editmode=false) {
2168   extract($vars);
2169  
2170   global $db;
2171   global $amp_conf;
2172   global $astman;
2173
2174   $thisexten = isset($thisexten) ? $thisexten : '';
2175
2176   if (trim($extension) == '' ) {
2177     echo "<script>javascript:alert('"._("You must put in an extension (or user) number")."');</script>";
2178     return false;
2179   }
2180
2181   //ensure this id is not already in use
2182   $extens = core_users_list();
2183   if(is_array($extens)) {
2184     foreach($extens as $exten) {
2185       if ($exten[0]===$extension) {
2186         echo "<script>javascript:alert('".sprintf(_("This user/extension %s is already in use"),$extension)."');</script>";
2187         return false;
2188       }
2189     }
2190   }
2191
2192   // clean and check the did to make sure it is not being used by another extension or in did routing
2193   //
2194   $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2195   if (trim($directdid) != "") {
2196     $existing=core_did_get($directdid,"");
2197     $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2198     if (!empty($existing) || !empty($existing_directdid)) {
2199       if (!empty($existing)) {
2200         echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2201       } else {
2202         echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2203       }
2204       return false;
2205     }
2206   }
2207
2208   $sipname = preg_replace("/\s/" ,"", trim($sipname));
2209   if (! core_sipname_check($sipname, $extension)) {
2210     echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
2211     return false;
2212   }
2213  
2214   //build the recording variable
2215   $recording = "out=".$record_out."|in=".$record_in;
2216  
2217   //escape quotes and any other bad chars:
2218   if(!get_magic_quotes_gpc()) {
2219     $outboundcid = addslashes($outboundcid);
2220     $name = addslashes($name);
2221   }
2222
2223   //if voicemail is enabled, set the box@context to use
2224   //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
2225   if ( function_exists('voicemail_mailbox_get') ) {
2226     $vmbox = voicemail_mailbox_get($extension);
2227     if ( $vmbox == null ) {
2228       $voicemail = "novm";
2229       $vmx_state = "false";
2230     } else {
2231       $voicemail = $vmbox['vmcontext'];
2232     }
2233   }
2234
2235   // MODIFICATION: (PL)
2236   // Added for directdid and didalert l for Alert Info distinctive ring)
2237   //
2238   // cleanup any non dial pattern characters prior to inserting into the database
2239   // then add directdid to the insert command.
2240   //
2241   // Clean replace any <> with () in display name - should have javascript stopping this but ...
2242   //
2243   $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
2244  
2245   //insert into users table
2246   $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
2247   $sql.= "$extension\", \"";
2248   $sql.= isset($password)?$password:'';
2249   $sql.= "\", \"";
2250   $sql.= isset($name)?$name:'';
2251   $sql.= "\", \"";
2252   $sql.= isset($voicemail)?$voicemail:'default';
2253   $sql.= "\", \"";
2254   $sql.= isset($ringtimer)?$ringtimer:'';
2255   $sql.= "\", \"";
2256   $sql.= isset($noanswer)?$noanswer:'';
2257   $sql.= "\", \"";
2258   $sql.= isset($recording)?$recording:'';
2259   $sql.= "\", \"";
2260   $sql.= isset($outboundcid)?$outboundcid:'';
2261   $sql.= "\", \"";
2262   $sql.= isset($directdid)?$directdid:'';
2263   $sql.= "\", \"";
2264   $sql.= isset($didalert)?$didalert:'';
2265
2266   $sql.= "\", \"";
2267   $sql.= isset($faxexten)?$faxexten:'';
2268   $sql.= "\", \"";
2269   $sql.= isset($faxemail)?$faxemail:'';
2270   $sql.= "\", \"";
2271   $sql.= isset($answer)?$answer:'';
2272   $sql.= "\", \"";
2273   $sql.= isset($wait)?$wait:'';
2274   $sql.= "\", \"";
2275   $sql.= isset($privacyman)?$privacyman:'';
2276   $sql.= "\", \"";
2277   $sql.= isset($mohclass)?$mohclass:'';
2278   $sql.= "\", \"";
2279   $sql.= isset($sipname)?$sipname:'';
2280   $sql.= "\")";
2281   sql($sql);
2282
2283   //write to astdb
2284   if ($astman) {
2285     $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
2286     $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
2287     $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
2288     $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
2289     $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
2290     $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
2291     $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
2292     $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
2293     $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
2294     if (!$editmode) {
2295       $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
2296     }
2297
2298     if (trim($callwaiting) == 'enabled') {
2299       $astman->database_put("CW",$extension,"\"ENABLED\"");
2300     } else if (trim($callwaiting) == 'disabled') {
2301       $astman->database_del("CW",$extension);
2302     } else {
2303       echo "ERROR: this state should not exist<br>";
2304     }
2305
2306     if ($vmx_state && $voicemail != "novm") {
2307
2308       $unavail_mode="enabled";
2309       $busy_mode="disabled";
2310       $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2311
2312       if (trim($vmx_state) == 'blocked') {
2313
2314         $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
2315         $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
2316
2317       } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
2318
2319         $repeat="1";
2320         $timeout="2";
2321         $vmxopts_timeout="";
2322         $loops="1";
2323
2324         $mode="unavail";
2325         $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
2326         $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2327
2328         $mode="busy";
2329         $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
2330         $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2331        
2332       }
2333     } else {
2334       $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2335       if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
2336         $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
2337         $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
2338       }
2339     }
2340   } else {
2341     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2342   }
2343   return true;
2344 }
2345
2346 function core_users_get($extension){
2347   global $db;
2348   global $amp_conf;
2349   global $astman;
2350   //get all the variables for the meetme
2351   $sql = "SELECT * FROM users WHERE extension = '$extension'";
2352   $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2353   if(DB::IsError($results)) {
2354     die_freepbx($results->getMessage().$sql);
2355   }
2356   if (empty($results)) {
2357     return $results;
2358   }
2359  
2360   //explode recording vars
2361   $recording = explode("|",$results['recording']);
2362   if (isset($recording[1])) {
2363     $recout = substr($recording[0],4);
2364     $recin = substr($recording[1],3);
2365     $results['record_in']=$recin;
2366     $results['record_out']=$recout;
2367   } else {
2368     $results['record_in']='Adhoc';
2369     $results['record_out']='Adhoc';
2370   }
2371   if ($astman) {
2372     $cw = $astman->database_get("CW",$extension);
2373     $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
2374     $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2375     $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
2376     $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
2377   } else {
2378     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2379   }
2380
2381   return $results;
2382 }
2383
2384 function core_users_del($extension, $editmode=false){
2385   global $db;
2386   global $amp_conf;
2387   global $astman;
2388  
2389   //delete from devices table
2390   $sql="DELETE FROM users WHERE extension = \"$extension\"";
2391   $results = $db->query($sql);
2392   if(DB::IsError($results)) {
2393     die_freepbx($results->getMessage().$sql);
2394   }
2395
2396   //delete details to astdb
2397   if ($astman && !$editmode) {
2398     $astman->database_del("AMPUSER",$extension."/password");
2399     $astman->database_del("AMPUSER",$extension."/ringtimer");
2400     $astman->database_del("AMPUSER",$extension."/noanswer");
2401     $astman->database_del("AMPUSER",$extension."/recording");
2402     $astman->database_del("AMPUSER",$extension."/outboundcid");
2403     $astman->database_del("AMPUSER",$extension."/cidname");
2404     $astman->database_del("AMPUSER",$extension."/cidnum");
2405     $astman->database_del("AMPUSER",$extension."/voicemail");
2406     $astman->database_del("AMPUSER",$extension."/device");
2407   }
2408 }
2409
2410 function core_users_directdid_get($directdid=""){
2411   if (empty($directdid)) {
2412     return array();
2413   } else {
2414     $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
2415     return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2416   }
2417 }
2418
2419 function core_users_cleanastdb($extension) {
2420   // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
2421   // call forwarding, call waiting settings could hang around and bite someone if they
2422   // recycle an extension. Is called from page.xtns and page.users.
2423   global $amp_conf;
2424   global $astman;
2425
2426   if ($astman) {
2427     $astman->database_del("CW",$extension);
2428     $astman->database_del("CF",$extension);
2429     $astman->database_del("CFB",$extension);
2430     $astman->database_del("CFU",$extension);
2431     $astman->database_deltree("AMPUSER/".$extension."/vmx");
2432
2433   } else {
2434     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2435   }
2436 }
2437
2438 function core_users_edit($extension,$vars){
2439   global $db;
2440   global $amp_conf;
2441   global $astman;
2442  
2443   //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
2444   if ($astman) {
2445     $ud = $astman->database_get("AMPUSER",$extension."/device");
2446     $vars['device'] = $ud;
2447   } else {
2448     fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2449   }
2450  
2451   $directdid=$vars['directdid'];
2452   $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2453   // clean and check the did to make sure it is not being used by another extension or in did routing
2454   //
2455   if (trim($directdid) != "") {
2456     $existing=core_did_get($directdid,"");
2457     $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2458     if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
2459       if (!empty($existing)) {
2460         echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2461       } else {
2462         echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2463       }
2464       return false;
2465     }
2466   }
2467
2468   //delete and re-add
2469   if (core_sipname_check($vars['sipname'],$extension)) {
2470     core_users_del($extension, true);
2471     core_users_add($vars, true);
2472   }
2473   return true;
2474  
2475 }
2476
2477 function core_directdid_list(){
2478   $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
2479   return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2480 }
2481
2482
2483
2484 function core_zapchandids_add($description, $channel, $did) {
2485   global $db;
2486
2487
2488   if (!ctype_digit(trim($channel)) || trim($channel) == '') {
2489     echo "<script>javascript:alert('"._('Invalid Channel Number, must be numeric and not blank')."')</script>";
2490     return false;
2491   }
2492   if (trim($did) == '') {
2493     echo "<script>javascript:alert('"._('Invalid DID, must be a non-blank DID')."')</script>";
2494     return false;
2495   }
2496
2497   $description = q($description);
2498   $channel     = q($channel);
2499   $did         = q($did);
2500
2501   $sql = "INSERT INTO zapchandids (channel, description, did) VALUES ($channel, $description, $did)";
2502   $results = $db->query($sql);
2503   if (DB::IsError($results)) {
2504     if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) {
2505       echo "<script>javascript:alert('"._("Error Duplicate Channel Entry")."')</script>";
2506       return false;
2507     } else {
2508       die_freepbx($results->getMessage()."<br><br>".$sql);
2509     }
2510   }
2511   return true;
2512 }
2513
2514 function core_zapchandids_edit($description, $channel, $did) {
2515   global $db;
2516
2517   $description = q($description);
2518   $channel     = q($channel);
2519   $did         = q($did);
2520
2521   $sql = "UPDATE zapchandids SET description = $description, did = $did WHERE channel = $channel";
2522   $results = $db->query($sql);
2523   if (DB::IsError($results)) {
2524     die_freepbx($results->getMessage()."<br><br>".$sql);
2525   }
2526   return true;
2527 }
2528
2529 function core_zapchandids_delete($channel) {
2530   global $db;
2531
2532   $channel     = q($channel);
2533
2534   $sql = "DELETE FROM zapchandids WHERE channel = $channel";
2535   $results = $db->query($sql);
2536   if (DB::IsError($results)) {
2537     die_freepbx($results->getMessage()."<br><br>".$sql);
2538   }
2539   return true;
2540 }
2541
2542 function core_zapchandids_list() {
2543   global $db;
2544
2545   $sql = "SELECT * FROM zapchandids ORDER BY channel";
2546   return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2547 }
2548
2549 function core_zapchandids_get($channel) {
2550   global $db;
2551
2552   $channel     = q($channel);
2553
2554   $sql = "SELECT * FROM zapchandids WHERE channel = $channel";
2555   return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2556 }
2557
2558 /* end page.users.php functions */
2559
2560
2561
2562
2563
2564 /* begin page.trunks.php functions */
2565
2566 // we're adding ,don't require a $trunknum
2567 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2568   global $db;
2569  
2570   // find the next available ID
2571   $trunknum = 1;
2572   foreach(core_trunks_list() as $trunk) {
2573     if ($trunknum == ltrim($trunk[0],"OUT_")) {
2574       $trunknum++;
2575     }
2576   }
2577  
2578   core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2579  
2580   return $trunknum;
2581 }
2582
2583 function core_trunks_del($trunknum, $tech = null) {
2584   global $db;
2585  
2586   if ($tech === null) { // in EditTrunk, we get this info anyways
2587     $tech = core_trunks_getTrunkTech($trunknum);
2588   }
2589
2590   //delete from globals table
2591   sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
2592  
2593   //write outids
2594   core_trunks_writeoutids();
2595
2596   // conditionally, delete from iax or sip
2597   switch (strtolower($tech)) {
2598     case "iax":
2599     case "iax2":
2600       sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2601     break;
2602     case "sip":
2603       sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2604     break;
2605   }
2606 }
2607
2608 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2609   //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2610   $tech = core_trunks_getTrunkTech($trunknum);
2611   core_trunks_del($trunknum, $tech);
2612   core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2613 }
2614
2615 // just used internally by addTrunk() and editTrunk()
2616 //obsolete
2617 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2618   global $db;
2619  
2620   if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
2621  
2622   //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2623  
2624   // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
2625   $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
2626   $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
2627  
2628   $glofields = array(
2629       array('OUT_'.$trunknum, $outval),
2630       array('OUTPREFIX_'.$trunknum, $dialoutprefix),
2631       array('OUTMAXCHANS_'.$trunknum, $maxchans),
2632       array('OUTCID_'.$trunknum, $outcid),
2633       array('OUTKEEPCID_'.$trunknum, $keepcid),
2634       array('OUTFAIL_'.$trunknum, $failtrunk),
2635       array('OUTDISABLE_'.$trunknum, $disabletrunk),
2636       );
2637      
2638   unset($techtemp);
2639  
2640   $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
2641   $result = $db->executeMultiple($compiled,$glofields);
2642   if(DB::IsError($result)) {
2643     die_freepbx($result->getMessage()."<br><br>".$sql);
2644   }
2645  
2646   core_trunks_writeoutids();
2647
2648   $disable_flag = ($disabletrunk == "on")?1:0;
2649  
2650   switch (strtolower($tech)) {
2651     case "iax":
2652     case "iax2":
2653       core_trunks_addSipOrIax($peerdetails,'iax',$channelid,$trunknum,$disable_flag);
2654       if ($usercontext != ""){
2655         core_trunks_addSipOrIax($userconfig,'iax',$usercontext,'9'.$trunknum,$disable_flag);
2656       }
2657       if ($register != ""){
2658         core_trunks_addRegister($trunknum,'iax',$register,$disable_flag);
2659       }
2660     break;
2661     case "sip":
2662       core_trunks_addSipOrIax($peerdetails,'sip',$channelid,$trunknum,$disable_flag);
2663       if ($usercontext != ""){
2664         core_trunks_addSipOrIax($userconfig,'sip',$usercontext,'9'.$trunknum,$disable_flag);
2665       }
2666       if ($register != ""){
2667         core_trunks_addRegister($trunknum,'sip',$register,$disable_flag);
2668       }
2669     break;
2670   }
2671 }
2672
2673 function core_trunks_getTrunkTech($trunknum) {
2674
2675   $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
2676   if (!$results) {
2677     return false;
2678   }
2679   if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
2680     $tech = "custom";
2681   } else {
2682     $tech = strtolower( strtok($results[0][0],'/') ); // the technology.  ie: ZAP/g0 is ZAP
2683    
2684     if ($tech == "iax2") $tech = "iax"; // same thing, here
2685   }
2686   return $tech;
2687 }
2688
2689 //add trunk info to sip or iax table
2690 function core_trunks_addSipOrIax($config,$table,$channelid,$trunknum,$disable_flag=0) {
2691   global $db;
2692  
2693   $confitem['account'] = $channelid;
2694   $gimmieabreak = nl2br($config);
2695   $lines = split('<br />',$gimmieabreak);
2696   foreach ($lines as $line) {
2697     $line = trim($line);
2698     if (count(split('=',$line)) > 1) {
2699       $tmp = split('=',$line,2);
2700       $key=trim($tmp[0]);
2701       $value=trim($tmp[1]);
2702       if (isset($confitem[$key]) && !empty($confitem[$key]))
2703         $confitem[$key].="&".$value;
2704       else
2705         $confitem[$key]=$value;
2706     }
2707   }
2708   // rember 1=disabled so we start at 2 (1 + the first 1)
2709   $seq = 1;
2710   foreach($confitem as $k=>$v) {
2711     $seq = ($disable_flag == 1) ? 1 : $seq+1;
2712     $dbconfitem[]=array($k,$v,$seq);
2713   }
2714   $compiled = $db->prepare("INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,?)");
2715   $result = $db->executeMultiple($compiled,$dbconfitem);
2716   if(DB::IsError($result)) {
2717     die_freepbx($result->getMessage()."<br><br>INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')"); 
2718   }
2719 }
2720
2721 //get unique trunks
2722 function core_trunks_list($assoc = false) {
2723   // TODO: $assoc default to true, eventually..
2724
2725   global $db;
2726   global $amp_conf;
2727  
2728   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2729   {
2730     // TODO: sqlite work arround - diego
2731     // TODO: WILL NOT WORK, need to remove the usage of SUBSTRING
2732     // need to reorder the trunks in PHP code
2733     $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
2734     $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\_%') d ";
2735     $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\_%' ";
2736     $sqlstr .= "UNION ALL ";
2737     $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
2738     $sqlstr .= "WHERE v.variable LIKE 'OUT\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
2739     $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\_%' ) ";
2740     $sqlstr .= "ORDER BY variable";
2741
2742     //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT_%' ORDER BY variable","getAll");
2743     $unique_trunks = sql($sqlstr,"getAll");
2744   }
2745   else
2746   {
2747     // we have to escape _ for mysql: normally a wildcard
2748     $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
2749     $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\\\_%') d ";
2750     $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\\\_%' ";
2751     $sqlstr .= "UNION ALL ";
2752     $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
2753     $sqlstr .= "WHERE v.variable LIKE 'OUT\\\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
2754     $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\\\_%' ) ";
2755     $sqlstr .= "ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0";
2756
2757     //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT\\\_%' ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0","getAll");
2758     $unique_trunks = sql($sqlstr,"getAll");
2759   }
2760
2761   //if no trunks have ever been defined, then create the proper variables with the default zap trunk
2762   if (count($unique_trunks) == 0)
2763   {
2764     //If all trunks have been deleted from admin, dialoutids might still exist
2765     sql("DELETE FROM globals WHERE variable = 'DIALOUTIDS'");
2766  
2767     $glofields = array(array('OUT_1','ZAP/g0'),
2768               array('DIAL_OUT_1','9'),
2769               array('DIALOUTIDS','1'));
2770     $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
2771     $result = $db->executeMultiple($compiled,$glofields);
2772     if(DB::IsError($result))
2773     {
2774       die_freepbx($result->getMessage()."<br><br>".$sql);
2775     }
2776     $unique_trunks[] = array('OUT_1','ZAP/g0');
2777   }
2778   // asort($unique_trunks);
2779
2780   if ($assoc) {
2781     $trunkinfo = array();
2782
2783     foreach ($unique_trunks as $trunk) {
2784       list($tech,$name) = explode('/',$trunk[1]);
2785       $trunkinfo[$name] = array(
2786         'name' => $name,
2787         'tech' => $tech,
2788         'globalvar' => $trunk[0], // ick
2789         'value' => $trunk[2], // ??  no idea what this is.
2790       ); 
2791     }
2792     return $trunkinfo;
2793   } else {
2794     return $unique_trunks;
2795   }
2796 }
2797
2798 //write the OUTIDS global variable (used in dialparties.agi)
2799 function core_trunks_writeoutids() {
2800   // we have to escape _ for mysql: normally a wildcard
2801   $unique_trunks = sql("SELECT variable FROM globals WHERE variable LIKE 'OUT\\\_%'","getAll");
2802
2803   $outids = null; // Start off with nothing
2804   foreach ($unique_trunks as $unique_trunk) {
2805     $outid = strtok($unique_trunk[0],"_");
2806     $outid = strtok("_");
2807     $outids .= $outid ."/";
2808   }
2809  
2810   sql("UPDATE globals SET value = '$outids' WHERE variable = 'DIALOUTIDS'");
2811 }
2812
2813 function core_trunks_addRegister($trunknum,$tech,$reg,$disable_flag=0) {
2814   sql("INSERT INTO $tech (id, keyword, data, flags) values ('9999999$trunknum','register','$reg','$disable_flag')");
2815 }
2816
2817
2818 function core_trunks_addDialRules($trunknum, $dialrules) {
2819   $values = array();
2820   $i = 1;
2821   foreach ($dialrules as $rule) {
2822     $values["rule".$i++] = $rule;
2823   }
2824  
2825   $conf = core_trunks_readDialRulesFile();
2826  
2827   // rewrite for this trunk
2828   $conf["trunk-".$trunknum] = $values;
2829  
2830   core_trunks_writeDialRulesFile($conf);
2831 }
2832
2833 function core_trunks_readDialRulesFile() {
2834   global $amp_conf;
2835   $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
2836  
2837   core_trunks_parse_conf($localPrefixFile, $conf, $section);
2838  
2839   return $conf;
2840 }
2841
2842 function core_trunks_writeDialRulesFile($conf) {
2843   global $amp_conf;
2844   $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
2845  
2846   $fd = fopen($localPrefixFile,"w");
2847   foreach ($conf as $section=>$values) {
2848     fwrite($fd, "[".$section."]\n");
2849     foreach ($values as $key=>$value) {
2850       fwrite($fd, $key."=".$value."\n");
2851     }
2852     fwrite($fd, "\n");
2853   }
2854   fclose($fd);
2855 }
2856
2857 function core_trunks_parse_conf($filename, &$conf, &$section) {
2858   if (is_null($conf)) {
2859     $conf = array();
2860   }
2861   if (is_null($section)) {
2862     $section = "general";
2863   }
2864  
2865   if (file_exists($filename)) {
2866     $fd = fopen($filename, "r");
2867     while ($line = fgets($fd, 1024)) {
2868       if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
2869         // name = value
2870         // option line
2871         $conf[$section][ $matches[1] ] = $matches[2];
2872       } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
2873         // section name
2874         $section = strtolower($matches[1]);
2875       } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
2876         // include another file
2877        
2878         if ($matches[1][0] == "/") {
2879           // absolute path
2880           $filename = $matches[1];
2881         } else {
2882           // relative path
2883           $filename =  dirname($filename)."/".$matches[1];
2884         }
2885        
2886         core_trunks_parse_conf($filename, $conf, $section);
2887       }
2888     }
2889   }
2890 }
2891
2892 function core_trunks_getTrunkTrunkName($trunknum) {
2893   $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
2894   if (!$results) {
2895     return false;
2896   }
2897  
2898   if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
2899     $tname = substr($results[0][0],4);
2900   } else {
2901   strtok($results[0][0],'/');
2902     $tname = strtok('/'); // the text _after_ technology.  ie: ZAP/g0 is g0
2903   }
2904   return $tname;
2905 }
2906
2907 //get and print peer details (prefixed with 4 9's)
2908 function core_trunks_getTrunkPeerDetails($trunknum) {
2909   global $db;
2910  
2911   $tech = core_trunks_getTrunkTech($trunknum);
2912  
2913   if ($tech == "zap") return ""; // zap has no details
2914  
2915   $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999$trunknum' ORDER BY flags, keyword DESC","getAll");
2916  
2917   foreach ($results as $result) {
2918     if ($result[0] != 'account') {
2919       if (isset($confdetail))
2920         $confdetail .= $result[0] .'='. $result[1] . "\n";
2921       else
2922         $confdetail = $result[0] .'='. $result[1] . "\n";
2923     }
2924   }
2925   return $confdetail;
2926 }
2927
2928 //get trunk user context (prefixed with 5 9's)
2929 function core_trunks_getTrunkUserContext($trunknum) {
2930   $tech = core_trunks_getTrunkTech($trunknum);
2931   if ($tech == "zap") return ""; // zap has no account
2932  
2933   $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum'","getAll");
2934
2935   foreach ($results as $result) {
2936     if ($result[0] == 'account') {
2937       $account = $result[1];
2938     }
2939   }
2940   return isset($account)?$account:null;
2941 }
2942
2943 //get and print user config (prefixed with 5 9's)
2944 function core_trunks_getTrunkUserConfig($trunknum) {
2945   global $db;
2946  
2947   $tech = core_trunks_getTrunkTech($trunknum);
2948  
2949   if ($tech == "zap") return ""; // zap has no details
2950  
2951   $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY flags, keyword DESC","getAll");
2952
2953   foreach ($results as $result) {
2954     if ($result[0] != 'account') {
2955       if (isset($confdetail))
2956         $confdetail .= $result[0] .'='. $result[1] . "\n";
2957       else
2958         $confdetail = $result[0] .'='. $result[1] . "\n";
2959     }
2960   }
2961   return isset($confdetail)?$confdetail:null;
2962 }
2963
2964 //get trunk account register string
2965 function core_trunks_getTrunkRegister($trunknum) {
2966   $tech = core_trunks_getTrunkTech($trunknum);
2967  
2968   if ($tech == "zap") return ""; // zap has no register
2969  
2970   $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999999$trunknum'","getAll");
2971
2972   foreach ($results as $result) {
2973       $register = $result[1];
2974   }
2975   return isset($register)?$register:null;
2976 }
2977
2978 function core_trunks_getDialRules($trunknum) {
2979   $conf = core_trunks_readDialRulesFile();
2980   if (isset($conf["trunk-".$trunknum])) {
2981     return $conf["trunk-".$trunknum];
2982   }
2983   return false;
2984 }
2985
2986 //get outbound routes for a given trunk
2987 function core_trunks_gettrunkroutes($trunknum) {
2988   global $amp_conf;
2989
2990   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2991     $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";
2992   else
2993     $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";
2994
2995   $results = sql( $sql_code, "getAll" );
2996
2997   foreach ($results as $row) {
2998     // original code was:
2999     //  $routes[$row[0]] = $row[1];
3000     // but substring is not supported in sqlite3.
3001     // how about we remove the 2nd part of the "if"? and use the same code on all DB's?
3002
3003     $t = ($amp_conf["AMPDBENGINE"] == "sqlite3") ? substr( $row[0], 7 ) : $row[0];
3004     $r = $row[1];
3005     $routes[ $r ] = $t;
3006
3007   }
3008   // array(routename=>priority)
3009   return isset($routes)?$routes:null;
3010 }
3011
3012 function core_trunks_deleteDialRules($trunknum) {
3013   $conf = core_trunks_readDialRulesFile();
3014  
3015   // remove rules for this trunk
3016   unset($conf["trunk-".$trunknum]);
3017  
3018   core_trunks_writeDialRulesFile($conf);
3019 }
3020
3021 /* end page.trunks.php functions */
3022
3023
3024 /* begin page.routing.php functions */
3025
3026 //get unique outbound route names
3027 function core_routing_getroutenames()
3028 {
3029   global $amp_conf;
3030  
3031   if ($amp_conf["AMPDBENGINE"] == "sqlite3")
3032   {
3033     // SUBSTRING is not supported under sqlite3, we need to filter
3034     // this in php. I am not sure why "6" and not "7"
3035     // but I don't really care -> it works :)
3036     $results = sql("SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
3037     foreach( array_keys($results) as $idx )
3038     {
3039        $results[$idx][0] = substr( $results[$idx][0], 6);
3040     }
3041   }
3042   else
3043   {
3044     // we SUBSTRING() to remove "outrt-"
3045     $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
3046   }
3047
3048
3049   //TODO: This needs to be yanked, should be in the upgrade script somewhere not here
3050   //
3051   if (count($results) == 0) {
3052     // see if they're still using the old dialprefix method
3053     $results = sql("SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\\\_OUT\\\_%'","getAll");
3054     // we SUBSTRING() to remove "outrt-"
3055    
3056     if (count($results) > 0) {
3057       // yes, they are using old method, let's update
3058      
3059       // get the default trunk
3060       $results_def = sql("SELECT value FROM globals WHERE variable = 'OUT'","getAll");
3061      
3062       if (preg_match("/{OUT_(\d+)}/", $results_def[0][0], $matches)) {
3063         $def_trunk = $matches[1];
3064       } else {
3065         $def_trunk = "";
3066       }
3067      
3068       $default_patterns = array(  // default patterns that used to be in extensions.conf
3069             "NXXXXXX",
3070             "NXXNXXXXXX",
3071             "1800NXXXXXX",
3072             "1888NXXXXXX",
3073             "1877NXXXXXX",
3074             "1866NXXXXXX",
3075             "1NXXNXXXXXX",
3076             "011.",
3077             "911",
3078             "411",
3079             "311",
3080             );
3081      
3082       foreach ($results as $temp) {
3083         // temp[0] is "DIAL_OUT_1"
3084         // temp[1] is the dial prefix
3085        
3086         $trunknum = substr($temp[0],9);
3087        
3088         $name = "route".$trunknum;
3089        
3090         $trunks = array(1=>"OUT_".$trunknum); // only one trunk to use
3091        
3092         $patterns = array();
3093         foreach ($default_patterns as $pattern) {
3094           $patterns[] = $temp[1]."|".$pattern;
3095         }
3096        
3097         if ($trunknum == $def_trunk) {
3098           // this is the default trunk, add the patterns with no prefix
3099           $patterns = array_merge($patterns, $default_patterns);
3100         }
3101        
3102         // add this as a new route
3103         core_routing_add($name, $patterns, $trunks,"new");
3104       }
3105      
3106      
3107       // delete old values
3108       sql("DELETE FROM globals WHERE (variable LIKE 'DIAL\\\_OUT\\\_%') OR (variable = 'OUT') ");
3109
3110       // we need to re-generate extensions_additional.conf
3111       // i'm not sure how to do this from here
3112      
3113       // re-run our query
3114       $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
3115       // we SUBSTRING() to remove "outrt-"
3116     }
3117    
3118   } // else, it just means they have no routes.
3119  
3120   return $results;
3121 }
3122
3123 function core_routing_setroutepriority($routepriority, $reporoutedirection, $reporoutekey)
3124 {
3125   global $db, $amp_conf;
3126   $counter=-1;
3127   foreach ($routepriority as $tresult)
3128   {
3129     $counter++;
3130     if (($counter==($reporoutekey-1)) && ($reporoutedirection=="up")) {
3131       // swap this one with the one before (move up)
3132       $temproute = $routepriority[$counter];
3133       $routepriority[ $counter ] = $routepriority[ $counter+1 ];
3134       $routepriority[ $counter+1 ] = $temproute;
3135      
3136     } else if (($counter==($reporoutekey)) && ($reporoutedirection=="down")) {
3137       // swap this one with the one after (move down)
3138       $temproute = $routepriority[ $counter+1 ];
3139       $routepriority[ $counter+1 ] = $routepriority[ $counter ];
3140       $routepriority[ $counter ] = $temproute;
3141     }
3142   }
3143   unset($temptrunk);
3144   $routepriority = array_values($routepriority); // resequence our numbers
3145   $counter=0;
3146   foreach ($routepriority as $tresult) {
3147     $order=core_routing_setroutepriorityvalue($counter++);
3148     $sql = sprintf("Update extensions set context='outrt-%s-%s' WHERE context='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
3149     $result = $db->query($sql);
3150     if(DB::IsError($result)) {     
3151       die_freepbx($result->getMessage());
3152     }
3153   }
3154  
3155   // Delete and readd the outbound-allroutes entries
3156   $sql = "delete from  extensions WHERE context='outbound-allroutes'";
3157   $result = $db->query($sql);
3158   if(DB::IsError($result)) {
3159           die_freepbx($result->getMessage().$sql);
3160   }
3161  
3162   $sql = "SELECT DISTINCT context FROM extensions WHERE context like 'outrt-%' ORDER BY context";
3163   $results = $db->getAll($sql);
3164   if(DB::IsError($results)) {
3165     die_freepbx($results->getMessage());
3166   }
3167
3168   $priority_loops=1; 
3169   foreach ($results as $row) {
3170     $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
3171     $sql .= "('outbound-allroutes', ";
3172     $sql .= "'include', ";
3173     $sql .= "'".$priority_loops++."', ";
3174     $sql .= "'".$row[0]."', ";
3175     $sql .= "'', ";
3176     $sql .= "'', ";
3177     $sql .= "'2')";
3178  
3179     //$sql = sprintf("Update extensions set application='outrt-%s-%s' WHERE context='outbound-allroutes' and  application='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
3180     $result = $db->query($sql);
3181     if(DB::IsError($result)) {     
3182       die_freepbx($result->getMessage(). $sql);
3183     }
3184   }
3185  
3186   if ( $amp_conf["AMPDBENGINE"] == "sqlite3")
3187     $sql = "SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
3188   else
3189     $sql = "SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
3190
3191         // we SUBSTRING() to remove "outrt-"
3192         $routepriority = $db->getAll($sql);
3193         if(DB::IsError($routepriority)) {
3194                 die_freepbx($routepriority->getMessage());
3195         }
3196
3197   // TODO: strip the context on the sqlite3 backend
3198   // not sure where does it effects, since this is working on my setup...
3199   // welcome to funky town
3200         return ($routepriority);
3201 }
3202
3203 function core_routing_setroutepriorityvalue($key)
3204 {
3205   $key=$key+1;
3206   if ($key<10)
3207     $prefix = sprintf("00%d",$key);
3208   else if ((9<$key)&&($key<100))
3209     $prefix = sprintf("0%d",$key);
3210   else if ($key>100)
3211     $prefix = sprintf("%d",$key);
3212   return ($prefix);
3213 }
3214
3215
3216 function core_routing_add($name, $patterns, $trunks, $method, $pass, $emergency = "", $intracompany = "", $mohsilence = "") {
3217
3218   global $db;
3219
3220   $trunktech=array();
3221
3222   //Retrieve each trunk tech for later lookup
3223   $sql="select * from globals WHERE variable LIKE 'OUT\\_%'";
3224         $result = $db->getAll($sql);
3225         if(DB::IsError($result)) {
3226     die_freepbx($result->getMessage());
3227   }
3228   foreach($result as $tr) {
3229     $tech = strtok($tr[1], "/");
3230     $trunktech[$tr[0]]=$tech;
3231   }
3232  
3233   if ($method=="new") {
3234     $sql="select DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context";
3235     $routepriority = $db->getAll($sql);
3236     if(DB::IsError($result)) {
3237       die_freepbx($result->getMessage());
3238     }
3239     $order=core_routing_setroutepriorityvalue(count($routepriority));
3240     $name = sprintf ("%s-%s",$order,$name);
3241   }
3242   $trunks = array_values($trunks); // probably already done, but it's important for our dialplan
3243
3244  
3245   foreach ($patterns as $pattern) {
3246     if (false !== ($pos = strpos($pattern,"|"))) {
3247       // we have a | meaning to not pass the digits on
3248       // (ie, 9|NXXXXXX should use the pattern _9NXXXXXX but only pass NXXXXXX, not the leading 9)
3249      
3250       $pattern = str_replace("|","",$pattern); // remove all |'s
3251       $exten = "EXTEN:".$pos; // chop off leading digit
3252     } else {
3253       // we pass the full dialed number as-is
3254       $exten = "EXTEN";
3255     }
3256    
3257     if (!preg_match("/^[0-9*]+$/",$pattern)) {
3258       // note # is not here, as asterisk doesn't recoginize it as a normal digit, thus it requires _ pattern matching
3259      
3260       // it's not strictly digits, so it must have patterns, so prepend a _
3261       $pattern = "_".$pattern;
3262     }
3263    
3264     // 1st priority is emergency dialing variable (if set)
3265     if(!empty($emergency)) {
3266       $startpriority = 1;
3267       $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
3268       $sql .= "('outrt-".$name."', ";
3269       $sql .= "'".$pattern."', ";
3270       $sql .= "'".$startpriority."', ";
3271       $sql .= "'SetVar', ";
3272       $sql .= "'EMERGENCYROUTE=YES', ";
3273       $sql .= "'Use Emergency CID for device')";
3274       $result = $db->query($sql);
3275       if(DB::IsError($result)) {
3276         die_freepbx($result->getMessage());
3277       }
3278     } else {
3279       $startpriority = 0;
3280     }
3281
3282     // Next Priority (either first or second depending on above)
3283     if(!empty($intracompany)) {
3284          $startpriority += 1;
3285          $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
3286          $sql .= "('outrt-".$name."', ";
3287          $sql .= "'".$pattern."', ";
3288          $sql .= "'".$startpriority."', ";
3289          $sql .= "'SetVar', ";
3290          $sql .= "'INTRACOMPANYROUTE=YES', ";
3291          $sql .= "'Preserve Intenal CID Info')";
3292          $result = $db->query($sql);
3293         if(DB::IsError($result)) {
3294              die_freepbx($result->getMessage());
3295         }
3296     }
3297
3298     // Next Priority (either first, second or third depending on above)
3299     if(!empty($mohsilence) && trim($mohsilence) != 'default') {
3300          $startpriority += 1;
3301          $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
3302          $sql .= "('outrt-".$name."', ";
3303          $sql .= "'".$pattern."', ";
3304          $sql .= "'".$startpriority."', ";
3305          $sql .= "'SetVar', ";
3306          $sql .= "'MOHCLASS=".$mohsilence."', ";
3307          $sql .= "'Do not play moh on this route')";
3308          $result = $db->query($sql);
3309         if(DB::IsError($result)) {
3310              die_freepbx($result->getMessage());
3311         }
3312     }
3313
3314     $first_trunk = 1;
3315     foreach ($trunks as $priority => $trunk) {
3316       $priority += $startpriority;
3317       $priority += 1; // since arrays are 0-based, but we want priorities to start at 1
3318      
3319       $sql = "INSERT INTO extensions (context, extension, priority, application, args) VALUES ";
3320       $sql .= "('outrt-".$name."', ";
3321       $sql .= "'".$pattern."', ";
3322       $sql .= "'".$priority."', ";
3323       $sql .= "'Macro', ";
3324       if ($first_trunk)
3325         $pass_str = $pass;
3326       else
3327         $pass_str = "";
3328
3329       if ($trunktech[$trunk] == "ENUM")
3330         $sql .= "'dialout-enum,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
3331       else
3332         $sql .= "'dialout-trunk,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
3333       $sql .= ")";
3334      
3335       $result = $db->query($sql);
3336       if(DB::IsError($result)) {
3337         die_freepbx($result->getMessage());
3338       }
3339       //To identify the first trunk in a pattern
3340       //so that passwords are in the first trunk in
3341       //each pattern
3342       $first_trunk = 0;
3343     }
3344    
3345     $priority += 1;
3346     $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
3347     $sql .= "('outrt-".$name."', ";
3348     $sql .= "'".$pattern."', ";
3349     $sql .= "'".$priority."', ";
3350     $sql .= "'Macro', ";
3351     $sql .= "'outisbusy', ";
3352     $sql .= "'No available circuits')";
3353    
3354     $result = $db->query($sql);
3355     if(DB::IsError($result)) {
3356       die_freepbx($result->getMessage());
3357     }
3358   }
3359
3360  
3361   // add an include=>outrt-$name  to [outbound-allroutes]:
3362  
3363   // we have to find the first available priority.. priority doesn't really matter for the include, but
3364   // there is a unique index on (context,extension,priority) so if we don't do this we can't put more than
3365   // one route in the outbound-allroutes context.
3366   $sql = "SELECT priority FROM extensions WHERE context = 'outbound-allroutes' AND extension = 'include'";
3367   $results = $db->getAll($sql);
3368   if(DB::IsError($results)) {
3369     die_freepbx($results->getMessage());
3370   }
3371   $priorities = array();
3372   foreach ($results as $row) {
3373     $priorities[] = $row[0];
3374   }
3375   for ($priority = 1; in_array($priority, $priorities); $priority++);
3376  
3377   // $priority should now be the lowest available number
3378  
3379   $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
3380   $sql .= "('outbound-allroutes', ";
3381   $sql .= "'include', ";
3382   $sql .= "'".$priority."', ";
3383   $sql .= "'outrt-".$name."', ";
3384   $sql .= "'', ";
3385   $sql .= "'', ";
3386   $sql .= "'2')";
3387  
3388   $result = $db->query($sql);
3389   if(DB::IsError($result)) {
3390     die_freepbx($priority.$result->getMessage());
3391   }
3392  
3393 }
3394
3395 function core_routing_edit($name, $patterns, $trunks, $pass, $emergency="", $intracompany = "", $mohsilence="") {
3396   core_routing_del($name);
3397   core_routing_add($name, $patterns, $trunks,"edit", $pass, $emergency, $intracompany, $mohsilence);
3398 }
3399
3400 function core_routing_del($name) {
3401   global $db;
3402   $sql = "DELETE FROM extensions WHERE context = 'outrt-".$name."'";
3403   $result = $db->query($sql);
3404   if(DB::IsError($result)) {
3405     die_freepbx($result->getMessage());
3406   }
3407  
3408   $sql = "DELETE FROM extensions WHERE context = 'outbound-allroutes' AND application = 'outrt-".$name."' ";
3409   $result = $db->query($sql);
3410   if(DB::IsError($result)) {
3411     die_freepbx($result->getMessage());
3412   }
3413  
3414   return $result;
3415 }
3416
3417 function core_routing_rename($oldname, $newname) {
3418   global $db;
3419
3420   $route_prefix=substr($oldname,0,4);
3421   $newname=$route_prefix.$newname;
3422   $sql = "SELECT context FROM extensions WHERE context = 'outrt-".$newname."'";
3423   $results = $db->getAll($sql);
3424   if (count($results) > 0) {
3425     // there's already a route with this name
3426     return false;
3427   }
3428  
3429   $sql = "UPDATE extensions SET context = 'outrt-".$newname."' WHERE context = 'outrt-".$oldname."'";
3430   $result = $db->query($sql);
3431   if(DB::IsError($result)) {
3432     die_freepbx($result->getMessage());
3433   }
3434         $mypriority=sprintf("%d",$route_prefix); 
3435   $sql = "UPDATE extensions SET application = 'outrt-".$newname."', priority = '$mypriority' WHERE context = 'outbound-allroutes' AND application = 'outrt-".$oldname."' ";
3436   $result = $db->query($sql);
3437   if(DB::IsError($result)) {
3438     die_freepbx($result->getMessage());
3439   }
3440  
3441   return true;
3442 }
3443
3444 //get unique outbound route patterns for a given context
3445 function core_routing_getroutepatterns($route) {
3446   global $db;
3447   $sql = "SELECT extension, args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk%' OR args LIKE'dialout-enum%') ORDER BY extension ";
3448   $results = $db->getAll($sql);
3449   if(DB::IsError($results)) {
3450     die_freepbx($results->getMessage());
3451   }
3452  
3453   $patterns = array();
3454   foreach ($results as $row) {
3455     if ($row[0][0] == "_") {
3456       // remove leading _
3457       $pattern = substr($row[0],1);
3458     } else {
3459       $pattern = $row[0];
3460     }
3461    
3462     if (preg_match("/{EXTEN:(\d+)}/", $row[1], $matches)) {
3463       // this has a digit offset, we need to insert a |
3464       $pattern = substr($pattern,0,$matches[1])."|".substr($pattern,$matches[1]);
3465     }
3466    
3467     $patterns[] = $pattern;
3468   }
3469   return array_unique($patterns);
3470 }
3471
3472 //get unique outbound route trunks for a given context
3473 function core_routing_getroutetrunks($route) {
3474   global $db;
3475   $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) ";
3476   $results = $db->getAll($sql);
3477   if(DB::IsError($results)) {
3478     die_freepbx($results->getMessage());
3479   }
3480  
3481   $trunks = array();
3482   foreach ($results as $row) {
3483     if (preg_match('/^dialout-trunk,(\d+)/', $row[0], $matches)) {
3484       // check in_array -- even though we did distinct
3485       // we still might get ${EXTEN} and ${EXTEN:1} if they used | to split a pattern
3486       if (!in_array("OUT_".$matches[1], $trunks)) {
3487         $trunks[] = "OUT_".$matches[1];
3488       }
3489     } else if (preg_match('/^dialout-enum,(\d+)/', $row[0], $matches)) {
3490       if (!in_array("OUT_".$matches[1], $trunks)) {
3491         $trunks[] = "OUT_".$matches[1];
3492       }
3493     }
3494   }
3495   return $trunks;
3496 }
3497
3498
3499 //get password for this route
3500 function core_routing_getroutepassword($route) {
3501   global $db;
3502   $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) ";
3503   $results = $db->getOne($sql);
3504   if(DB::IsError($results)) {
3505     die_freepbx($results->getMessage());
3506   }
3507   if (preg_match('/^.*,.*,.*,(\d+|\/\S+)/', $results, $matches)) {
3508     $password = $matches[1];
3509   } else {
3510     $password = "";
3511   }
3512  
3513   return $password;
3514 }
3515
3516 //get emergency state for this route
3517 function core_routing_getrouteemergency($route) {
3518   global $db;
3519   $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'EMERGENCYROUTE%') ";
3520   $results = $db->getOne($sql);
3521   if(DB::IsError($results)) {
3522     die_freepbx($results->getMessage());
3523   }
3524   if (preg_match('/^.*=(.*)/', $results, $matches)) {
3525     $emergency = $matches[1];
3526   } else {
3527     $emergency = "";
3528   }
3529  
3530   return $emergency;
3531 }
3532
3533 //get intracompany routing status for this route
3534 function core_routing_getrouteintracompany($route) {
3535
3536        global $db;
3537        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'INTRACOMPANYROUTE%') ";
3538        $results = $db->getOne($sql);
3539        if(DB::IsError($results)) {
3540                die_freepbx($results->getMessage());
3541        }
3542        if (preg_match('/^.*=(.*)/', $results, $matches)) {
3543                $intracompany = $matches[1];
3544        } else {
3545                $intracompany = "";
3546        }
3547        return $intracompany;
3548 }
3549
3550 //get mohsilence routing status for this route
3551 function core_routing_getroutemohsilence($route) {
3552
3553        global $db;
3554        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'MOHCLASS%') ";
3555        $results = $db->getOne($sql);
3556        if(DB::IsError($results)) {
3557                die_freepbx($results->getMessage());
3558        }
3559        if (preg_match('/^.*=(.*)/', $results, $matches)) {
3560                $mohsilence = $matches[1];
3561        } else {
3562                $mohsilence = "";
3563        }
3564        return $mohsilence;
3565 }
3566
3567 function general_get_zonelist() {
3568   return array(
3569  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"),
3570  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"),
3571  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"),
3572  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"),
3573  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"),
3574  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"),
3575  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"),
3576  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"),
3577  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"),
3578  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"),
3579  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"),
3580  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"),
3581  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"),
3582  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"),
3583  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"),
3584  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"),
3585  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"),
3586  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"),
3587  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"),
3588  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"),
3589  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"),
3590  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"),
3591  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"),
3592  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"),
3593  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"),
3594  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"),
3595  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"),
3596  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"),
3597  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"),
3598  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"),
3599  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"),
3600  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"),
3601  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"),
3602  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"),
3603  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"),);
3604 }
3605
3606 function general_display_zones($curzone) {
3607   $zonelist = general_get_zonelist();
3608   echo "<select name='TONEZONE'>\n";
3609   foreach ($zonelist as $zone) {
3610     if ($zone['iso'] == $curzone)
3611       echo "<option selected value='{$zone['iso']}'>{$zone['name']}</option>\n";
3612     else 
3613       echo "<option value='{$zone['iso']}'>{$zone['name']}</option>\n";
3614   }
3615   echo "</select>";
3616  
3617 }
3618
3619 function general_generate_indications() {
3620   global $db;
3621   global $asterisk_conf;
3622
3623   $sql = "SELECT value FROM globals WHERE variable='TONEZONE'";
3624   $result = $db->getRow($sql,DB_FETCHMODE_ASSOC);
3625
3626   $filename = isset($asterisk_conf["astetcdir"]) && $asterisk_conf["astetcdir"] != '' ? rtrim($asterisk_conf["astetcdir"],DIRECTORY_SEPARATOR) : "/etc/asterisk";
3627   $filename .= "/indications.conf";
3628   $fd = fopen($filename, "w");
3629   fwrite($fd, "[general]\ncountry=".$result['value']."\n\n");
3630
3631   $zonelist = general_get_zonelist();
3632   foreach ($zonelist as $zone) {
3633     fwrite($fd, "[{$zone['iso']}]\n{$zone['conf']}\n\n");
3634   }
3635   fclose($fd);
3636 }
3637 /* end page.routing.php functions */
3638
3639
3640
3641 // init registered 'your' config load and config process functions
3642 function core_users_configpageinit($dispnum) {
3643   global $currentcomponent;
3644   global $amp_conf;
3645
3646   if ( $dispnum == 'users' || $dispnum == 'extensions' ) {
3647     // Setup option list we need
3648     $currentcomponent->addoptlistitem('recordoptions', 'Adhoc', _("On Demand"));
3649     $currentcomponent->addoptlistitem('recordoptions', 'Always', _("Always"));
3650     $currentcomponent->addoptlistitem('recordoptions', 'Never', _("Never"));
3651     $currentcomponent->setoptlistopts('recordoptions', 'sort', false);
3652
3653     $currentcomponent->addoptlistitem('faxdetecttype', '0', _("None"));
3654     $currentcomponent->addoptlistitem('faxdetecttype', '1', 'Zaptel');
3655     $currentcomponent->addoptlistitem('faxdetecttype', '2', 'NVFax');
3656     $currentcomponent->setoptlistopts('faxdetecttype', 'sort', false);
3657
3658     $currentcomponent->addoptlistitem('privyn', '0', _("No"));
3659     $currentcomponent->addoptlistitem('privyn', '1', _("Yes"));
3660     $currentcomponent->setoptlistopts('privyn', 'sort', false);
3661
3662     $currentcomponent->addoptlistitem('callwaiting', 'enabled', _("Enable"));
3663     $currentcomponent->addoptlistitem('callwaiting', 'disabled', _("Disable"));
3664     $currentcomponent->setoptlistopts('callwaiting', 'sort', false);
3665
3666     $currentcomponent->addoptlistitem('ringtime', '0', 'Default');
3667     for ($i=1; $i <= 120; $i++) {
3668       $currentcomponent->addoptlistitem('ringtime', "$i", "$i");
3669     }
3670     $currentcomponent->setoptlistopts('ringtime', 'sort', false);
3671
3672     $currentcomponent->addoptlistitem('faxdestoptions', 'default', _("FreePBX default"));
3673     $currentcomponent->addoptlistitem('faxdestoptions', 'disabled', _("disabled"));
3674     $currentcomponent->addoptlistitem('faxdestoptions', 'system', _("system"));
3675     $currentcomponent->setoptlistopts('faxdestoptions', 'sort', false);
3676
3677     if (function_exists('music_list')) {
3678         $tresults = music_list($amp_conf['ASTVARLIBDIR']."/mohmp3");
3679         if (isset($tresults[0])) {
3680       foreach ($tresults as $tresult) {
3681           $currentcomponent->addoptlistitem('mohclass', $tresult, $tresult);
3682       }
3683         $currentcomponent->setoptlistopts('mohclass', 'sort', false);
3684         }
3685     }
3686
3687     //get unique devices to finishoff faxdestoptions list
3688     $devices = core_devices_list();
3689     if (isset($devices)) {
3690       foreach ($devices as $device) {
3691         $currentcomponent->addoptlistitem('faxdestoptions', $device[0], "$device[1] <$device[0]>");
3692       }
3693     }
3694
3695     // Add the 'proces' functions
3696     $currentcomponent->addguifunc('core_users_configpageload');
3697     // Ensure users is called in middle order ($sortorder = 5), this is to allow
3698     // other modules to call stuff before / after the processing of users if needed
3699     // e.g. Voicemail module needs to create mailbox BEFORE the users as the mailbox
3700     // context is needed by the add users function
3701     $currentcomponent->addprocessfunc('core_users_configprocess', 5);     
3702   }
3703 }
3704
3705 function core_users_configpageload() {
3706   global $currentcomponent;
3707   global $amp_conf;
3708
3709   // Ensure variables possibly extracted later exist
3710   $name = $directdid = $didalert = $outboundcid = $answer = null;
3711   $record_in = $record_out = $faxexten = $faxemail = $mohclass = $sipname = $cid_masquerade = null;
3712
3713   // Init vars from $_REQUEST[]
3714   $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
3715   $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
3716   $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
3717   $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
3718
3719   if ( $action == 'del' ) { // Deleted
3720
3721     $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
3722
3723   } elseif ( $display == 'extensions' && ($extdisplay == '' && $tech_hardware == '') ) { // Adding
3724
3725     // do nothing as you want the Devices to handle this bit
3726
3727   } else {
3728
3729     $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
3730  
3731     if ( is_string($extdisplay) ) {
3732
3733       if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3734         $extenInfo=core_users_get($extdisplay);
3735         extract($extenInfo);
3736       }
3737       if (isset($deviceInfo) && is_array($deviceInfo))
3738         extract($deviceInfo);
3739  
3740       if ( $display == 'extensions' ) {
3741         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Extension").": $extdisplay", false), 0);
3742         if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3743           $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Extension")." $extdisplay", $delURL, true, false), 0);
3744
3745           $usage_list = framework_display_destination_usage(core_getdest($extdisplay));
3746           if (!empty($usage_list)) {
3747             $currentcomponent->addguielem('_top', new gui_link_label('dests', $usage_list['text'], $usage_list['tooltip'], true), 0);
3748           }
3749         }
3750       } else {
3751         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("User").": $extdisplay", false), 0);
3752         if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3753           $currentcomponent->addguielem('_top', new gui_link('del', _("Delete User")." $extdisplay", $delURL, true, false), 0);
3754
3755           $usage_list = framework_display_destination_usage(core_getdest($extdisplay));
3756           if (!empty($usage_list)) {
3757             $currentcomponent->addguielem('_top', new gui_link_label('dests', $usage_list['text'], $usage_list['tooltip'], true), 0);
3758           }
3759         }
3760       }
3761
3762     } elseif ( $display != 'extensions' ) {
3763       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add User/Extension")), 0);
3764     }
3765    
3766     // Setup vars for use in the gui later on             
3767     $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
3768     $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
3769    
3770     $msgInvalidExtNum = _("Please enter a valid extension number.");
3771     $msgInvalidCidNum = _("Please enter a valid CID Num Alias (must be a valid number).");
3772     $msgInvalidExtPwd = _("Please enter valid User Password using numbers only");
3773     $msgInvalidDispName = _("Please enter a valid Display Name");
3774     $msgInvalidOutboundCID = _("Please enter a valid Outbound CID");
3775     $msgInvalidPause = _("Please enter a valid pause time in seconds, using digits only");
3776
3777     // This is the actual gui stuff
3778     $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
3779     $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
3780    
3781     if ( $display == 'extensions' ) {
3782       $section = ($extdisplay ? _("Edit Extension") : _("Add Extension"));     
3783     } else {
3784       $section = ($extdisplay ? _("Edit User") : _("Add User"));
3785     }
3786     if ( $extdisplay ) {
3787       $currentcomponent->addguielem($section, new gui_hidden('extension', $extdisplay), 2);
3788     } else {
3789       $currentcomponent->addguielem($section, new gui_textbox('extension', $extdisplay, 'User Extension', 'The extension number to dial to reach this user.', '!isInteger()', $msgInvalidExtNum, false), 3);
3790     }
3791     if ( $display != 'extensions' ) {
3792       $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));
3793       // extra JS function check required for blank password warning -- call last in the onsubmit() function
3794       $currentcomponent->addjsfunc('onsubmit()', "\treturn checkBlankUserPwd();\n", 9);
3795     }
3796     $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));
3797     $cid_masquerade = (trim($cid_masquerade) == $extdisplay)?"":$cid_masquerade;
3798     $currentcomponent->addguielem($section, new gui_textbox('cid_masquerade', $cid_masquerade, 'CID Num Alias', 'The CID Number to use for internal calls, if different from the extension number. This is used to masquerade as a different user. A common example is a team of support people who would like their internal callerid to display the general support number (a ringgroup or queue). There will be no effect on external calls.', '!isWhitespace() && !isInteger()', $msgInvalidCidNum, false));
3799     $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."));
3800    
3801     $section = 'Extension Options';
3802     $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);
3803     $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"));
3804     if (function_exists('music_list')) {
3805         $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));
3806     }
3807     $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));
3808     $ringtimer = (isset($ringtimer) ? $ringtimer : '0');
3809     $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));
3810     if (!isset($callwaiting)) {
3811       if ($amp_conf['ENABLECW']) {
3812         $callwaiting = 'enabled';
3813       } else {
3814         $callwaiting = 'disabled';
3815       }
3816     }
3817     $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));
3818
3819     $section = 'Recording Options';
3820     $currentcomponent->addguielem($section, new gui_selectbox('record_in', $currentcomponent->getoptlist('recordoptions'), $record_in, 'Record Incoming', "Record all inbound calls received at this extension.", false));
3821     $currentcomponent->addguielem($section, new gui_selectbox('record_out', $currentcomponent->getoptlist('recordoptions'), $record_out, 'Record Outgoing', "Record all outbound calls received at this extension.", false));
3822
3823     $section = 'Fax Handling';
3824     $wait = (isset($wait) ? $wait : '0');
3825     $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);
3826     $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"));
3827     $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));
3828     $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));
3829
3830     $section = 'Privacy';
3831     $privacyman = (isset($privacyman) ? $privacyman : '0');
3832     $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);
3833
3834   }
3835 }
3836
3837 function core_users_configprocess() {
3838   if ( !class_exists('agi_asteriskmanager') )
3839     include 'common/php-asmanager.php';
3840  
3841   //create vars from the request
3842   extract($_REQUEST);
3843  
3844   //make sure we can connect to Asterisk Manager
3845   if (!checkAstMan()) {
3846     return false;
3847   }
3848
3849   //check if the extension is within range for this user
3850   if (isset($extension) && !checkRange($extension)){
3851     echo "<script>javascript:alert('". _("Warning! Extension")." ".$extension." "._("is not allowed for your account").".');</script>";
3852     $GLOBALS['abort'] = true;
3853   } else {
3854     //if submitting form, update database
3855     if (!isset($action)) $action = null;
3856     switch ($action) {
3857       case "add":
3858         $conflict_url = array();
3859         $usage_arr = framework_check_extension_usage($_REQUEST['extension']);
3860         if (!empty($usage_arr)) {
3861           $GLOBALS['abort'] = true;
3862           $conflict_url = framework_display_extension_usage_alert($usage_arr,true);
3863           global $currentcomponent;
3864           $id=0;
3865           foreach ($conflict_url as $edit_link) {
3866             $currentcomponent->addguielem('_top', new gui_link('conflict'.$i++, $edit_link['label'], $edit_link['url']));
3867           }
3868         } elseif (core_users_add($_REQUEST)) {
3869           needreload();
3870           redirect_standard_continue();
3871         } else {
3872           // really bad hack - but if core_users_add fails, want to stop core_devices_add
3873           // Comment, this does not help everywhere. Other hooks functions can hook before
3874           // this like voicemail!
3875           //
3876           $GLOBALS['abort'] = true;
3877         }
3878       break;
3879       case "del":
3880         core_users_del($extdisplay);
3881         core_users_cleanastdb($extdisplay);
3882         if (function_exists('findmefollow_del')) {
3883             findmefollow_del($extdisplay);
3884         }
3885         needreload();
3886         redirect_standard_continue();
3887       break;
3888       case "edit":
3889         if (core_users_edit($extdisplay,$_REQUEST)) {
3890           needreload();
3891           redirect_standard_continue('extdisplay');
3892         } else {
3893           // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
3894           $GLOBALS['abort'] = true;
3895         }
3896       break;
3897     }
3898   }
3899   return true;
3900 }
3901
3902
3903 function core_devices_configpageinit($dispnum) {
3904   global $currentcomponent;
3905
3906   if ( $dispnum == 'devices' || $dispnum == 'extensions' ) {
3907     // Setup arrays for device types
3908     $currentcomponent->addgeneralarray('devtechs');
3909    
3910     // Some errors for the validation bits
3911     $msgInvalidDTMFMODE = _("Please enter the dtmfmode for this device");
3912     $msgInvalidChannel = _("Please enter the channel for this device");
3913     $msgConfirmSecret = _("You have not entered a Secret for this device, although this is possible it is generally bad practice to not assign a Secret to a device. Are you sure you want to leave the Secret empty?");
3914     $msgInvalidSecret = _("Please enter a Secret for this device");
3915    
3916     // zap
3917     $tmparr = array();
3918     $tmparr['channel'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidChannel);
3919     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
3920     $tmparr['immediate'] = array('value' => 'no', 'level' => 1);
3921     $tmparr['signalling'] = array('value' => 'fxo_ks', 'level' => 1);
3922     $tmparr['echocancel'] = array('value' => 'yes', 'level' => 1);
3923     $tmparr['echocancelwhenbridged'] = array('value' => 'no', 'level' => 1);
3924     $tmparr['echotraining'] = array('value' => '800', 'level' => 1);
3925     $tmparr['busydetect'] = array('value' => 'no', 'level' => 1);
3926     $tmparr['busycount'] = array('value' => '7', 'level' => 1);
3927     $tmparr['callprogress'] = array('value' => 'no', 'level' => 1);
3928     $tmparr['dial'] = array('value' => '', 'level' => 1);
3929     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3930     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3931     $currentcomponent->addgeneralarrayitem('devtechs', 'zap', $tmparr);
3932     unset($tmparr);
3933    
3934     // iax2
3935     $tmparr = array();
3936     $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
3937     $tmparr['notransfer'] = array('value' => 'yes', 'level' => 1);
3938     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
3939     $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
3940     $tmparr['type'] = array('value' => 'friend', 'level' => 1);
3941     $tmparr['port'] = array('value' => '4569', 'level' => 1);
3942     $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
3943     $tmparr['disallow'] = array('value' => '', 'level' => 1);
3944     $tmparr['allow'] = array('value' => '', 'level' => 1);
3945     $tmparr['dial'] = array('value' => '', 'level' => 1);
3946     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3947     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3948     $currentcomponent->addgeneralarrayitem('devtechs', 'iax2', $tmparr);
3949     unset($tmparr);
3950
3951     // sip
3952     $tmparr = array();
3953     $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
3954     $tmparr['dtmfmode'] = array('value' => 'rfc2833', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidDTMFMODE );
3955     $tmparr['canreinvite'] = array('value' => 'no', 'level' => 1);
3956     $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
3957     $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
3958     $tmparr['type'] = array('value' => 'friend', 'level' => 1);
3959     $tmparr['nat'] = array('value' => 'yes', 'level' => 1);
3960     $tmparr['port'] = array('value' => '5060', 'level' => 1);
3961     $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
3962     $tmparr['callgroup'] = array('value' => '', 'level' => 1);
3963     $tmparr['pickupgroup'] = array('value' => '', 'level' => 1);
3964     $tmparr['disallow'] = array('value' => '', 'level' => 1);
3965     $tmparr['allow'] = array('value' => '', 'level' => 1);
3966     $tmparr['dial'] = array('value' => '', 'level' => 1);
3967     $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3968     $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3969     $currentcomponent->addgeneralarrayitem('devtechs', 'sip', $tmparr);
3970     unset($tmparr);
3971
3972     // custom
3973     $tmparr = array();
3974     $tmparr['dial'] = array('value' => '', 'level' => 0);
3975     $currentcomponent->addgeneralarrayitem('devtechs', 'custom', $tmparr);
3976     unset($tmparr);
3977    
3978     // Devices list
3979     $currentcomponent->addoptlistitem('devicelist', 'sip_generic', _("Generic SIP Device"));
3980     $currentcomponent->addoptlistitem('devicelist', 'iax2_generic', _("Generic IAX2 Device"));
3981     $currentcomponent->addoptlistitem('devicelist', 'zap_generic', _("Generic ZAP Device"));
3982     $currentcomponent->addoptlistitem('devicelist', 'custom_custom', _("Other (Custom) Device"));
3983     $currentcomponent->setoptlistopts('devicelist', 'sort', false);
3984
3985
3986     // Option lists used by the gui
3987     $currentcomponent->addoptlistitem('devicetypelist', 'fixed', _("Fixed"));
3988     $currentcomponent->addoptlistitem('devicetypelist', 'adhoc', _("Adhoc"));
3989     $currentcomponent->setoptlistopts('devicetypelist', 'sort', false);
3990    
3991     $currentcomponent->addoptlistitem('deviceuserlist', 'none', _("none"));
3992     $currentcomponent->addoptlistitem('deviceuserlist', 'new', _("New User"));
3993     $users = core_users_list();
3994     if (isset($users)) {
3995       foreach ($users as $auser) {
3996         $currentcomponent->addoptlistitem('deviceuserlist', $auser[0], $auser[0]);
3997       }
3998     }
3999     $currentcomponent->setoptlistopts('deviceuserlist', 'sort', false);
4000
4001     // Add the 'proces' functions
4002     $currentcomponent->addguifunc('core_devices_configpageload');
4003     $currentcomponent->addprocessfunc('core_devices_configprocess');
4004   }
4005 }
4006
4007 function core_devices_configpageload() {
4008   global $currentcomponent;
4009
4010   // Init vars from $_REQUEST[]
4011   $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
4012   $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
4013   $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
4014   $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
4015  
4016   if ( $action == 'del' ) { // Deleted
4017
4018     if ( $display != 'extensions' )
4019       $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
4020
4021   } elseif ( $extdisplay == '' && $tech_hardware == '' ) { // Adding
4022
4023     if ( $display != 'extensions') {
4024       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add Device")), 0);
4025     } else {
4026       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add an Extension")), 0);
4027     }
4028     $currentcomponent->addguielem('_top', new gui_label('instructions', _("Please select your Device below then click Submit")));
4029     $currentcomponent->addguielem('Device', new gui_selectbox('tech_hardware', $currentcomponent->getoptlist('devicelist'), '', 'Device', '', false));
4030
4031   } else {
4032
4033     $deviceInfo = array();
4034     if ( $extdisplay ) { // Editing
4035
4036       $deviceInfo = core_devices_get($extdisplay);
4037
4038       if ( $display != 'extensions' ) {
4039         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Device").": $extdisplay", false), 0);
4040
4041         $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
4042         $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Device")." $extdisplay", $delURL, true, false), 0);
4043       }
4044  
4045     } else {
4046
4047       $tmparr = explode('_', $tech_hardware);
4048       $deviceInfo['tech'] = $tmparr[0];
4049       $deviceInfo['hardware'] = $tmparr[1];
4050       unset($tmparr);
4051      
4052       if ( $display != 'extensions' ) {
4053         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Device")), 0);
4054       } else {
4055         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Extension")), 0);
4056       }
4057
4058     }
4059
4060     // Ensure they exist before the extract
4061     $devinfo_description = $devinfo_emergency_cid = null;
4062     $devinfo_devicetype = $devinfo_user = $devinfo_hardware = null;
4063     if ( is_array($deviceInfo) )
4064       extract($deviceInfo, EXTR_PREFIX_ALL, 'devinfo');
4065
4066     // Setup vars for use in the gui later on             
4067     $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
4068     $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
4069
4070     $msgInvalidDevID = _("Please enter a device id.");
4071     $msgInvalidDevDesc = _("Please enter a valid Description for this device");
4072     $msgInvalidEmergCID = _("Please enter a valid Emergency CID");
4073     $msgInvalidExtNum = _("Please enter a valid extension number.");
4074    
4075     // Actual gui
4076     $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
4077     $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
4078
4079     if ( $display != 'extensions' ) {
4080       $section = 'Device Info';
4081       if ( $extdisplay ) { // Editing
4082         $currentcomponent->addguielem($section, new gui_hidden('deviceid', $extdisplay));
4083       } else { // Adding
4084         $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));
4085       }
4086       $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));
4087       $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));
4088       $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));
4089       $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));
4090     } else {
4091       $section = 'Extension Options';
4092       $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));
4093     }
4094     $currentcomponent->addguielem($section, new gui_hidden('tech', $devinfo_tech));
4095     $currentcomponent->addguielem($section, new gui_hidden('hardware', $devinfo_hardware));
4096
4097     $section = 'Device Options';
4098     $currentcomponent->addguielem($section, new gui_label('techlabel', sprintf(_("This device uses %s technology."),$devinfo_tech)),4);
4099     $devopts = $currentcomponent->getgeneralarrayitem('devtechs', $devinfo_tech);
4100     foreach ($devopts as $devopt=>$devoptarr) {
4101       $devopname = 'devinfo_'.$devopt;
4102       $devoptcurrent = isset($$devopname) ? $$devopname : $devoptarr['value'];
4103       $devoptjs = isset($devoptarr['jsvalidation']) ? $devoptarr['jsvalidation'] : '';
4104       $devoptfailmsg = isset($devoptarr['failvalidationmsg']) ? $devoptarr['failvalidationmsg'] : '';
4105      
4106       if ( $devoptarr['level'] == 0 || ($extdisplay && $devoptarr['level'] == 1) ) { // editing to show advanced as well
4107         $currentcomponent->addguielem($section, new gui_textbox($devopname, $devoptcurrent, $devopt, '', $devoptjs, $devoptfailmsg), 4);
4108       } else { // add so only basic
4109         $currentcomponent->addguielem($section, new gui_hidden($devopname, $devoptcurrent), 4);
4110       }
4111     }
4112   }
4113 }
4114
4115 function core_devices_configprocess() {
4116   if ( !class_exists('agi_asteriskmanager') )
4117     include 'common/php-asmanager.php';
4118
4119   //make sure we can connect to Asterisk Manager
4120   if (!checkAstMan()) {
4121     return false;
4122   }
4123  
4124   //create vars from the request
4125   extract($_REQUEST);
4126
4127   $extension = isset($extension)?$extension:null;
4128   $deviceid = isset($deviceid)?$deviceid:null;
4129   $name = isset($name)?$name:null;
4130   $action = isset($action)?$action:null;
4131
4132   // fixed users only in extensions mode
4133   if ( $display == 'extensions' ) {
4134     $devicetype = 'fixed';
4135     $deviceid = $deviceuser = $extension;
4136         $description = $name;
4137   }
4138  
4139   //if submitting form, update database
4140   switch ($action) {
4141     case "add":
4142     // really bad hack - but if core_users_add fails, want to stop core_devices_add
4143     if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
4144       if (core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid)) {
4145         needreload();
4146         if ($deviceuser != 'new') {
4147           redirect_standard_continue();
4148         }
4149       }
4150     }
4151     break;
4152     case "del":
4153       core_devices_del($extdisplay);
4154       needreload();
4155       redirect_standard_continue();
4156     break;
4157     case "edit":  //just delete and re-add
4158       // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
4159       if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
4160         core_devices_del($extdisplay,true);
4161         core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid,true);
4162         needreload();
4163         redirect_standard_continue('extdisplay');
4164       }
4165       break;
4166       case "resetall":  //form a url with this option to nuke the AMPUSER & DEVICE trees and start over.
4167         core_users2astdb();
4168         core_devices2astdb();
4169       break;
4170   }
4171   return true;
4172 }
4173
4174 ?>
Note: See TracBrowser for help on using the browser.