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

Revision 7881, 189.5 kB (checked in by p_lindheimer, 5 days ago)

Merged revisions 7878 via svnmerge from
http://svn.freepbx.org/modules/branches/2.5

........

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


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

........

  • Property svn:mime-type set to text/plain
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2
3 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                         $ver12 = false;
151                 } else {
152                         $call_limit = "";
153                         $ver12 = true;
154                 }
155
156                 $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
157                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
158                 if(DB::IsError($results)) {
159                 die($results->getMessage());
160                 }
161                 foreach ($results as $result) {
162                         if ($ver12) {
163                                 $additional .= $result['keyword']."=".$result['data']."\n";
164                         } else {
165                                 $option = $result['data'];
166                                 switch (strtolower($result['keyword'])) {
167                                         case 'insecure':
168                                                 if ($option == 'very')
169                                                         $additional .= "insecure=port,invite\n";
170                                                 else if ($option == 'yes')
171                                                         $additional .= "insecure=port\n";
172                                                 else
173                                                         $additional .= $result['keyword']."=$option\n";
174                                                 break;
175                                         case 'allow':
176                                         case 'disallow':
177                                                 if ($option != '')
178                                                         $additional .= $result['keyword']."=$option\n";
179                                                 break;
180                                         default:
181                                                 $additional .= $result['keyword']."=$option\n";
182                                 }
183                         }
184                 }
185
186                 $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
187                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
188                 if(DB::IsError($results)) {
189                 die($results->getMessage());
190                 }
191
192                 foreach ($results as $result) {
193                         $account = $result['data'];
194                         $id = $result['id'];
195                         $output .= "[$account]\n";
196        
197                         $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
198                         $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
199                         if(DB::IsError($results2)) {
200                         die($results2->getMessage());
201                         }
202                         foreach ($results2 as $result2) {
203                                 $options = explode("&", $result2['data']);
204                                 if ($ver12) {
205                                         foreach ($options as $option) {
206                                                 $output .= $result2['keyword']."=$option\n";
207                                         }
208                                 } else {
209                                         foreach ($options as $option) {
210                                                 switch (strtolower($result2['keyword'])) {
211                                                         case 'insecure':
212                                                                 if ($option == 'very')
213                                                                         $output .= "insecure=port,invite\n";
214                                                                 else if ($option == 'yes')
215                                                                         $output .= "insecure=port\n";
216                                                                 else
217                                                                         $output .= $result2['keyword']."=$option\n";
218                                                                 break;
219                                                         case 'allow':
220                                                         case 'disallow':
221                                                                 if ($option != '')
222                                                                         $output .= $result2['keyword']."=$option\n";
223                                                                 break;
224                                                         default:
225                                                                 $output .= $result2['keyword']."=$option\n";
226                                                 }
227                                         }
228                                 }
229                         }
230                         if ($call_limit && (substr($id,0,4) != "9999" | $id < 99990)) {
231
232                                 $output .= $call_limit;
233                         }
234                         $output .= $additional."\n";
235                 }
236                 return $output;
237         }
238
239         function generate_sip_registrations($ast_version) {
240                 global $db;
241
242                 $table_name = "sip";
243                 $output = "";
244
245                 // items with id like 9999999% get put in registrations file
246                 //
247                 $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
248                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
249                 if(DB::IsError($results)) {
250                 die($results->getMessage());
251                 }
252
253                 foreach ($results as $result) {
254                         $output .= $result['keyword']."=".$result['data']."\n";
255                 }
256
257                 return $output;
258         }
259
260         function generate_iax_additional($ast_version) {
261                 global $db;
262
263                 $table_name = "iax";
264                 $additional = "";
265                 $output = "";
266
267                 $ver12 = version_compare($ast_version, '1.4', 'lt');
268
269                 $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
270                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
271                 if(DB::IsError($results)) {
272                 die($results->getMessage());
273                 }
274                 foreach ($results as $result) {
275                         if ($ver12) {
276                                 $additional .= $result['keyword']."=".$result['data']."\n";
277                         } else {
278                                 $option = $result['data'];
279                                 switch ($result['keyword']) {
280                                         case 'notransfer':
281                                                 if (strtolower($option) == 'yes') {
282                                                         $additional .= "transfer=no\n";
283                                                 } else if (strtolower($option) == 'no') {
284                                                         $additional .= "transfer=yes\n";
285                                                 } else if (strtolower($option) == 'mediaonly') {
286                                                         $additional .= "transfer=mediaonly\n";
287                                                 } else {
288                                                         $additional .= $result['keyword']."=$option\n";
289                                                 }
290                                                 break;
291                                         case 'allow':
292                                         case 'disallow':
293                                                 if ($option != '')
294                                                         $additional .= $result['keyword']."=$option\n";
295                                                 break;
296                                         default:
297                                                 $additional .= $result['keyword']."=$option\n";
298                                 }
299                         }
300                 }
301
302                 $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
303                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
304                 if(DB::IsError($results)) {
305                 die($results->getMessage());
306                 }
307                
308                 foreach ($results as $result) {
309                         $account = $result['data'];
310                         $id = $result['id'];
311                         $output .= "[$account]\n";
312        
313                         $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
314                         $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
315                         if(DB::IsError($results2)) {
316                         die($results2->getMessage());
317                         }       
318                         foreach ($results2 as $result2) {
319                                 $options = explode("&", $result2['data']);
320                                 if ($ver12) {
321                                         foreach ($options as $option) {
322                                                 $output .= $result2['keyword']."=$option\n";
323                                         }
324                                 } else {
325                                         foreach ($options as $option) {
326                                                 switch ($result2['keyword']) {
327                                                         case 'notransfer':
328                                                                 if (strtolower($option) == 'yes') {
329                                                                         $output .= "transfer=no\n";
330                                                                 } else if (strtolower($option) == 'no') {
331                                                                         $output .= "transfer=yes\n";
332                                                                 } else if (strtolower($option) == 'mediaonly') {
333                                                                         $output .= "transfer=mediaonly\n";
334                                                                 } else {
335                                                                         $output .= $result2['keyword']."=$option\n";
336                                                                 }
337                                                                 break;
338                                                         case 'allow':
339                                                         case 'disallow':
340                                                                 if ($option != '')
341                                                                         $output .= $result2['keyword']."=$option\n";
342                                                                 break;
343                                                         default:
344                                                                 $output .= $result2['keyword']."=$option\n";
345                                                 }
346                                         }
347                                 }
348                         }
349                         $output .= $additional."\n";
350                 }
351                 return $output;
352         }
353
354         function generate_iax_registrations($ast_version) {
355                 global $db;
356
357                 $table_name = "iax";
358                 $output = "";
359
360                 // items with id like 9999999% get put in the registration file
361                 //
362                 $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
363                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
364                 if(DB::IsError($results)) {
365                 die($results->getMessage());
366                 }
367
368                 foreach ($results as $result) {
369                         $output .= $result['keyword']."=".$result['data']."\n";
370                 }
371
372                 return $output;
373         }
374
375         function generate_zapata_additional($ast_version) {
376                 global $db;
377
378                 $table_name = "zap";
379
380                 $additional = "";
381                 $output = '';
382
383                 $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
384                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
385                 if(DB::IsError($results)) {
386                 die($results->getMessage());
387                 }
388                 foreach ($results as $result) {
389                         $additional .= $result['keyword']."=".$result['data']."\n";
390                 }
391
392                 $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
393                 $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
394                 if(DB::IsError($results)) {
395                 die($results->getMessage());
396                 }
397
398                 foreach ($results as $result) {
399                         $account = $result['data'];
400                         $id = $result['id'];
401                         $output .= ";;;;;;[$account]\n";
402        
403                         $sql = "SELECT keyword,data from $table_name where id=$id and keyword <> 'account' and flags <> 1 order by keyword DESC";
404                         $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
405                         if(DB::IsError($results2)) {
406                         die($results2->getMessage());
407                         }
408                         $zapchannel="";
409                         foreach ($results2 as $result2) {
410                                 if ($result2['keyword'] == 'channel') {
411                                         $zapchannel = $result2['data'];
412                                 } else {
413                                         $output .= $result2['keyword']."=".$result2['data']."\n";
414                                 }
415                         }
416                         $output .= "channel=>$zapchannel\n";
417                         $output .= $additional."\n";
418                 }
419                 return $output;
420         }
421 }
422
423 // The destinations this module provides
424 // returns a associative arrays with keys 'destination' and 'description'
425 function core_destinations() {
426         //static destinations
427         $extens = array();
428         $category = 'Terminate Call';
429         $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category);
430         $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category);
431         $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category);
432         $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category);
433         $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category);
434         $extens[] = array('destination' => 'app-blackhole,ring,1', 'description' => 'Play ringtones to caller until they hangup', 'category' => $category);
435        
436         //get the list of meetmes
437         $results = core_users_list();
438        
439         if (isset($results) && function_exists('voicemail_getVoicemail')) {
440                 //get voicemail
441                 $uservm = voicemail_getVoicemail();
442                 $vmcontexts = array_keys($uservm);
443                 foreach ($results as $thisext) {
444                         $extnum = $thisext[0];
445                         // search vm contexts for this extensions mailbox
446                         foreach ($vmcontexts as $vmcontext) {
447                                 if(isset($uservm[$vmcontext][$extnum])){
448                                         //$vmname = $uservm[$vmcontext][$extnum]['name'];
449                                         //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>');
450                                         $vmboxes[$extnum] = true;
451                                 }
452                         }
453                 }
454         }
455        
456         // return an associative array with destination and description
457         // core provides both users and voicemail boxes as destinations
458         if (isset($results)) {
459                 foreach($results as $result) {
460                         $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions');
461                         if(isset($vmboxes[$result['0']])) {
462                                 $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail');
463                                 $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail');
464                                 $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail');
465                         }
466                 }
467         }
468        
469         if (isset($extens))
470                 return $extens;
471         else
472                 return null;
473 }
474
475 function core_getdest($exten) {
476         $dests[] = 'from-did-direct,'.$exten.',1';
477         if (!function_exists('voicemail_mailbox_get')) {
478                 return $dests;
479         }
480         $box = voicemail_mailbox_get($exten);
481         if ($box == null) {
482                 return $dests;
483         }
484         $dests[] = 'ext-local,vmb'.$exten.',1';
485         $dests[] = 'ext-local,vmu'.$exten.',1';
486         $dests[] = 'ext-local,vms'.$exten.',1';
487
488         return $dests;
489 }
490
491 function core_getdestinfo($dest) {
492         global $active_modules;
493
494         // Check for Extension Number Destinations
495         //
496         if (substr(trim($dest),0,16) == 'from-did-direct,') {
497                 $exten = explode(',',$dest);
498                 $exten = $exten[1];
499                 $thisexten = core_users_get($exten);
500                 if (empty($thisexten)) {
501                         return array();
502                 } else {
503                         //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
504                         $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
505                         return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
506                                      'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
507                                                                   );
508                 }
509
510         // Check for voicemail box destinations
511         //
512         } else if (substr(trim($dest),0,12) == 'ext-local,vm') {
513                 $exten = explode(',',$dest);
514                 $exten = substr($exten[1],3);
515                 if (!function_exists('voicemail_mailbox_get')) {
516                         return array();
517                 }
518                 $thisexten = core_users_get($exten);
519                 if (empty($thisexten)) {
520                         return array();
521                 }
522                 $box = voicemail_mailbox_get($exten);
523                 if ($box == null) {
524                         return array();
525                 }
526                 $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
527                 return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
528                              'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
529                                                           );
530
531         // Check for blackhole Termination Destinations
532         //
533         } else if (substr(trim($dest),0,14) == 'app-blackhole,') {
534                 $exten = explode(',',$dest);
535                 $exten = $exten[1];
536
537                 switch ($exten) {
538                         case 'hangup':
539                                 $description = 'Hangup';
540                                 break;
541                         case 'congestion':
542                                 $description = 'Congestion';
543                                 break;
544                         case 'busy':
545                                 $description = 'Busy';
546                                 break;
547                         case 'zapateller':
548                                 $description = 'Play SIT Tone (Zapateller)';
549                                 break;
550                         case 'musiconhold':
551                                 $description = 'Put caller on hold forever';
552                                 break;
553                         case 'ring':
554                                 $description = 'Play ringtones to caller';
555                                 break;
556                         default:
557                                 $description = false;
558                 }
559                 if ($description) {
560                         return array('description' => 'Core: '.$description,
561                                  'edit_url' => false,
562                                                                  );
563                 } else {
564                         return array();
565                 }
566
567         // None of the above, so not one of ours
568         //
569         } else {
570                 return false;
571         }
572 }
573 /*      Generates dialplan for "core" components (extensions & inbound routing)
574         We call this with retrieve_conf
575 */
576 function core_get_config($engine) {
577         global $ext;  // is this the best way to pass this?
578         global $version;  // this is not the best way to pass this, this should be passetd together with $engine
579         global $amp_conf;
580         global $core_conf;
581
582         $modulename = "core";
583        
584         switch($engine) {
585                 case "asterisk":
586
587                         // Now add to sip_general_addtional.conf
588                         //
589                         if (isset($core_conf) && is_a($core_conf, "core_conf")) {
590                                 $core_conf->addSipGeneral('disallow','all');
591                                 $core_conf->addSipGeneral('allow','ulaw');
592                                 $core_conf->addSipGeneral('allow','alaw');
593                                 $core_conf->addSipGeneral('context','from-sip-external');
594                                 $core_conf->addSipGeneral('callerid','Unknown');
595                                 $core_conf->addSipGeneral('notifyringing','yes');
596                                 if (version_compare($version, '1.4', 'ge')) {
597                                         $core_conf->addSipGeneral('notifyhold','yes');
598                                         $core_conf->addSipGeneral('limitonpeers','yes');
599                                         $core_conf->addSipGeneral('tos_sip','cs3');    // Recommended setting from doc/ip-tos.txt
600                                         $core_conf->addSipGeneral('tos_audio','ef');   // Recommended setting from doc/ip-tos.txt
601                                         $core_conf->addSipGeneral('tos_video','af41'); // Recommended setting from doc/ip-tos.txt
602                                 } else {
603                                         $core_conf->addSipGeneral('tos','0x68'); // This really doesn't do anything with astersk not running as root
604                                 }
605                                 $core_conf->addIaxGeneral('disallow','all');
606                                 $core_conf->addIaxGeneral('allow','ulaw');
607                                 $core_conf->addIaxGeneral('allow','alaw');
608                                 $core_conf->addIaxGeneral('allow','gsm');
609                                 $core_conf->addIaxGeneral('mailboxdetail','yes');
610                                 if (version_compare($version, '1.4', 'ge')) {
611                                         $core_conf->addIaxGeneral('tos','ef'); // Recommended setting from doc/ip-tos.txt
612                                 }
613
614                                 $fcc = new featurecode($modulename, 'blindxfer');
615                                 $code = $fcc->getCodeActive();
616                                 unset($fcc);
617                                 if ($code != '') {
618                                         $core_conf->addFeatureMap('blindxfer',$code);
619                                 }
620
621                                 $fcc = new featurecode($modulename, 'atxfer');
622                                 $code = $fcc->getCodeActive();
623                                 unset($fcc);
624                                 if ($code != '') {
625                                         $core_conf->addFeatureMap('atxfer',$code);
626                                 }
627
628                                 $fcc = new featurecode($modulename, 'automon');
629                                 $code = $fcc->getCodeActive();
630                                 unset($fcc);
631                                 if ($code != '') {
632                                         $core_conf->addFeatureMap('automon',$code);
633                                 }
634
635                                 $core_conf->addFeatureMap('disconnect','**');
636                         }
637
638                         // FeatureCodes
639                         $fcc = new featurecode($modulename, 'userlogon');
640                         $fc_userlogon = $fcc->getCodeActive();
641                         unset($fcc);
642
643                         $fcc = new featurecode($modulename, 'userlogoff');
644                         $fc_userlogoff = $fcc->getCodeActive();
645                         unset($fcc);
646
647                         $fcc = new featurecode($modulename, 'zapbarge');
648                         $fc_zapbarge = $fcc->getCodeActive();
649                         unset($fcc);
650
651                         $fcc = new featurecode($modulename, 'chanspy');
652                         $fc_chanspy = $fcc->getCodeActive();
653                         unset($fcc);
654
655                         $fcc = new featurecode($modulename, 'simu_pstn');
656                         $fc_simu_pstn = $fcc->getCodeActive();
657                         unset($fcc);
658
659                         $fcc = new featurecode($modulename, 'simu_fax');
660                         $fc_simu_fax = $fcc->getCodeActive();
661                         unset($fcc);
662
663                         $fcc = new featurecode($modulename, 'pickup');
664                         $fc_pickup = $fcc->getCodeActive();
665                         unset($fcc);
666
667                         // Log on / off -- all in one context
668                         if ($fc_userlogoff != '' || $fc_userlogon != '') {
669                                 $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal
670                                
671                                 if ($fc_userlogoff != '') {
672                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
673                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup(''));
674                                 }
675        
676                                 if ($fc_userlogon != '') {
677                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
678                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
679                                        
680                                         $clen = strlen($fc_userlogon);
681                                         $fc_userlogon = "_$fc_userlogon.";
682                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}'));
683                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
684                                 }
685                         }
686
687                         // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
688                         // when a user pushes a flashing BLF.
689                         if ($fc_pickup != '') {
690                                 $ext->addInclude('from-internal-additional', 'app-pickup');
691                                 $fclen = strlen($fc_pickup);
692                                 $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}'));
693                                 if (strstr($version, 'BRI'))
694                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_dpickup('${EXTEN:'.$fclen.'}'));
695                                 else
696                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_pickup('${EXTEN:'.$fclen.'}'));
697                         }
698                        
699                        
700                         // zap barge
701                         if ($fc_zapbarge != '') {
702                                 $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal
703                                
704                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
705                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}'));
706                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
707                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
708                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
709                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
710                         }
711
712                         // chan spy
713                         if ($fc_chanspy != '') {
714                                 $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal
715                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
716                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
717                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
718                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
719                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
720                         }
721                        
722                         // Simulate options (ext-test)
723                         if ($fc_simu_pstn != '' || $fc_simu_fax != '') {
724                                 $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal
725                                
726                                 if ($fc_simu_pstn != '') {
727                                         $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
728                                 }
729
730                                 if ($fc_simu_fax != '') {
731                                         $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax'));
732                                 }
733
734                                 $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
735                         }
736                        
737                         /* Always have Fax detection in ext-did, no matter what */
738                         $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax'));
739
740                         /* inbound routing extensions */
741                         $didlist = core_did_list();
742                         if(is_array($didlist)){
743                                 $catchall = false;
744                                 $catchall_context='ext-did-catchall';
745                                 foreach($didlist as $item) {
746                                         $did = core_did_get($item['extension'],$item['cidnum']);
747                                         $exten = $did['extension'];
748                                         $cidnum = $did['cidnum'];
749
750                                         $exten = (empty($exten)?"s":$exten);
751                                         $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it
752
753                                         $context = "ext-did";
754
755                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
756                                         // always set callerID name
757                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
758                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
759                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
760
761                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
762                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
763                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
764                                         }
765
766                                         // If we require RINGING, signal it as soon as we enter.
767                                         if ($item['ringing'] === "CHECKED") {
768                                                 $ext->add($context, $exten, '', new ext_ringing(''));
769                                         }
770
771                                         if ($exten == "s" && $context == "ext-did") { 
772                                                 //if the exten is s, then also make a catchall for undefined DIDs
773                                                 $catchaccount = "_.".(empty($cidnum)?"":"/".$cidnum);
774                                                 if ($catchaccount =="_." && ! $catchall) {
775                                                         $catchall = true;
776                                                         $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
777                                                         $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did'));
778                                                 }
779                                         }
780                                        
781                                         if ($item['faxexten'] != "default") {
782                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
783                                         }
784                                         if (!empty($item['faxemail'])) {
785                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
786                                         }
787                                         if ($item['answer'] == "1") {
788                                                 $ext->add($context, $exten, '', new ext_answer(''));
789                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
790                                         }
791                                         if ($item['answer'] == "2") { // NVFaxDetect
792                                                 $ext->add($context, $exten, '', new ext_answer(''));
793                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
794                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
795                                         }
796                                         if ($item['privacyman'] == "1") {
797                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
798                                         } else {
799                                                 // if privacymanager is used, this is not necessary as it will not let blocked/anonymous calls through
800                                                 // otherwise, we need to save the caller presence to set it properly if we forward the call back out the pbx
801                                                 // note - the indirect table could go away as of 1.4.20 where it is fixed so that SetCallerPres can take
802                                                 // the raw format.
803                                                 //
804                                                 if (version_compare($version, "1.6", "lt")) {
805                                                         $ext->add($context, $exten, '', new ext_setvar('__CALLINGPRES_SV','${CALLINGPRES_${CALLINGPRES}}'));
806                                                 } else {
807                                                         $ext->add($context, $exten, '', new ext_setvar('__CALLINGPRES_SV','${CALLERPRES()}'));
808                                                 }
809                                                 $ext->add($context, $exten, '', new ext_setcallerpres('allowed_not_screened'));
810                                         }
811                                         if (!empty($item['alertinfo'])) {
812                                                 $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo'])));
813                                         }
814                                         // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should
815                                         // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different
816                                         // modules.
817                                         //
818                                         // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here.
819                                         //
820                                         // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX)
821                                         //
822                                         if (!empty($item['grppre'])) {
823                                                 $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre']));
824                                                 $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
825                                         }
826                                        
827                                         //the goto destination
828                                         // destination field in 'incoming' database is backwards from what ext_goto expects
829                                         $goto_context = strtok($did['destination'],',');
830                                         $goto_exten = strtok(',');
831                                         $goto_pri = strtok(',');
832                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
833                                        
834                                 }
835                                 // If there's not a catchall, make one with an error message
836                                 if (!$catchall) {
837                                         $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
838                                         $ext->add($catchall_context, 's', '', new ext_answer(''));
839                                         $ext->add($catchall_context, 's', '', new ext_wait('2'));
840                                         $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
841                                         $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
842                                         $ext->add($catchall_context, '_[*#X].', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
843                                         $ext->add($catchall_context, '_[*#X].', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
844                                         $ext->add($catchall_context, '_[*#X].', '', new ext_goto('1','s','ext-did'));
845                                 }
846                                        
847                         }
848
849                         /* MODIFIED (PL)
850                          *
851                          * Add Direct DIDs
852                          *
853                          * This functions creates a new context, ext-did-direct, used to route an incoming DID directly to the specified user.
854                          * The purpose is to use when a user has a personal external DID. This keeps it clean and easy to administer.
855                          * Any conflict with those routes will depend on which of the two contexts are included first in the extensions.conf file.
856                          *
857                          * Calls are sent to context from-did-direct though this feature. You must create that context in extenions.conf or
858                          * in extensions_custom.conf and it should look something like:
859                          *
860                          * [from-did-direct]
861                          * include => ext-findmefollow
862                          * include => ext-local
863                          *
864                          * This is so that personal ring groups are used if they exist for the direct did and if not, then the local extension.
865                          * If the module is not implented, it will just go to the users extension.
866                          */
867
868                         $directdidlist = core_directdid_list();
869                         if(is_array($directdidlist)){
870                                 $context = "ext-did";
871                                 if(!is_array($didlist)){
872                                         /* if not set above, add one here */
873                                         $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
874                                 }
875                                 foreach($directdidlist as $item) {
876                                         $exten = $item['directdid'];
877                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
878                                         // always set callerID name
879                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
880                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
881                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
882
883                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
884                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
885                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
886                                         }
887                                        
888                                         if ($item['faxexten'] != "default") {
889                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
890                                         }
891                                         if (!empty($item['faxemail'])) {
892                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
893                                         }
894                                         if ($item['answer'] == "1") {
895                                                 $ext->add($context, $exten, '', new ext_answer(''));
896                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
897                                         }
898                                         if ($item['answer'] == "2") { // NVFaxDetect
899                                                 $ext->add($context, $exten, '', new ext_answer(''));
900                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
901                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
902                                         }
903                                         if ($item['privacyman'] == "1") {
904                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
905                                         }
906
907
908                                         if (!empty($item['didalert'])) {
909                                                 $ext->add($context, $exten, '', new ext_setvar("_ALERT_INFO", str_replace(';', '\;', $item['didalert'])));
910                                         }
911                                         $goto_context = 'from-did-direct';
912                                         $goto_exten = $item['extension'];
913                                         $goto_pri = 1;
914                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
915
916                                 }
917                         }
918
919                         // Now create macro-from-zaptel-nnn for each defined channel to route it to the DID routing
920                         // Send it to from-trunk so it is handled as other dids would be handled.
921                         //
922                         foreach (core_zapchandids_list() as $row) {
923                                 $channel = $row['channel'];
924                                 $did     = $row['did'];
925
926                                 $zap_context = "macro-from-zaptel-{$channel}";
927                                 $ext->add($zap_context, 's', '', new ext_noop('Entering '.$zap_context.' with DID = ${DID} and setting to: '.$did));
928                                 $ext->add($zap_context, 's', '', new ext_setvar('__FROM_DID',$did));
929                                 $ext->add($zap_context, 's', '', new ext_goto('1',$did,'from-trunk'));
930                         }
931
932                         /* user extensions */
933                         $ext->addInclude('from-internal-additional','ext-local');
934
935                         // If running in Dynamic mode, this will insert the hints through an Asterisk #exec call.
936                         // which require "execincludes=yes" to be set in the [options] section of asterisk.conf
937                         //
938                         if ($amp_conf['DYNAMICHINTS']) {
939                                 $ext->addExec('ext-local',$amp_conf['AMPBIN'].'/generate_hints.php');
940                         }
941                         $userlist = core_users_list();
942                         if (is_array($userlist)) {
943                                 foreach($userlist as $item) {
944                                         $exten = core_users_get($item[0]);
945                                         $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']);
946
947                                         if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0)
948                                                 $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer']));
949                                        
950                                         $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension']));
951                                         $ext->add('ext-local', $exten['extension'], '', new ext_hangup(''));
952                                        
953                                         if($vm != "novm") {
954                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',"$vm,DIRECTDIAL"));
955                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_hangup(''));
956                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',"$vm,BUSY"));
957                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_hangup(''));
958                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',"$vm,NOANSWER"));
959                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_hangup(''));
960                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',"$vm,NOMESSAGE"));
961                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_hangup(''));
962                                         }
963                                                
964                                         // Create the hints if running in normal mode
965                                         //
966                                         if (!$amp_conf['DYNAMICHINTS']) {
967                                                 $hint = core_hint_get($exten['extension']);
968                                                 if (!empty($hint)) {
969                                                         $ext->addHint('ext-local', $exten['extension'], $hint);
970                                                 }
971                                         }
972                                         if ($exten['sipname']) {
973                                                 $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal'));
974                                         }
975                                         // Now make a special context for the IVR inclusions of local extension dialing so that
976                                         // when people use the Queues breakout ability, and break out to someone's extensions, voicemail
977                                         // works.
978                                         //
979                                         $ivr_context = 'from-did-direct-ivr';
980                                         $ext->add($ivr_context, $exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
981                                         $ext->add($ivr_context, $exten['extension'],'', new ext_setvar('__NODEST', ''));
982                                         $ext->add($ivr_context, $exten['extension'],'', new ext_goto('1',$exten['extension'],'from-did-direct'));
983                                         if($vm != "novm") {
984                                                 $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
985                                                 $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_setvar('__NODEST', ''));
986                                                 $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_macro('vm',"$vm,DIRECTDIAL"));
987                                         }
988                                 }
989                         }
990
991                         // create from-trunk context for each trunk that adds counts to channels
992                         //
993                         $trunklist = core_trunks_list(true);
994                         if (is_array($trunklist)) {
995                                 foreach ($trunklist as $trunkprops) {
996                                         if (trim($trunkprops['value']) == 'on') {
997                                                 // value of on is disabled and for zap we don't create a context
998                                                 continue;
999                                         }
1000                                         switch ($trunkprops['tech']) {
1001                                                 case 'DUNDI':
1002                                                         $macro_name = 'macro-dundi-'.substr($trunkprops['globalvar'],4);
1003                                                         $ext->addSwitch($macro_name,'DUNDI/'.$trunkprops['name']);
1004                                                         $ext->add($macro_name, 's', '', new ext_goto('1','${ARG1}'));
1005                                                 case 'IAX':
1006                                                 case 'IAX2':
1007                                                 case 'SIP':
1008                                                         $trunkgroup = $trunkprops['globalvar'];
1009                                                         $trunkcontext  = "from-trunk-".strtolower($trunkprops['tech'])."-".$trunkprops['name'];
1010                                                         $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup));
1011                                                         $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk'));
1012                                                         break;
1013                                                 default:
1014                                         }
1015                                 }
1016                         }
1017
1018                         /* dialplan globals */
1019                         // modules should NOT use the globals table to store anything!
1020                         // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
1021                         // I'm cheating for core functionality - do as I say, not as I do ;-)           
1022
1023                         // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
1024                         //
1025                         $amp_conf_globals = array(
1026                                 "ASTETCDIR",
1027                                 "ASTMODDIR",
1028                                 "ASTVARLIBDIR",
1029                                 "ASTAGIDIR",
1030                                 "ASTSPOOLDIR",
1031                                 "ASTRUNDIR",
1032                                 "ASTLOGDIR",
1033                                 "CWINUSEBUSY",
1034                                 "AMPMGRUSER",
1035                                 "AMPMGRPASS"
1036                         );
1037
1038                         $sql = "SELECT * FROM globals";
1039                         $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1040                         foreach($globals as $global) {
1041                                 $ext->addGlobal($global['variable'],$global['value']);
1042
1043                                 // now if for some reason we have a variable in the global table
1044                                 // that is in our $amp_conf_globals list, then remove it so we
1045                                 // don't duplicate, the sql table will take precedence
1046                                 //
1047                                 if (array_key_exists($global['variable'],$amp_conf_globals)) {
1048                                         $rm_keys = array_keys($amp_conf_globals,$global['variable']);
1049                                         foreach ($rm_keys as $index) {
1050                                                 unset($amp_conf_globals[$index]);
1051                                         }
1052                                 }
1053                         }
1054                         foreach ($amp_conf_globals as $global) {
1055                                 if (isset($amp_conf[$global])) {
1056                                         $value = $amp_conf[$global];
1057                                         if ($value === true || $value === false) {
1058                                                 $value = ($value) ? 'true':'false';
1059                                         }
1060                                         $ext->addGlobal($global, $value);
1061                                         out("Added to globals: $global = $value");
1062                                 }
1063                         }
1064                         // Put the asterisk version in a global for agi etc.
1065                         $ext->addGlobal('ASTVERSION', $version);
1066
1067                         // Create CallingPresTable to deal with difference that ${CALINGPRES} returns vs. what
1068                         // SetCallerPres() accepts. This is a workaround that gets resolved in 1.6 where
1069                         // function CALLINGPRES() is consistent.
1070                         // This should be fixed in 1.4.20 but for now we keep it in until 1.6
1071                         //
1072                         if (version_compare($version, "1.6", "lt")) {
1073                                 $ext->addGlobal('CALLINGPRES_0', 'allowed_not_screened');
1074                                 $ext->addGlobal('CALLINGPRES_1', 'allowed_passed_screen');
1075                                 $ext->addGlobal('CALLINGPRES_2', 'allowed_failed_screen');
1076                                 $ext->addGlobal('CALLINGPRES_3', 'allowed');
1077                                 $ext->addGlobal('CALLINGPRES_32', 'prohib_not_screened');
1078                                 $ext->addGlobal('CALLINGPRES_33', 'prohib_passed_screen');
1079                                 $ext->addGlobal('CALLINGPRES_34', 'prohib_failed_screen');
1080                                 $ext->addGlobal('CALLINGPRES_35', 'prohib');
1081                                 $ext->addGlobal('CALLINGPRES_67', 'unavailable');
1082                         }
1083
1084                         /* outbound routes */
1085                         // modules should use their own table for storage (and module_get_config() to add dialplan)
1086                         // modules should NOT use the extension table to store anything!
1087                         $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application";
1088                         $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1089                         $ext->addInclude('from-internal-additional','outbound-allroutes');
1090                         $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
1091                         foreach($outrts as $outrt) {
1092                                 $ext->addInclude('outbound-allroutes',$outrt['application']);
1093                                 $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC";
1094                                 $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1095                                 $lastexten = false;
1096                                 foreach($thisrt as $exten) {
1097                                         //if emergencyroute, then set channel var
1098                                         if(strpos($exten['args'],"EMERGENCYROUTE") !== false)
1099                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15)));
1100                                         if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false)
1101                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18)));
1102                                         // Don't set MOHCLASS if already set, threre may be a feature code that overrode it
1103                                         if(strpos($exten['args'],"MOHCLASS") !== false)
1104                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' ));
1105                                         if(strpos($exten['args'],"dialout-trunk") !== false || strpos($exten['args'],"dialout-enum") !== false || strpos($exten['args'],"dialout-dundi") !== false) {
1106                                                 if ($exten['extension'] !== $lastexten) {
1107
1108                                                         // If NODEST is set, clear it. No point in remembering since dialout-trunk will just end in the
1109                                                         // bit bucket. But if answered by an outside line with transfer capability, we want NODEST to be
1110                                                         // clear so a subsequent transfer to an internal extension works and goes to voicmail or other
1111                                                         // destinations.
1112                                                         //
1113                                                         // Then do one call to user-callerid and record-enable instead of each time as in the past
1114                                                         //
1115                                                         $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('user-callerid,SKIPTTL'));
1116                                                         $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("_NODEST",""));
1117                                                         $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('record-enable,${AMPUSER},OUT'));
1118                                                         $lastexten = $exten['extension'];
1119                                                 }
1120                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
1121                                         }
1122                                         if(strpos($exten['args'],"outisbusy") !== false)
1123                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy"));
1124                                 }
1125                         }
1126
1127                         general_generate_indications();
1128
1129                         // "blackhole" destinations
1130                         $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
1131                         $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
1132
1133                         $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
1134                         $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
1135                         $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
1136                         // Should hangup ?
1137                         // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
1138                                        
1139                         $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
1140                         $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
1141                         $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
1142
1143                         $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
1144                         $ext->add('app-blackhole', 'congestion', '', new ext_answer());
1145                         $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
1146                         $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
1147                         $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
1148
1149                         $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
1150                         $ext->add('app-blackhole', 'busy', '', new ext_answer());
1151                         $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy'));
1152                         $ext->add('app-blackhole', 'busy', '', new ext_busy());
1153                         $ext->add('app-blackhole', 'busy', '', new ext_hangup());
1154
1155                         $ext->add('app-blackhole', 'ring', '', new ext_noop('Blackhole Dest: Ring'));
1156                         $ext->add('app-blackhole', 'ring', '', new ext_answer());
1157                         $ext->add('app-blackhole', 'ring', '', new ext_playtones('ring'));
1158                         $ext->add('app-blackhole', 'ring', '', new ext_wait(300));
1159                         $ext->add('app-blackhole', 'ring', '', new ext_hangup());
1160
1161                         if ($amp_conf['AMPBADNUMBER'] !== false) {
1162                                 $context = 'bad-number';
1163                                 $exten = '_X.';
1164                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
1165                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
1166                                 $ext->add($context, $exten, '', new ext_wait('1'));
1167                                 $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1168                                 $ext->add($context, $exten, '', new ext_wait('1'));
1169                                 $ext->add($context, $exten, '', new ext_congestion('20'));
1170                                 $ext->add($context, $exten, '', new ext_hangup());
1171
1172                                 $exten = '_*.';
1173                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
1174                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
1175                                 $ext->add($context, $exten, '', new ext_wait('1'));
1176                                 $ext->add($context, $exten, '', new ext_playback('silence/1&feature-not-avail-line&silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1177                                 $ext->add($context, $exten, '', new ext_wait('1'));
1178                                 $ext->add($context, $exten, '', new ext_congestion('20'));
1179                                 $ext->add($context, $exten, '', new ext_hangup());
1180                         }
1181
1182                         $context = 'macro-dialout-trunk';
1183                         $exten = 's';
1184                        
1185                         /*
1186                          * dialout using a trunk, using pattern matching (don't strip any prefix)
1187                          * arg1 = trunk number, arg2 = number, arg3 = route password
1188                          *
1189                          * MODIFIED (PL)
1190                          *
1191                          * Modified both Dial() commands to include the new TRUNK_OPTIONS from the general
1192                          * screen of AMP
1193                          */
1194                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1195                         $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1196                         $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
1197                         $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this
1198                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company
1199                         $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
1200                         $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
1201                         $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
1202                         $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));  // Set to YES if treated like internal
1203                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}'));
1204                         $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
1205                         $ext->add($context, $exten, 'skipoutcid', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1206                         $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number
1207                         $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}'));  // Custom trunks are prefixed with "AMP:"
1208                
1209                         // Back to normal processing, whether intracompany or not.
1210                         // But add the macro-setmusic if we don't want music on this outbound call
1211                         $ext->add($context, $exten, '', new ext_gotoif('$[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]', 'gocall'));  // Set to YES if we should pump silence
1212                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', 'M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));  // set MoH or off
1213                
1214                         // This macro call will always be blank and is provided as a hook for customization required prior to making a call
1215                         // such as adding SIP header information or other requirements. All the channel variables from above are present
1216                        
1217                         $ext->add($context, $exten, 'gocall', new ext_macro('dialout-trunk-predial-hook'));
1218                         $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
1219                
1220                         $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
1221                         $ext->add($context, $exten, '', new ext_dial('${OUT_${DIAL_TRUNK}}/${OUTNUM}', '300,${DIAL_TRUNK_OPTIONS}'));  // Regular Trunk Dial
1222                         $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1223                        
1224                         $ext->add($context, $exten, 'customtrunk', new ext_set('pre_num', '${CUT(OUT_${DIAL_TRUNK},$,1)}'));
1225                         $ext->add($context, $exten, '', new ext_set('the_num', '${CUT(OUT_${DIAL_TRUNK},$,2)}'));  // this is where we expect to find string OUTNUM
1226                         $ext->add($context, $exten, '', new ext_set('post_num', '${CUT(OUT_${DIAL_TRUNK},$,3)}'));
1227                         $ext->add($context, $exten, '', new ext_gotoif('$["${the_num}" = "OUTNUM"]', 'outnum', 'skipoutnum'));  // if we didn't find "OUTNUM", then skip to Dial
1228                         $ext->add($context, $exten, 'outnum', new ext_set('the_num', '${OUTNUM}'));  // replace "OUTNUM" with the actual number to dial
1229                         $ext->add($context, $exten, 'skipoutnum', new ext_dial('${pre_num:4}${the_num}${post_num}', '300,${DIAL_TRUNK_OPTIONS}'));
1230                         $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1231                        
1232                         $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
1233                
1234                         $exten = 's-BUSY';
1235                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
1236                         $ext->add($context, $exten, '', new ext_playtones('busy'));
1237                         $ext->add($context, $exten, '', new ext_busy(20));
1238                
1239                         $exten = 's-NOANSWER';
1240                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
1241                         $ext->add($context, $exten, '', new ext_playtones('congestion'));
1242                         $ext->add($context, $exten, '', new ext_congestion(20));
1243                
1244                         $exten = 's-CANCEL';
1245                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up'));
1246                         $ext->add($context, $exten, '', new ext_playtones('congestion'));
1247                         $ext->add($context, $exten, '', new ext_congestion(20));
1248                
1249                         $exten = '_s-.';
1250                         $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport'));
1251                         $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
1252                         $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks'));
1253                        
1254                         $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
1255                         $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook'));
1256                
1257                         $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1258
1259
1260
1261
1262                         $context = 'macro-dialout-dundi';
1263                         $exten = 's';
1264                        
1265                         /*
1266                          * Dialout Dundi Trunk
1267                          */
1268                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1269                         $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1270                         $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
1271                         $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this
1272                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company
1273                         $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}'));
1274                         $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
1275                         $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
1276                         $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));  // Set to YES if treated like internal
1277                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}'));
1278                         $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
1279                         $ext->add($context, $exten, 'skipoutcid', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1280                         $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number
1281
1282                         // Back to normal processing, whether intracompany or not.
1283                         // But add the macro-setmusic if we don't want music on this outbound call
1284                         $ext->add($context, $exten, '', new ext_gotoif('$[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]', 'gocall'));  // Set to YES if we should pump silence
1285                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', 'M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));  // set MoH or off
1286                
1287                         // This macro call will always be blank and is provided as a hook for customization required prior to making a call
1288                         // such as adding SIP header information or other requirements. All the channel variables from above are present
1289                        
1290                         $ext->add($context, $exten, 'gocall', new ext_macro('dialout-dundi-predial-hook'));
1291                         $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
1292                
1293                         $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
1294
1295                         $ext->add($context, $exten, '', new ext_macro('dundi-${DIAL_TRUNK}','${OUTNUM}'));
1296                         $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1297                        
1298                         $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
1299                
1300                         $exten = 's-BUSY';
1301                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
1302                         $ext->add($context, $exten, '', new ext_playtones('busy'));
1303                         $ext->add($context, $exten, '', new ext_busy(20));
1304                
1305                         $exten = 's-NOANSWER';
1306                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
1307                         $ext->add($context, $exten, '', new ext_playtones('congestion'));
1308                         $ext->add($context, $exten, '', new ext_congestion(20));
1309                
1310                         $exten = 's-CANCEL';
1311                         $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up'));
1312                         $ext->add($context, $exten, '', new ext_playtones('congestion'));
1313                         $ext->add($context, $exten, '', new ext_congestion(20));
1314                
1315                         $exten = '_s-.';
1316                         $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport'));
1317                         $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
1318                         $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks'));
1319                        
1320                         $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
1321                         $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-dundi-predial-hook'));
1322                
1323                         $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1324
1325
1326
1327                         /*
1328                          * sets the callerid of the device to that of the logged in user
1329                          *
1330                          * ${AMPUSER} is set upon return to the real user despite any aliasing that may
1331                          * have been set as a result of the AMPUSER/<nnn>/cidnum field. This is used by
1332                          * features like DND, CF, etc. to set the proper structure on aliased instructions
1333                          */
1334                         $context = 'macro-user-callerid';
1335                         $exten = 's';
1336                        
1337                         $ext->add($context, $exten, '', new ext_noop('user-callerid: ${CALLERID(name)} ${CALLERID(number)}'));
1338                                                        
1339                         // make sure AMPUSER is set if it doesn't get set below                 
1340                         $ext->add($context, $exten, '', new ext_set('AMPUSER', '${IF($["foo${AMPUSER}" = "foo"]?${CALLERID(number)}:${AMPUSER})}'));
1341                         $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}" = "Local"]', 'report'));
1342                         $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}'));
1343                         $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1344                         $ext->add($context, $exten, '', new ext_set('AMPUSER', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1345                         $ext->add($context, $exten, '', new ext_set('AMPUSERCIDNAME', '${DB(AMPUSER/${AMPUSER}/cidname)}'));
1346                         $ext->add($context, $exten, '', new ext_gotoif('$["x${AMPUSERCIDNAME:1:2}" = "x"]', 'report'));
1347
1348                         // user may masquerade as a different user internally, so set the internal cid as indicated
1349                         // but keep the REALCALLERID which is used to determine their true identify and lookup info
1350                         // during outbound calls.
1351                         $ext->add($context, $exten, '', new ext_set('AMPUSERCID', '${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}'));
1352                         $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '"${AMPUSERCIDNAME}" <${AMPUSERCID}>'));
1353                         $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1354                         if (version_compare($version, "1.4", "ge")) {
1355                                 $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/language)}" != ""]', 'Set', 'CHANNEL(language)=${DB(AMPUSER/${AMPUSER}/language)}'));
1356                         } else {
1357                                 $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/language)}" != ""]', 'Set', 'LANGUAGE()=${DB(AMPUSER/${AMPUSER}/language)}'));
1358                         }
1359                         $ext->add($context, $exten, 'report', new ext_noop('TTL: ${TTL} ARG1: ${ARG1}'));
1360                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${ARG1}" = "SKIPTTL" ]', 'continue'));
1361                         $ext->add($context, $exten, 'report2', new ext_set('__TTL', '${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}'));
1362                         $ext->add($context, $exten, '', new ext_gotoif('$[ ${TTL} > 0 ]', 'continue'));
1363                         $ext->add($context, $exten, '', new ext_wait('${RINGTIMER}'));  // wait for a while, to give it a chance to be picked up by voicemail
1364                         $ext->add($context, $exten, '', new ext_answer());
1365                         $ext->add($context, $exten, '', new ext_wait('2'));
1366                         $ext->add($context, $exten, '', new ext_playback('im-sorry&an-error-has-occured&with&call-forwarding'));
1367                         $ext->add($context, $exten, '', new ext_macro('hangupcall'));
1368                         $ext->add($context, $exten, '', new ext_congestion(20));
1369                         $ext->add($context, $exten, 'continue', new ext_noop('Using CallerID ${CALLERID(all)}'));
1370                         $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1371                        
1372                         /*
1373                          * arg1 = trunk number, arg2 = number
1374                          *
1375                          * Re-written to use enumlookup.agi
1376                          */
1377        
1378                         $context = 'macro-dialout-enum';
1379                         $exten = 's';
1380        
1381                         $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1382                         $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${ARG1}'));
1383                         $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${ARG1}'));
1384                         $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${ARG1}}foo" = "foo"]', 'nomax'));
1385                         $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${ARG1})} >= ${OUTMAXCHANS_${ARG1}} ]', 'nochans'));
1386                         $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}'));
1387                         $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1388                         $ext->add($context, $exten, '', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1389                         //  Replacement for asterisk's ENUMLOOKUP function
1390                         $ext->add($context, $exten, '', new ext_agi('enumlookup.agi'));
1391                         // Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority
1392                         // Loop through them trying them in order.
1393                         $ext->add($context, $exten, 'dialloop', new ext_gotoif('$["foo${DIALARR}"="foo"]', 'end'));
1394                         $ext->add($context, $exten, '', new ext_set('TRYDIAL', '${CUT(DIALARR,%,1)}'));
1395                         $ext->add($context, $exten, '', new ext_set('DIALARR', '${CUT(DIALARR,%,2-)}'));
1396                         $ext->add($context, $exten, '', new ext_dial('${TRYDIAL}', ''));
1397                         $ext->add($context, $exten, '', new ext_noop('Dial exited in macro-enum-dialout with ${DIALSTATUS}'));
1398                         // Now, if we're still here, that means the Dial failed for some reason.
1399                         // If it's CONGESTION or CHANUNAVAIL we want to try again on a different
1400                         // different channel. If there's no more left, the dialloop tag will exit.
1401                         $ext->add($context, $exten, '', new ext_gotoif('$[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]', 'dialloop'));
1402                         // If we're here, then it's BUSY or NOANSWER or something and well, deal with it.
1403                         $ext->add($context, $exten, 'dialfailed', new ext_goto(1, 's-${DIALSTATUS}'));
1404                         // Here are the exit points for the macro.
1405                         $ext->add($context, $exten, 'nochans', new ext_noop('max channels used up'));
1406                         $ext->add($context, $exten, 'end', new ext_noop('Exiting macro-dialout-enum'));
1407                         $ext->add($context, 's-BUSY', '', new ext_noop('Trunk is reporting BUSY'));
1408                         $ext->add($context, 's-BUSY', '', new ext_busy(20));
1409                         $ext->add($context, '_s-.', '', new ext_noop('Dial failed due to ${DIALSTATUS}'));                     
1410                        
1411                         /*
1412                          * overrides callerid out trunks
1413                          * arg1 is trunk
1414                          * macro-user-callerid should be called _before_ using this macro
1415                          */
1416
1417                         $context = 'macro-outbound-callerid';
1418                         $exten = 's';
1419                        
1420                         // If we modified the caller presence, set it back. This allows anonymous calls to be internally prepended but keep
1421                         // their status if forwarded back out. Not doing this can result in the trunk CID being displayed vs. 'blocked call'
1422                         //
1423                         if (version_compare($version, "1.6", "lt")) {
1424                                 $ext->add($context, $exten, '', new ext_execif('$["${CALLINGPRES_SV}" != ""]', 'SetCallerPres', '${CALLINGPRES_SV}'));
1425                         } else {
1426                                 $ext->add($context, $exten, '', new ext_execif('$["${CALLINGPRES_SV}" != ""]', 'Set', 'CALLERPRES()=${CALLINGPRES_SV}'));
1427                         }
1428
1429                         // Keep the original CallerID number, for failover to the next trunk.
1430                         $ext->add($context, $exten, '', new ext_gotoif('$["${REALCALLERIDNUM:1:2}" != ""]', 'start'));
1431                         $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${CALLERID(number)}'));
1432                         $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1433
1434                         // If this came through a ringgroup or CF, then we want to retain original CID unless
1435                         // OUTKEEPCID_${trunknum} is set.
1436                         // Save then CIDNAME while it is still intact in case we end up sending out this same CID
1437                         $ext->add($context, $exten, '', new ext_gotoif('$["${KEEPCID}" != "TRUE"]', 'normcid'));  // Set to TRUE if coming from ringgroups, CF, etc.
1438                         $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTKEEPCID_${ARG1}}" = "xon"]', 'normcid'));
1439                         $ext->add($context, $exten, '', new ext_gotoif('$["foo${REALCALLERIDNUM}" = "foo"]', 'normcid'));  // if not set to anything, go through normal processing
1440                         $ext->add($context, $exten, '', new ext_set('USEROUTCID', '${REALCALLERIDNUM}'));
1441                         //$ext->add($context, $exten, '', new ext_set('REALCALLERIDNAME', '${CALLERID(name)}'));
1442
1443                         // 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
1444                         // call (would be quite a conincidence if not) and go through the normal processing to get that CID. If a device
1445                         // is set for this CID, then it must be internal
1446                         // If we end up using USEROUTCID at the end, it may still be the REALCALLERIDNUM we saved above. That is determined
1447                         // if the two are equal, AND there is no CALLERID(name) present since it has been removed by the CALLERID(all)=${USEROUTCID}
1448                         // 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
1449                         // carriers, there are cases where it is so this preserves that information to be used by those carriers who do honor it.
1450                         $ext->add($context, $exten, '', new ext_gotoif('$["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" = "foo"]', 'bypass', 'normcid'));
1451
1452                         $ext->add($context, $exten, 'normcid', new ext_set('USEROUTCID', '${DB(AMPUSER/${REALCALLERIDNUM}/outboundcid)}'));
1453                         $ext->add($context, $exten, 'bypass', new ext_set('EMERGENCYCID', '${DB(DEVICE/${REALCALLERIDNUM}/emergency_cid)}'));
1454                         $ext->add($context, $exten, '', new ext_set('TRUNKOUTCID', '${OUTCID_${ARG1}}'));
1455                         $ext->add($context, $exten, '', new ext_gotoif('$["${EMERGENCYROUTE:1:2}" = ""]', 'trunkcid'));  // check EMERGENCY ROUTE
1456                         $ext->add($context, $exten, '', new ext_gotoif('$["${EMERGENCYCID:1:2}" = ""]', 'trunkcid'));  // empty EMERGENCY CID, so default back to trunk
1457                         $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${EMERGENCYCID}'));  // emergency cid for device
1458                         $ext->add($context, $exten, '', new ext_goto('report'));
1459                         $ext->add($context, $exten, 'trunkcid', new ext_gotoif('$["${TRUNKOUTCID:1:2}" = ""]', 'usercid'));  // check for CID override for trunk (global var)
1460                         $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${TRUNKOUTCID}'));
1461                         $ext->add($context, $exten, 'usercid', new ext_gotoif('$["${USEROUTCID:1:2}" = ""]', 'report'));  // check CID override for extension
1462                         $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${USEROUTCID}'));
1463                         //$ext->add($context, $exten, '', new ext_gotoif('$["x${CALLERID(name)}"!="xhidden"]', 'checkname', 'hidecid'));  // check CID blocking for extension
1464                         $ext->add($context, $exten, '', new ext_gotoif('$["x${CALLERID(name)}"!="xhidden"]', 'report', 'hidecid'));  // check CID blocking for extension
1465                         $ext->add($context, $exten, 'hidecid', new ext_setcallerpres('prohib_passed_screen'));  // Only works with ISDN (T1/E1/BRI)
1466                         //$ext->add($context, $exten, 'checkname', new ext_execif('$[ $[ "${CALLERID(number)}" = "${REALCALLERIDNUM}" ] & $[ "${CALLERID(name)}" = "" ] ]', 'Set', 'CALLERID(name)=${REALCALLERIDNAME}'));
1467                         $ext->add($context, $exten, 'report', new ext_noop('CallerID set to ${CALLERID(all)}'));                       
1468
1469                        
1470                         /*
1471                          * Adds a dynamic agent/member to a Queue
1472                          * Prompts for call-back number - in not entered, uses CIDNum
1473                          */
1474
1475                         $context = 'macro-agent-add';
1476                         $exten = 's';
1477                        
1478                         $ext->add($context, $exten, '', new ext_wait(1));
1479                         $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
1480                         $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-login'));  // get callback number from user
1481                         $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" != ""]', 'a7'));  // if user just pressed # or timed out, use cidnum
1482                         $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}'));
1483                         $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}'));
1484                         $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
1485                         $ext->add($context, $exten, 'a7', new ext_gotoif('$["${CALLBACKNUM}" = "${ARG1}"]', 'invalid'));  // Error, they put in the queue number
1486                         $ext->add($context, $exten, '', new ext_execif('$["${ARG2}" != ""]', 'Authenticate', '${ARG2}'));
1487                         $ext->add($context, $exten, 'a9', new ext_addqueuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n'));  // using chan_local allows us to have agents over trunks
1488                         $ext->add($context, $exten, '', new ext_userevent('Agentlogin', 'Agent: ${CALLBACKNUM}'));
1489                         $ext->add($context, $exten, '', new ext_wait(1));
1490                         $ext->add($context, $exten, '', new ext_playback('agent-loginok&with&extension'));
1491                         $ext->add($context, $exten, '', new ext_saydigits('${CALLBACKNUM}'));
1492                         $ext->add($context, $exten, '', new ext_hangup());
1493                         $ext->add($context, $exten, '', new ext_macroexit());
1494                         $ext->add($context, $exten, 'invalid', new ext_playback('pbx-invalid'));
1495                         $ext->add($context, $exten, '', new ext_goto('a3'));
1496
1497                         /*
1498                          * Removes a dynamic agent/member from a Queue
1499                          * Prompts for call-back number - in not entered, uses CIDNum
1500                          */
1501
1502                         $context = 'macro-agent-del';
1503                        
1504                         $ext->add($context, $exten, '', new ext_wait(1));
1505                         $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
1506                         $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-logoff'));  // get callback number from user
1507                         $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a5', 'a7'));  // if user just pressed # or timed out, use cidnum
1508                         $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}'));
1509                         $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}'));
1510                         $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
1511                         $ext->add($context, $exten, 'a7', new ext_removequeuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n'));
1512                         $ext->add($context, $exten, '', new ext_userevent('RefreshQueue'));
1513                         $ext->add($context, $exten, '', new ext_wait(1));
1514                         $ext->add($context, $exten, '', new ext_playback('agent-loggedoff'));
1515                         $ext->add($context, $exten, '', new ext_hangup());
1516
1517                         $context = 'macro-systemrecording';
1518                        
1519                         $ext->add($context, 's', '', new ext_goto(1, '${ARG1}'));
1520                        
1521                         $exten = 'dorecord';
1522                        
1523                         $ext->add($context, $exten, '', new ext_record('/tmp/${AMPUSER}-ivrrecording:wav'));
1524                         $ext->add($context, $exten, '', new ext_wait(1));
1525                         $ext->add($context, $exten, '', new ext_goto(1, 'confmenu'));
1526
1527                         $exten = 'docheck';
1528                        
1529                         $ext->add($context, $exten, '', new ext_playback('/tmp/${AMPUSER}-ivrrecording'));
1530                         $ext->add($context, $exten, '', new ext_wait(1));
1531                         $ext->add($context, $exten, '', new ext_goto(1, 'confmenu'));
1532
1533                         $exten = 'confmenu';
1534                         if (version_compare($version, "1.4", "ge")) {
1535                                 $ext->add($context, $exten, '', new ext_background('to-listen-to-it&press-1&to-rerecord-it&press-star,m,${CHANNEL(language)},macro-systemrecording'));
1536                         } else {
1537                                 $ext->add($context, $exten, '', new ext_background('to-listen-to-it&press-1&to-rerecord-it&press-star,m,${LANGUAGE},macro-systemrecording'));
1538                         }
1539                         $ext->add($context, $exten, '', new ext_read('RECRESULT', '', 1, '', '', 4));
1540                         $ext->add($context, $exten, '', new ext_gotoif('$["x${RECRESULT}"="x*"]', 'dorecord,1'));
1541                         $ext->add($context, $exten, '', new ext_gotoif('$["x${RECRESULT}"="x1"]', 'docheck,1'));
1542                         $ext->add($context, $exten, '', new ext_goto(1));
1543                        
1544                         $ext->add($context, '1', '', new ext_goto(1, 'docheck'));
1545                         $ext->add($context, '*', '', new ext_goto(1, 'dorecord'));
1546                        
1547                         $ext->add($context, 't', '', new ext_playback('goodbye'));
1548                         $ext->add($context, 't', '', new ext_hangup());
1549                        
1550                         $ext->add($context, 'i', '', new ext_playback('pm-invalid-option'));
1551                         $ext->add($context, 'i', '', new ext_goto(1, 'confmenu'));
1552
1553                         $ext->add($context, 'h', '', new ext_hangup());
1554                        
1555                 break;
1556         }
1557 }
1558
1559 /* begin page.ampusers.php functions */
1560
1561 function core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections) {
1562         $sql = "INSERT INTO ampusers (username, password, extension_low, extension_high, deptname, sections) VALUES (";
1563         $sql .= "'".$username."',";
1564         $sql .= "'".$password."',";
1565         $sql .= "'".$extension_low."',";
1566         $sql .= "'".$extension_high."',";
1567         $sql .= "'".$deptname."',";
1568         $sql .= "'".implode(";",$sections)."');";
1569        
1570         sql($sql,"query");
1571 }
1572
1573 function core_ampusers_del($username) {
1574         $sql = "DELETE FROM ampusers WHERE username = '".$username."'";
1575         sql($sql,"query");
1576 }
1577
1578 function core_ampusers_list() {
1579         $sql = "SELECT username FROM ampusers ORDER BY username";
1580         return sql($sql,"getAll");
1581 }
1582
1583 /* end page.ampusers.php functions */
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593 /* begin page.did.php functions */
1594
1595 function core_did_list($order='extension'){
1596         switch ($order) {
1597                 case 'description':
1598                         $sql = "SELECT * FROM incoming ORDER BY description,extension,cidnum";
1599                         break;
1600                 case 'extension':
1601                 default:
1602                         $sql = "SELECT * FROM incoming ORDER BY extension,cidnum";
1603         }
1604         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1605 }
1606
1607 function core_did_get($extension="",$cidnum=""){
1608         $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1609         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1610 }
1611
1612 function core_did_del($extension,$cidnum){
1613         $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1614         sql($sql);
1615 }
1616
1617 function core_did_edit($old_extension,$old_cidnum, $incoming){
1618
1619         $old_extension = addslashes(trim($old_extension));
1620         $old_cidnum = addslashes(trim($old_cidnum));
1621
1622         $incoming['extension'] = trim($incoming['extension']);
1623         $incoming['cidnum'] = trim($incoming['cidnum']);
1624
1625         $extension = addslashes($incoming['extension']);
1626         $cidnum = addslashes($incoming['cidnum']);
1627
1628         // if did or cid changed, then check to make sure that this pair is not already being used.
1629         //
1630         if (($extension != $old_extension) || ($cidnum != $old_cidnum)) {
1631                 $existing=core_did_get($extension,$cidnum);
1632                 if (empty($existing) && (trim($cidnum) == "")) {
1633                         $existing_directdid = core_users_directdid_get($extension);
1634                 } else {
1635                         $existing_directdid = "";
1636                 }
1637         } else {
1638                 $existing = $existing_directdid = "";
1639         }
1640
1641         if (empty($existing) && empty($existing_directdid)) {
1642                 core_did_del($old_extension,$old_cidnum);
1643                 core_did_add($incoming);
1644                 return true;
1645         } else {
1646                 if (!empty($existing)) {
1647                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1648                 } else {
1649                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1650                 }
1651                 return false;
1652         }
1653 }
1654
1655 function core_did_add($incoming){
1656         foreach ($incoming as $key => $val) { ${$key} = addslashes($val); } // create variables from request
1657
1658         // Check to make sure the did is not being used elsewhere
1659         //
1660         $existing=core_did_get($extension,$cidnum);
1661         if (empty($existing) && (trim($cidnum) == "")) {
1662                 $existing_directdid = core_users_directdid_get($extension);
1663         } else {
1664                 $existing_directdid = "";
1665         }
1666
1667         if (empty($existing) && empty($existing_directdid)) {
1668                 $destination=${$goto0.'0'};
1669                 $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')";
1670                 sql($sql);
1671                 return true;
1672         } else {
1673                 if (!empty($existing)) {
1674                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1675                 } else {
1676                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1677                 }
1678                 return false;
1679         }
1680 }
1681
1682 /* end page.did.php functions */
1683
1684
1685
1686
1687
1688
1689
1690 /* begin page.devices.php functions */
1691
1692 //get the existing devices
1693 function core_devices_list($tech="all") {
1694         $sql = "SELECT id,description FROM devices";
1695         switch (strtoupper($tech)) {
1696                 case "IAX":
1697                         $sql .= " WHERE tech = 'iax2'";
1698                         break;
1699                 case "IAX2":
1700                 case "SIP":
1701                 case "ZAP":
1702                         $sql .= " WHERE tech = '".strtolower($tech)."'";
1703                         break;
1704                 case "ALL":
1705                 default:
1706         }
1707         $sql .= ' ORDER BY id';
1708         $results = sql($sql,"getAll");
1709
1710         foreach($results as $result){
1711                 if (checkRange($result[0])){
1712                         $extens[] = array(
1713                                 0=>$result[0],  // for backwards compatibility
1714                                 1=>$result[1],
1715                                 'id'=>$result[0], // FETCHMODE_ASSOC emulation
1716                                 'description'=>$result[1],
1717                         );
1718                 }
1719         }
1720         if (isset($extens)) {
1721                 return $extens;
1722         } else {
1723                 return null;
1724         }
1725 }
1726
1727
1728 function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){
1729         global $amp_conf;
1730         global $currentFile;
1731         global $astman;
1732
1733         $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
1734
1735         if (trim($id) == '' ) {
1736                 if ($display != 'extensions') {
1737                         echo "<script>javascript:alert('"._("You must put in a device id")."');</script>";
1738                 }
1739                 return false;
1740         }
1741        
1742         //ensure this id is not already in use
1743         $devices = core_devices_list();
1744         if (is_array($devices)) {
1745                 foreach($devices as $device) {
1746                         if ($device[0] === $id) {
1747                                 if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
1748                                 return false;
1749                         }
1750                 }
1751         }
1752         //unless defined, $dial is TECH/id
1753         if ( $dial == '' ) {
1754                 //zap is an exception
1755                 if ( strtolower($tech) == "zap" ) {
1756                         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1757                         $dial = 'ZAP/'.$zapchan;
1758                 } else {
1759                         $dial = strtoupper($tech)."/".$id;
1760                 }
1761         }
1762        
1763         //check to see if we are requesting a new user
1764         if ($user == "new") {
1765                 $user = $id;
1766                 $jump = true;
1767         }
1768        
1769         if(!get_magic_quotes_gpc()) {
1770                 if(!empty($emergency_cid))
1771                         $emergency_cid = addslashes($emergency_cid);
1772                 if(!empty($description))
1773                         $description = addslashes($description);
1774         }
1775        
1776         //insert into devices table
1777         $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
1778         sql($sql);
1779        
1780         //add details to astdb
1781         if ($astman) {
1782                 // if adding or editting a fixed device, user property should always be set
1783                 if ($devicetype == 'fixed' || !$editmode) {
1784                         $astman->database_put("DEVICE",$id."/user",$user);
1785                 }
1786                 // If changing from a fixed to an adhoc, the user property should be intialized
1787                 // to the new default, not remain as the previous fixed user
1788                 if ($editmode) {
1789                         $previous_type = $astman->database_get("DEVICE",$id."/type");
1790                         if ($previous_type == 'fixed' && $devicetype == 'adhoc') {
1791                                 $astman->database_put("DEVICE",$id."/user",$user);
1792                         }
1793                 }
1794                 $astman->database_put("DEVICE",$id."/dial",$dial);
1795                 $astman->database_put("DEVICE",$id."/type",$devicetype);
1796                 $astman->database_put("DEVICE",$id."/default_user",$user);
1797                 if($emergency_cid != '') {
1798                         $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1799                 }
1800
1801                 if ($user != "none") {
1802                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1803                         if (empty($existingdevices)) {
1804                                 $astman->database_put("AMPUSER",$user."/device",$id);
1805                         } else {
1806                                 $existingdevices_array = explode('&',$existingdevices);
1807                                 if (!in_array($id, $existingdevices_array)) {
1808                                         $existingdevices_array[]=$id;
1809                                         $existingdevices = implode('&',$existingdevices_array);
1810                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices);
1811                                 }
1812                         }
1813                 }
1814
1815         } else {
1816                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1817         }
1818        
1819         // create a voicemail symlink if needed
1820         $thisUser = core_users_get($user);
1821         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1822                 if(empty($thisUser['voicemail'])) {
1823                         $vmcontext = "default";
1824                 } else {
1825                         $vmcontext = $thisUser['voicemail'];
1826                 }
1827                
1828                 //voicemail symlink
1829                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1830                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1831         }
1832                
1833         //take care of sip/iax/zap config
1834         $funct = "core_devices_add".strtolower($tech);
1835         if(function_exists($funct)){
1836                 $funct($id);
1837         }
1838        
1839 /*      if($user != "none") {
1840                 core_hint_add($user);
1841         }*/
1842        
1843         //if we are requesting a new user, let's jump to users.php
1844         if (isset($jump)) {
1845                 echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
1846         }
1847         return true;
1848 }
1849
1850 function core_devices_del($account,$editmode=false){
1851         global $amp_conf;
1852         global $currentFile;
1853         global $astman;
1854        
1855         //get all info about device
1856         $devinfo = core_devices_get($account);
1857        
1858         //delete details to astdb
1859         if ($astman) {
1860                 // If a user was selected, remove this device from the user
1861                 $deviceuser = $astman->database_get("DEVICE",$account."/user");
1862                 if (isset($deviceuser) && $deviceuser != "none") {
1863                         // Remove the device record from the user's device list
1864                         $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
1865
1866                         // We need to remove just this user and leave the rest alone
1867                         $userdevicesarr = explode("&", $userdevices);
1868                         $userdevicesarr_hash = array_flip($userdevicesarr);
1869                         unset($userdevicesarr_hash[$account]);
1870                         $userdevicesarr = array_flip($userdevicesarr_hash);
1871                         $userdevices = implode("&", $userdevicesarr);
1872                        
1873                         if (empty($userdevices)) {
1874                                         $astman->database_del("AMPUSER",$deviceuser."/device");
1875                         } else {
1876                                         $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
1877                         }
1878                 }
1879                 if (! $editmode) {
1880                         $astman->database_del("DEVICE",$account."/dial");
1881                         $astman->database_del("DEVICE",$account."/type");
1882                         $astman->database_del("DEVICE",$account."/user");
1883                         $astman->database_del("DEVICE",$account."/default_user");
1884                         $astman->database_del("DEVICE",$account."/emergency_cid");
1885                 }
1886
1887                 //delete from devices table
1888                 $sql="DELETE FROM devices WHERE id = \"$account\"";
1889                 sql($sql);
1890
1891                 //voicemail symlink
1892                 exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
1893         } else {
1894                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1895         }
1896        
1897         //take care of sip/iax/zap config
1898         $funct = "core_devices_del".strtolower($devinfo['tech']);
1899         if(function_exists($funct)){
1900                 $funct($account);
1901         }
1902 }
1903
1904 function core_devices_get($account){
1905         //get all the variables for the meetme
1906         $sql = "SELECT * FROM devices WHERE id = '$account'";
1907         $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1908        
1909         //take care of sip/iax/zap config
1910         $funct = "core_devices_get".strtolower($results['tech']);
1911         if (!empty($results['tech']) && function_exists($funct)) {
1912                 $devtech = $funct($account);
1913                 if (is_array($devtech)){
1914                         $results = array_merge($results,$devtech);
1915                 }
1916         }
1917        
1918         return $results;
1919 }
1920
1921 // this function rebuilds the astdb based on device table contents
1922 // used on devices.php if action=resetall
1923 function core_devices2astdb(){
1924         global $astman;
1925         global $amp_conf;
1926
1927         $sql = "SELECT * FROM devices";
1928         $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1929
1930         //add details to astdb
1931         if ($astman) {
1932                 $astman->database_deltree("DEVICE");
1933                 foreach ($devresults as $dev) {
1934                         extract($dev); 
1935                         $astman->database_put("DEVICE",$id."/dial",$dial);
1936                         $astman->database_put("DEVICE",$id."/type",$devicetype);
1937                         $astman->database_put("DEVICE",$id."/user",$user);             
1938                         $astman->database_put("DEVICE",$id."/default_user",$user);
1939                         if(trim($emergency_cid) != '') {
1940                                 $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1941                         }
1942                         // If a user is selected, add this device to the user
1943                         if ($user != "none") {
1944                                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1945                                         if (!empty($existingdevices)) {
1946                                                         $existingdevices .= "&";
1947                                         }
1948                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
1949                         }
1950                        
1951                         // create a voicemail symlink if needed
1952                         $thisUser = core_users_get($user);
1953                         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1954                                 if(empty($thisUser['voicemail']))
1955                                         $vmcontext = "default";
1956                                 else
1957                                         $vmcontext = $thisUser['voicemail'];
1958                                 //voicemail symlink
1959                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1960                                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1961                         }
1962                 }
1963                 return true;
1964         } else {
1965                 return false;
1966         }
1967 }
1968
1969 // this function rebuilds the astdb based on users table contents
1970 // used on devices.php if action=resetall
1971 function core_users2astdb(){
1972         global $amp_conf;
1973         global $astman;
1974
1975         $sql = "SELECT * FROM users";
1976         $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1977        
1978         //add details to astdb
1979         if ($astman) {
1980                 foreach($userresults as $usr) {
1981                         extract($usr);
1982                         $astman->database_put("AMPUSER",$extension."/password",$password);
1983                         $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
1984                         $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
1985                         $astman->database_put("AMPUSER",$extension."/recording",$recording);
1986                         $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
1987                         $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
1988                         $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
1989                 }       
1990                 return true;
1991         } else {
1992                 return false;
1993         }
1994
1995 //      TODO: this was...       
1996 //      return $astman->disconnect();
1997 //      is "true" the correct value...?
1998 }
1999
2000 //add to sip table
2001 function core_devices_addsip($account) {
2002         global $db;
2003         global $currentFile;
2004
2005         foreach ($_REQUEST as $req=>$data) {
2006                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2007                         $keyword = substr($req, 8);
2008                         if ( $keyword == 'dial' && $data == '' ) {
2009                                 $sipfields[] = array($account, $keyword, 'SIP/'.$account);
2010                         } elseif ($keyword == 'mailbox' && $data == '') {
2011                                 $sipfields[] = array($account,'mailbox',$account.'@device');
2012                         } else {
2013                                 $sipfields[] = array($account, $keyword, $data);
2014                         }
2015                 }
2016         }
2017        
2018         if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
2019                 $sipfields = array(
2020                         //array($account,'account',$account),
2021                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
2022                         array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
2023                         array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
2024                         array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
2025                         array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
2026                         array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
2027                         array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
2028                         array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
2029                         array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
2030                         array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
2031                         array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
2032                         array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
2033                         array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
2034                         array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
2035                         array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
2036                         array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
2037                         //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
2038                         //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
2039                         //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
2040                 );
2041         }
2042
2043         // Very bad
2044         $sipfields[] = array($account,'account',$account);     
2045         $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2046        
2047         // Where is this in the interface ??????
2048         $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2049         $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2050
2051         $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
2052         $result = $db->executeMultiple($compiled,$sipfields);
2053         if(DB::IsError($result)) {
2054                 die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table');   
2055         }
2056 }
2057
2058 function core_devices_delsip($account) {
2059         global $db;
2060         global $currentFile;
2061        
2062         $sql = "DELETE FROM sip WHERE id = '$account'";
2063         $result = $db->query($sql);
2064        
2065         if(DB::IsError($result)) {
2066                 die_freepbx($result->getMessage().$sql);
2067         }
2068 }
2069
2070 function core_devices_getsip($account) {
2071         global $db;
2072         $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
2073         $results = $db->getAssoc($sql);
2074         if(DB::IsError($results)) {
2075                 $results = null;
2076         }
2077        
2078         return $results;
2079 }
2080
2081 //add to iax table
2082 function core_devices_addiax2($account) {
2083         global $db;
2084         global $currentFile;
2085        
2086         foreach ($_REQUEST as $req=>$data) {
2087                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2088                         $keyword = substr($req, 8);
2089                         if ( $keyword == 'dial' && $data == '' ) {
2090                                 $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
2091                         } elseif ($keyword == 'mailbox' && $data == '') {
2092                                 $iaxfields[] = array($account,'mailbox',$account.'@device');
2093                         } else {
2094                                 $iaxfields[] = array($account, $keyword, $data);
2095                         }
2096                 }
2097         }
2098        
2099         if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
2100                 $iaxfields = array(
2101                         //array($account,'account',$account),
2102                         array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
2103                         array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
2104                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
2105                         array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
2106                         array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
2107                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
2108                         array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
2109                         array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
2110                         array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
2111                         array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
2112                         array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
2113                         array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
2114                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
2115                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
2116                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
2117                 );
2118         }
2119
2120         // Very bad
2121         $iaxfields[] = array($account,'account',$account);     
2122         $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2123         // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
2124         // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
2125         // callerid as a variable which gets picked up in macro-callerid.
2126         // Ref - http://bugs.digium.com/view.php?id=456
2127         $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
2128        
2129         // Where is this in the interface ??????
2130         $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2131         $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2132        
2133         $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
2134         $result = $db->executeMultiple($compiled,$iaxfields);
2135         if(DB::IsError($result)) {
2136                 die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
2137         }
2138 }
2139
2140 function core_devices_deliax2($account) {
2141         global $db;
2142         global $currentFile;
2143        
2144         $sql = "DELETE FROM iax WHERE id = '$account'";
2145         $result = $db->query($sql);
2146        
2147         if(DB::IsError($result)) {
2148                 die_freepbx($result->getMessage().$sql);
2149         }
2150 }
2151
2152 function core_devices_getiax2($account) {
2153         global $db;
2154         $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
2155         $results = $db->getAssoc($sql);
2156         if(DB::IsError($results)) {
2157                 $results = null;
2158         }
2159        
2160         return $results;
2161 }
2162
2163 function core_devices_addzap($account) {
2164         global $db;
2165         global $currentFile;
2166        
2167         foreach ($_REQUEST as $req=>$data) {
2168                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2169                         $keyword = substr($req, 8);
2170                         if ( $keyword == 'dial' && $data == '' ) {
2171                                 $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
2172                                 $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
2173                         } elseif ($keyword == 'mailbox' && $data == '') {
2174                                 $zapfields[] = array($account,'mailbox',$account.'@device');
2175                         } else {
2176                                 $zapfields[] = array($account, $keyword, $data);
2177                         }
2178                 }
2179         }
2180        
2181         if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
2182                 $zapfields = array(
2183                         //array($account,'account',$account),
2184                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
2185                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
2186                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
2187                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
2188                         array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
2189                         array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
2190                         array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
2191                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),       
2192                         array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
2193                         array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
2194                         array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
2195                         array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
2196                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),     
2197                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
2198                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
2199                         array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
2200                 );
2201         }
2202
2203         // Very bad
2204         $zapfields[] = array($account,'account',$account);     
2205         $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2206        
2207         // Where is this in the interface ??????
2208         $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2209         $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2210
2211         $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
2212         $result = $db->executeMultiple($compiled,$zapfields);
2213         if(DB::IsError($result)) {
2214                 die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
2215         }
2216 }
2217
2218 function core_devices_delzap($account) {
2219         global $db;
2220         global $currentFile;
2221        
2222         $sql = "DELETE FROM zap WHERE id = '$account'";
2223         $result = $db->query($sql);
2224         if(DB::IsError($result)) {
2225                 die_freepbx($result->getMessage().$sql);
2226         }
2227 }
2228
2229 function core_devices_getzap($account) {
2230         global $db;
2231         $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
2232         $results = $db->getAssoc($sql);
2233         if(DB::IsError($results)) {
2234                 $results = null;
2235         }
2236         return $results;
2237 }
2238 /* end page.devices.php functions */
2239
2240
2241
2242
2243 function core_hint_get($account){
2244         global $astman;
2245
2246         // We should always check the AMPUSER in case they logged into a device
2247         // but we will fall back to the old methond if $astman not open although
2248         // I'm pretty sure everything else will puke anyhow if not running
2249         //
2250         if ($astman) {
2251                 $device=$astman->database_get("AMPUSER",$account."/device");
2252                 $device_arr = explode('&',$device);
2253                 $sql = "SELECT dial from devices where id in ('".implode("','",$device_arr)."')";
2254         } else {
2255                 $sql = "SELECT dial from devices where user = '{$account}'";
2256         }
2257         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2258        
2259         //create an array of strings
2260         if (is_array($results)){
2261                 foreach ($results as $result) {
2262                         $dial[] = $result['dial'];
2263                 }
2264         }
2265        
2266         //create a string with & delimiter
2267         if (isset($dial) && is_array($dial)){
2268                 $hint = implode($dial,"&");
2269         } else {
2270                 if (isset($results[0]['dial'])) {
2271                         $hint = $results[0]['dial'];
2272                 } else {
2273                         $hint = null;
2274                 }
2275         }
2276        
2277         return $hint;
2278 }
2279
2280
2281
2282 /* begin page.users.php functions */
2283
2284 // get the existing extensions
2285 // the returned arrays contain [0]:extension [1]:name
2286 function core_users_list() {
2287         $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
2288
2289         //only allow extensions that are within administrator's allowed range
2290         foreach($results as $result){
2291                 if (checkRange($result[0])){
2292                         $extens[] = array($result[0],$result[1],$result[2]);
2293                 }
2294         }
2295        
2296         if (isset($extens)) {
2297                 sort($extens);
2298                 return $extens;
2299         } else {
2300                 return null;
2301         }
2302 }
2303
2304 function core_check_extensions($exten=true) {
2305         global $amp_conf;
2306
2307         $extenlist = array();
2308         if (is_array($exten) && empty($exten)) {
2309                 return $extenlist;
2310         }
2311         $sql = "SELECT extension, name FROM users ";
2312         if (is_array($exten)) {
2313                 $sql .= "WHERE extension in ('".implode("','",$exten)."')";
2314         }
2315         $sql .= " ORDER BY extension";
2316         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2317
2318         foreach ($results as $result) {
2319                 $thisexten = $result['extension'];
2320                 $extenlist[$thisexten]['description'] = _("User Extension: ").$result['name'];
2321                 $extenlist[$thisexten]['status'] = 'INUSE';
2322                 $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
2323                 $extenlist[$thisexten]['edit_url'] = "config.php?type=setup&display=$display&extdisplay=".urlencode($thisexten)."&skip=0";
2324         }
2325         return $extenlist;
2326 }
2327
2328 function core_check_destinations($dest=true) {
2329         global $active_modules;
2330
2331         $destlist = array();
2332         if (is_array($dest) && empty($dest)) {
2333                 return $destlist;
2334         }
2335         $sql = "SELECT extension, cidnum, description, destination FROM incoming ";
2336         if ($dest !== true) {
2337                 $sql .= "WHERE destination in ('".implode("','",$dest)."')";
2338         }
2339         $sql .= "ORDER BY extension, cidnum";
2340         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2341
2342         //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
2343
2344         foreach ($results as $result) {
2345                 $thisdest = $result['destination'];
2346                 $thisid   = $result['extension'].'/'.$result['cidnum'];
2347                 $destlist[] = array(
2348                         'dest' => $thisdest,
2349                         'description' => 'Inbound Route: '.$result['description'].' ('.$thisid.')',
2350                         'edit_url' => 'config.php?display=did&extdisplay='.urlencode($thisid),
2351                 );
2352         }
2353         return $destlist;
2354 }
2355
2356 function core_sipname_check($sipname, $extension) {
2357         global $db;
2358         if (!isset($sipname) || trim($sipname)=='')
2359                 return true;
2360
2361         $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
2362         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2363         if(DB::IsError($results)) {
2364         die_freepbx($results->getMessage().$sql);
2365         }
2366        
2367         if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
2368                 return false;
2369         else
2370                 return true;
2371 }
2372
2373 function core_users_add($vars, $editmode=false) {
2374         extract($vars);
2375        
2376         global $db;
2377         global $amp_conf;
2378         global $astman;
2379
2380         $thisexten = isset($thisexten) ? $thisexten : '';
2381
2382         if (trim($extension) == '' ) {
2383                 echo "<script>javascript:alert('"._("You must put in an extension (or user) number")."');</script>";
2384                 return false;
2385         }
2386
2387         //ensure this id is not already in use
2388         $extens = core_users_list();
2389         if(is_array($extens)) {
2390                 foreach($extens as $exten) {
2391                         if ($exten[0]===$extension) {
2392                                 echo "<script>javascript:alert('".sprintf(_("This user/extension %s is already in use"),$extension)."');</script>";
2393                                 return false;
2394                         }
2395                 }
2396         }
2397
2398         // clean and check the did to make sure it is not being used by another extension or in did routing
2399         //
2400         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2401         if (trim($directdid) != "") {
2402                 $existing=core_did_get($directdid,"");
2403                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2404                 if (!empty($existing) || !empty($existing_directdid)) {
2405                         if (!empty($existing)) {
2406                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2407                         } else {
2408                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2409                         }
2410                         return false;
2411                 }
2412         }
2413
2414         $sipname = preg_replace("/\s/" ,"", trim($sipname));
2415         if (! core_sipname_check($sipname, $extension)) {
2416                 echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
2417                 return false;
2418         }
2419        
2420         //build the recording variable
2421         $recording = "out=".$record_out."|in=".$record_in;
2422        
2423         //escape quotes and any other bad chars:
2424         if(!get_magic_quotes_gpc()) {
2425                 $outboundcid = addslashes($outboundcid);
2426                 $name = addslashes($name);
2427         }
2428
2429         //if voicemail is enabled, set the box@context to use
2430         //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
2431         if ( function_exists('voicemail_mailbox_get') ) {
2432                 $vmbox = voicemail_mailbox_get($extension);
2433                 if ( $vmbox == null ) {
2434                         $voicemail = "novm";
2435                         $vmx_state = "false";
2436                 } else {
2437                         $voicemail = $vmbox['vmcontext'];
2438                 }
2439         }
2440
2441         // MODIFICATION: (PL)
2442         // Added for directdid and didalert l for Alert Info distinctive ring)
2443         //
2444         // cleanup any non dial pattern characters prior to inserting into the database
2445         // then add directdid to the insert command.
2446         //
2447         // Clean replace any <> with () in display name - should have javascript stopping this but ...
2448         //
2449         $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
2450        
2451         //insert into users table
2452         $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
2453         $sql.= "$extension\", \"";
2454         $sql.= isset($password)?$password:'';
2455         $sql.= "\", \"";
2456         $sql.= isset($name)?$name:'';
2457         $sql.= "\", \"";
2458         $sql.= isset($voicemail)?$voicemail:'default';
2459         $sql.= "\", \"";
2460         $sql.= isset($ringtimer)?$ringtimer:'';
2461         $sql.= "\", \"";
2462         $sql.= isset($noanswer)?$noanswer:'';
2463         $sql.= "\", \"";
2464         $sql.= isset($recording)?$recording:'';
2465         $sql.= "\", \"";
2466         $sql.= isset($outboundcid)?$outboundcid:'';
2467         $sql.= "\", \"";
2468         $sql.= isset($directdid)?$directdid:'';
2469         $sql.= "\", \"";
2470         $sql.= isset($didalert)?$didalert:'';
2471
2472         $sql.= "\", \"";
2473         $sql.= isset($faxexten)?$faxexten:'';
2474         $sql.= "\", \"";
2475         $sql.= isset($faxemail)?$faxemail:'';
2476         $sql.= "\", \"";
2477         $sql.= isset($answer)?$answer:'';
2478         $sql.= "\", \"";
2479         $sql.= isset($wait)?$wait:'';
2480         $sql.= "\", \"";
2481         $sql.= isset($privacyman)?$privacyman:'';
2482         $sql.= "\", \"";
2483         $sql.= isset($mohclass)?$mohclass:'';
2484         $sql.= "\", \"";
2485         $sql.= isset($sipname)?$sipname:'';
2486         $sql.= "\")";
2487         sql($sql);
2488
2489         //write to astdb
2490         if ($astman) {
2491                 $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
2492                 $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
2493                 $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
2494                 $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
2495                 $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
2496                 $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
2497                 $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
2498                 $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
2499                 $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
2500                 if (!$editmode) {
2501                         $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
2502                 }
2503
2504                 if (trim($callwaiting) == 'enabled') {
2505                         $astman->database_put("CW",$extension,"\"ENABLED\"");
2506                 } else if (trim($callwaiting) == 'disabled') {
2507                         $astman->database_del("CW",$extension);
2508                 } else {
2509                         echo "ERROR: this state should not exist<br>";
2510                 }
2511
2512                 if ($vmx_state && $voicemail != "novm") {
2513
2514                         $unavail_mode="enabled";
2515                         $busy_mode="disabled";
2516                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2517
2518                         if (trim($vmx_state) == 'blocked') {
2519
2520                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
2521                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
2522
2523                         } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
2524
2525                                 $repeat="1";
2526                                 $timeout="2";
2527                                 $vmxopts_timeout="";
2528                                 $loops="1";
2529
2530                                 $mode="unavail";
2531                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
2532                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2533
2534                                 $mode="busy";
2535                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
2536                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2537                                
2538                         }
2539                 } else {
2540                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2541                         if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
2542                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
2543                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
2544                         }
2545                 }
2546         } else {
2547                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2548         }
2549         return true;
2550 }
2551
2552 function core_users_get($extension){
2553         global $db;
2554         global $amp_conf;
2555         global $astman;
2556         //get all the variables for the meetme
2557         $sql = "SELECT * FROM users WHERE extension = '$extension'";
2558         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2559         if(DB::IsError($results)) {
2560                 die_freepbx($results->getMessage().$sql);
2561         }
2562         if (empty($results)) {
2563                 return $results;
2564         }
2565        
2566         //explode recording vars
2567         $recording = explode("|",$results['recording']);
2568         if (isset($recording[1])) {
2569                 $recout = substr($recording[0],4);
2570                 $recin = substr($recording[1],3);
2571                 $results['record_in']=$recin;
2572                 $results['record_out']=$recout;
2573         } else {
2574                 $results['record_in']='Adhoc';
2575                 $results['record_out']='Adhoc';
2576         }
2577         if ($astman) {
2578                 $cw = $astman->database_get("CW",$extension);
2579                 $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
2580                 $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2581                 $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
2582                 $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
2583         } else {
2584                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2585         }
2586
2587         return $results;
2588 }
2589
2590 function core_users_del($extension, $editmode=false){
2591         global $db;
2592         global $amp_conf;
2593         global $astman;
2594        
2595         //delete from devices table
2596         $sql="DELETE FROM users WHERE extension = \"$extension\"";
2597         $results = $db->query($sql);
2598         if(DB::IsError($results)) {
2599                 die_freepbx($results->getMessage().$sql);
2600         }
2601
2602         //delete details to astdb
2603         if ($astman && !$editmode) {
2604                 $astman->database_del("AMPUSER",$extension."/password");
2605                 $astman->database_del("AMPUSER",$extension."/ringtimer");
2606                 $astman->database_del("AMPUSER",$extension."/noanswer");
2607                 $astman->database_del("AMPUSER",$extension."/recording");
2608                 $astman->database_del("AMPUSER",$extension."/outboundcid");
2609                 $astman->database_del("AMPUSER",$extension."/cidname");
2610                 $astman->database_del("AMPUSER",$extension."/cidnum");
2611                 $astman->database_del("AMPUSER",$extension."/voicemail");
2612                 $astman->database_del("AMPUSER",$extension."/device");
2613         }
2614 }
2615
2616 function core_users_directdid_get($directdid=""){
2617         if (empty($directdid)) {
2618                 return array();
2619         } else {
2620                 $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
2621                 return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2622         }
2623 }
2624
2625 function core_users_cleanastdb($extension) {
2626         // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
2627         // call forwarding, call waiting settings could hang around and bite someone if they
2628         // recycle an extension. Is called from page.xtns and page.users.
2629         global $amp_conf;
2630         global $astman;
2631
2632         if ($astman) {
2633                 $astman->database_del("CW",$extension);
2634                 $astman->database_del("CF",$extension);
2635                 $astman->database_del("CFB",$extension);
2636                 $astman->database_del("CFU",$extension);
2637                 $astman->database_deltree("AMPUSER/".$extension."/vmx");
2638
2639         } else {
2640                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2641         }
2642 }
2643
2644 function core_users_edit($extension,$vars){
2645         global $db;
2646         global $amp_conf;
2647         global $astman;
2648        
2649         //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
2650         if ($astman) {
2651                 $ud = $astman->database_get("AMPUSER",$extension."/device");
2652                 $current_vmcontext = $astman->database_get("AMPUSER",$extension."/voicemail");
2653                 $new_vmcontext = isset($vars['vmcontext']) ? $vars['vmcontext'] : 'novm';
2654                 $vars['device'] = $ud;
2655         } else {
2656                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2657         }
2658        
2659         $directdid=$vars['directdid'];
2660         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2661         // clean and check the did to make sure it is not being used by another extension or in did routing
2662         //
2663         if (trim($directdid) != "") {
2664                 $existing=core_did_get($directdid,"");
2665                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2666                 if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
2667                         if (!empty($existing)) {
2668                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2669                         } else {
2670                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2671                         }
2672                         return false;
2673                 }
2674         }
2675
2676         //delete and re-add
2677         if (core_sipname_check($vars['sipname'],$extension)) {
2678                 core_users_del($extension, true);
2679                 core_users_add($vars, true);
2680
2681                 // If the vmcontext has changed, we need to change all the links. In extension mode, the link
2682                 // to the current fixed device will get changed, but none others will
2683                 //
2684                 if ($current_vmcontext != $new_vmcontext) {
2685                         $user_devices = explode('&',$ud);
2686                         foreach ($user_devices as $user_device) {
2687                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$user_device);
2688                                 if ($new_context != 'novm') {
2689                                         exec("/bin/ln -s /var/spool/asterisk/voicemail/".$new_vmcontext."/".$extension."/ /var/spool/asterisk/voicemail/device/".$user_device);
2690                                 }
2691                         }
2692                 }
2693         }
2694         return true;
2695 }
2696
2697 function core_directdid_list(){
2698         $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
2699         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2700 }
2701
2702
2703
2704 function core_zapchandids_add($description, $channel, $did) {
2705         global $db;
2706
2707
2708         if (!ctype_digit(trim($channel)) || trim($channel) == '') {
2709                 echo "<script>javascript:alert('"._('Invalid Channel Number, must be numeric and not blank')."')</script>";
2710                 return false;
2711         }
2712         if (trim($did) == '') {
2713                 echo "<script>javascript:alert('"._('Invalid DID, must be a non-blank DID')."')</script>";
2714                 return false;
2715         }
2716
2717         $description = q($description);
2718         $channel     = q($channel);
2719         $did         = q($did);
2720
2721         $sql = "INSERT INTO zapchandids (channel, description, did) VALUES ($channel, $description, $did)";
2722         $results = $db->query($sql);
2723         if (DB::IsError($results)) {
2724                 if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) {
2725                         echo "<script>javascript:alert('"._("Error Duplicate Channel Entry")."')</script>";
2726                         return false;
2727                 } else {
2728                         die_freepbx($results->getMessage()."<br><br>".$sql);
2729                 }
2730         }
2731         return true;
2732 }
2733
2734 function core_zapchandids_edit($description, $channel, $did) {
2735         global $db;
2736
2737         $description = q($description);
2738         $channel     = q($channel);
2739         $did         = q($did);
2740
2741         $sql = "UPDATE zapchandids SET description = $description, did = $did WHERE channel = $channel";
2742         $results = $db->query($sql);
2743         if (DB::IsError($results)) {
2744                 die_freepbx($results->getMessage()."<br><br>".$sql);
2745         }
2746         return true;
2747 }
2748
2749 function core_zapchandids_delete($channel) {
2750         global $db;
2751
2752         $channel     = q($channel);
2753
2754         $sql = "DELETE FROM zapchandids WHERE channel = $channel";
2755         $results = $db->query($sql);
2756         if (DB::IsError($results)) {
2757                 die_freepbx($results->getMessage()."<br><br>".$sql);
2758         }
2759         return true;
2760 }
2761
2762 function core_zapchandids_list() {
2763         global $db;
2764
2765         $sql = "SELECT * FROM zapchandids ORDER BY channel";
2766         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2767 }
2768
2769 function core_zapchandids_get($channel) {
2770         global $db;
2771
2772         $channel     = q($channel);
2773
2774         $sql = "SELECT * FROM zapchandids WHERE channel = $channel";
2775         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2776 }
2777
2778 /* end page.users.php functions */
2779
2780
2781
2782
2783
2784 /* begin page.trunks.php functions */
2785
2786 // we're adding ,don't require a $trunknum
2787 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2788         global $db;
2789        
2790         // find the next available ID
2791         $trunknum = 1;
2792
2793         // This is pretty ugle, will fix when we redo trunks and routes with proper uniqueids.
2794         // get the list, sort them, then look for a hole and use it, or overflow to the end if
2795         // not and use that
2796         //
2797         $trunk_hash = array();
2798         foreach(core_trunks_list() as $trunk) {
2799                 $trunknum = ltrim($trunk[0],"OUT_");
2800                 $trunk_hash[] = $trunknum;
2801         }
2802         sort($trunk_hash);
2803         $trunknum = 1;
2804         foreach ($trunk_hash as $trunk_id) {
2805                 if ($trunk_id != $trunknum) {
2806                         break;
2807                 }
2808                 $trunknum++;
2809         }
2810        
2811         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2812        
2813         return $trunknum;
2814 }
2815
2816 function core_trunks_del($trunknum, $tech = null) {
2817         global $db;
2818        
2819         if ($tech === null) { // in EditTrunk, we get this info anyways
2820                 $tech = core_trunks_getTrunkTech($trunknum);
2821         }
2822
2823         //delete from globals table
2824         sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
2825        
2826         //write outids
2827         core_trunks_writeoutids();
2828
2829         // conditionally, delete from iax or sip
2830         switch (strtolower($tech)) {
2831                 case "iax":
2832                 case "iax2":
2833                         sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2834                 break;
2835                 case "sip":
2836                         sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2837                 break;
2838         }
2839 }
2840
2841 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2842         //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2843         $tech = core_trunks_getTrunkTech($trunknum);
2844         core_trunks_del($trunknum, $tech);
2845         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2846 }
2847
2848 // just used internally by addTrunk() and editTrunk()
2849 //obsolete
2850 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2851         global $db;
2852        
2853         if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
2854        
2855         //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2856        
2857         // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
2858         $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
2859         $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
2860        
2861         $glofields = array(
2862                         array('OUT_'.$trunknum, $outval),
2863                         array('OUTPREFIX_'.$trunknum, $dialoutprefix),
2864                         array('OUTMAXCHANS_'.$trunknum, $maxchans),
2865                         array('OUTCID_'.$trunknum, $outcid),
2866                         array('OUTKEEPCID_'.$trunknum, $keepcid),
2867                         array('OUTFAIL_'.$trunknum, $failtrunk),
2868                         array('OUTDISABLE_'.$trunknum, $disabletrunk),
2869                         );
2870                        
2871         unset($techtemp);
2872        
2873         $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
2874         $result = $db->executeMultiple($compiled,$glofields);
2875         if(DB::IsError($result)) {
2876                 die_freepbx($result->getMessage()."<br><br>".$sql);
2877         }
2878        
2879         core_trunks_writeoutids();
2880
2881         $disable_flag = ($disabletrunk == "on")?1:0;
2882        
2883         switch (strtolower(