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

Revision 8624, 189.3 kB (checked in by mickecarlsson, 2 months ago)

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

................

r8622 | mickecarlsson | 2010-01-15 17:53:48 +0100 (Fri, 15 Jan 2010) | 9 lines


Merged revisions 8620 via svnmerge from
http://svn.freepbx.org/modules/branches/2.6


........

r8620 | mickecarlsson | 2010-01-15 12:06:43 +0100 (Fri, 15 Jan 2010) | 1 line


re r8613 add missing global

........

................

  • 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         global $db;
1609         $cidnum = $db->escapeSimple($cidnum);
1610         $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1611         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1612 }
1613
1614 function core_did_del($extension,$cidnum){
1615         global $db;
1616         $cidnum = $db->escapeSimple($cidnum);
1617         $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\"";
1618         sql($sql);
1619 }
1620
1621 function core_did_edit($old_extension,$old_cidnum, $incoming){
1622
1623         $old_extension = addslashes(trim($old_extension));
1624         $old_cidnum = addslashes(trim($old_cidnum));
1625
1626         $incoming['extension'] = trim($incoming['extension']);
1627         $incoming['cidnum'] = trim($incoming['cidnum']);
1628
1629         $extension = addslashes($incoming['extension']);
1630         $cidnum = addslashes($incoming['cidnum']);
1631
1632         // if did or cid changed, then check to make sure that this pair is not already being used.
1633         //
1634         if (($extension != $old_extension) || ($cidnum != $old_cidnum)) {
1635                 $existing=core_did_get($extension,$cidnum);
1636                 if (empty($existing) && (trim($cidnum) == "")) {
1637                         $existing_directdid = core_users_directdid_get($extension);
1638                 } else {
1639                         $existing_directdid = "";
1640                 }
1641         } else {
1642                 $existing = $existing_directdid = "";
1643         }
1644
1645         if (empty($existing) && empty($existing_directdid)) {
1646                 core_did_del($old_extension,$old_cidnum);
1647                 core_did_add($incoming);
1648                 return true;
1649         } else {
1650                 if (!empty($existing)) {
1651                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1652                 } else {
1653                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1654                 }
1655                 return false;
1656         }
1657 }
1658
1659 function core_did_add($incoming){
1660         foreach ($incoming as $key => $val) { ${$key} = addslashes($val); } // create variables from request
1661
1662         // Check to make sure the did is not being used elsewhere
1663         //
1664         $existing=core_did_get($extension,$cidnum);
1665         if (empty($existing) && (trim($cidnum) == "")) {
1666                 $existing_directdid = core_users_directdid_get($extension);
1667         } else {
1668                 $existing_directdid = "";
1669         }
1670
1671         if (empty($existing) && empty($existing_directdid)) {
1672                 $destination=${$goto0.'0'};
1673                 $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')";
1674                 sql($sql);
1675                 return true;
1676         } else {
1677                 if (!empty($existing)) {
1678                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
1679                 } else {
1680                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1681                 }
1682                 return false;
1683         }
1684 }
1685
1686 /* end page.did.php functions */
1687
1688
1689
1690
1691
1692
1693
1694 /* begin page.devices.php functions */
1695
1696 //get the existing devices
1697 function core_devices_list($tech="all") {
1698         $sql = "SELECT id,description FROM devices";
1699         switch (strtoupper($tech)) {
1700                 case "IAX":
1701                         $sql .= " WHERE tech = 'iax2'";
1702                         break;
1703                 case "IAX2":
1704                 case "SIP":
1705                 case "ZAP":
1706                         $sql .= " WHERE tech = '".strtolower($tech)."'";
1707                         break;
1708                 case "ALL":
1709                 default:
1710         }
1711         $sql .= ' ORDER BY id';
1712         $results = sql($sql,"getAll");
1713
1714         foreach($results as $result){
1715                 if (checkRange($result[0])){
1716                         $extens[] = array(
1717                                 0=>$result[0],  // for backwards compatibility
1718                                 1=>$result[1],
1719                                 'id'=>$result[0], // FETCHMODE_ASSOC emulation
1720                                 'description'=>$result[1],
1721                         );
1722                 }
1723         }
1724         if (isset($extens)) {
1725                 return $extens;
1726         } else {
1727                 return null;
1728         }
1729 }
1730
1731
1732 function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){
1733         global $amp_conf;
1734         global $currentFile;
1735         global $astman;
1736
1737         $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
1738
1739         if (trim($id) == '' ) {
1740                 if ($display != 'extensions') {
1741                         echo "<script>javascript:alert('"._("You must put in a device id")."');</script>";
1742                 }
1743                 return false;
1744         }
1745        
1746         //ensure this id is not already in use
1747         $devices = core_devices_list();
1748         if (is_array($devices)) {
1749                 foreach($devices as $device) {
1750                         if ($device[0] === $id) {
1751                                 if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
1752                                 return false;
1753                         }
1754                 }
1755         }
1756         //unless defined, $dial is TECH/id
1757         if ( $dial == '' ) {
1758                 //zap is an exception
1759                 if ( strtolower($tech) == "zap" ) {
1760                         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1761                         $dial = 'ZAP/'.$zapchan;
1762                 } else {
1763                         $dial = strtoupper($tech)."/".$id;
1764                 }
1765         }
1766        
1767         //check to see if we are requesting a new user
1768         if ($user == "new") {
1769                 $user = $id;
1770                 $jump = true;
1771         }
1772        
1773         if(!get_magic_quotes_gpc()) {
1774                 if(!empty($emergency_cid))
1775                         $emergency_cid = addslashes($emergency_cid);
1776                 if(!empty($description))
1777                         $description = addslashes($description);
1778         }
1779        
1780         //insert into devices table
1781         $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
1782         sql($sql);
1783        
1784         //add details to astdb
1785         if ($astman) {
1786                 // if adding or editting a fixed device, user property should always be set
1787                 if ($devicetype == 'fixed' || !$editmode) {
1788                         $astman->database_put("DEVICE",$id."/user",$user);
1789                 }
1790                 // If changing from a fixed to an adhoc, the user property should be intialized
1791                 // to the new default, not remain as the previous fixed user
1792                 if ($editmode) {
1793                         $previous_type = $astman->database_get("DEVICE",$id."/type");
1794                         if ($previous_type == 'fixed' && $devicetype == 'adhoc') {
1795                                 $astman->database_put("DEVICE",$id."/user",$user);
1796                         }
1797                 }
1798                 $astman->database_put("DEVICE",$id."/dial",$dial);
1799                 $astman->database_put("DEVICE",$id."/type",$devicetype);
1800                 $astman->database_put("DEVICE",$id."/default_user",$user);
1801                 if($emergency_cid != '') {
1802                         $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1803                 }
1804
1805                 if ($user != "none") {
1806                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1807                         if (empty($existingdevices)) {
1808                                 $astman->database_put("AMPUSER",$user."/device",$id);
1809                         } else {
1810                                 $existingdevices_array = explode('&',$existingdevices);
1811                                 if (!in_array($id, $existingdevices_array)) {
1812                                         $existingdevices_array[]=$id;
1813                                         $existingdevices = implode('&',$existingdevices_array);
1814                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices);
1815                                 }
1816                         }
1817                 }
1818
1819         } else {
1820                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1821         }
1822        
1823         // create a voicemail symlink if needed
1824         $thisUser = core_users_get($user);
1825         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1826                 if(empty($thisUser['voicemail'])) {
1827                         $vmcontext = "default";
1828                 } else {
1829                         $vmcontext = $thisUser['voicemail'];
1830                 }
1831                
1832                 //voicemail symlink
1833                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1834                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1835         }
1836                
1837         //take care of sip/iax/zap config
1838         $funct = "core_devices_add".strtolower($tech);
1839         if(function_exists($funct)){
1840                 $funct($id);
1841         }
1842        
1843 /*      if($user != "none") {
1844                 core_hint_add($user);
1845         }*/
1846        
1847         //if we are requesting a new user, let's jump to users.php
1848         if (isset($jump)) {
1849                 echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
1850         }
1851         return true;
1852 }
1853
1854 function core_devices_del($account,$editmode=false){
1855         global $amp_conf;
1856         global $currentFile;
1857         global $astman;
1858        
1859         //get all info about device
1860         $devinfo = core_devices_get($account);
1861        
1862         //delete details to astdb
1863         if ($astman) {
1864                 // If a user was selected, remove this device from the user
1865                 $deviceuser = $astman->database_get("DEVICE",$account."/user");
1866                 if (isset($deviceuser) && $deviceuser != "none") {
1867                         // Remove the device record from the user's device list
1868                         $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
1869
1870                         // We need to remove just this user and leave the rest alone
1871                         $userdevicesarr = explode("&", $userdevices);
1872                         $userdevicesarr_hash = array_flip($userdevicesarr);
1873                         unset($userdevicesarr_hash[$account]);
1874                         $userdevicesarr = array_flip($userdevicesarr_hash);
1875                         $userdevices = implode("&", $userdevicesarr);
1876                        
1877                         if (empty($userdevices)) {
1878                                         $astman->database_del("AMPUSER",$deviceuser."/device");
1879                         } else {
1880                                         $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
1881                         }
1882                 }
1883                 if (! $editmode) {
1884                         $astman->database_del("DEVICE",$account."/dial");
1885                         $astman->database_del("DEVICE",$account."/type");
1886                         $astman->database_del("DEVICE",$account."/user");
1887                         $astman->database_del("DEVICE",$account."/default_user");
1888                         $astman->database_del("DEVICE",$account."/emergency_cid");
1889                 }
1890
1891                 //delete from devices table
1892                 $sql="DELETE FROM devices WHERE id = \"$account\"";
1893                 sql($sql);
1894
1895                 //voicemail symlink
1896                 exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
1897         } else {
1898                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1899         }
1900        
1901         //take care of sip/iax/zap config
1902         $funct = "core_devices_del".strtolower($devinfo['tech']);
1903         if(function_exists($funct)){
1904                 $funct($account);
1905         }
1906 }
1907
1908 function core_devices_get($account){
1909         //get all the variables for the meetme
1910         $sql = "SELECT * FROM devices WHERE id = '$account'";
1911         $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1912        
1913         //take care of sip/iax/zap config
1914         $funct = "core_devices_get".strtolower($results['tech']);
1915         if (!empty($results['tech']) && function_exists($funct)) {
1916                 $devtech = $funct($account);
1917                 if (is_array($devtech)){
1918                         $results = array_merge($results,$devtech);
1919                 }
1920         }
1921        
1922         return $results;
1923 }
1924
1925 // this function rebuilds the astdb based on device table contents
1926 // used on devices.php if action=resetall
1927 function core_devices2astdb(){
1928         global $astman;
1929         global $amp_conf;
1930
1931         $sql = "SELECT * FROM devices";
1932         $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1933
1934         //add details to astdb
1935         if ($astman) {
1936                 $astman->database_deltree("DEVICE");
1937                 foreach ($devresults as $dev) {
1938                         extract($dev); 
1939                         $astman->database_put("DEVICE",$id."/dial",$dial);
1940                         $astman->database_put("DEVICE",$id."/type",$devicetype);
1941                         $astman->database_put("DEVICE",$id."/user",$user);             
1942                         $astman->database_put("DEVICE",$id."/default_user",$user);
1943                         if(trim($emergency_cid) != '') {
1944                                 $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
1945                         }
1946                         // If a user is selected, add this device to the user
1947                         if ($user != "none") {
1948                                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
1949                                         if (!empty($existingdevices)) {
1950                                                         $existingdevices .= "&";
1951                                         }
1952                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
1953                         }
1954                        
1955                         // create a voicemail symlink if needed
1956                         $thisUser = core_users_get($user);
1957                         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
1958                                 if(empty($thisUser['voicemail']))
1959                                         $vmcontext = "default";
1960                                 else
1961                                         $vmcontext = $thisUser['voicemail'];
1962                                 //voicemail symlink
1963                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
1964                                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
1965                         }
1966                 }
1967                 return true;
1968         } else {
1969                 return false;
1970         }
1971 }
1972
1973 // this function rebuilds the astdb based on users table contents
1974 // used on devices.php if action=resetall
1975 function core_users2astdb(){
1976         global $amp_conf;
1977         global $astman;
1978
1979         $sql = "SELECT * FROM users";
1980         $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1981        
1982         //add details to astdb
1983         if ($astman) {
1984                 foreach($userresults as $usr) {
1985                         extract($usr);
1986                         $astman->database_put("AMPUSER",$extension."/password",$password);
1987                         $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
1988                         $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
1989                         $astman->database_put("AMPUSER",$extension."/recording",$recording);
1990                         $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
1991                         $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
1992                         $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
1993                 }       
1994                 return true;
1995         } else {
1996                 return false;
1997         }
1998
1999 //      TODO: this was...       
2000 //      return $astman->disconnect();
2001 //      is "true" the correct value...?
2002 }
2003
2004 //add to sip table
2005 function core_devices_addsip($account) {
2006         global $db;
2007         global $currentFile;
2008
2009         foreach ($_REQUEST as $req=>$data) {
2010                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2011                         $keyword = substr($req, 8);
2012                         if ( $keyword == 'dial' && $data == '' ) {
2013                                 $sipfields[] = array($account, $keyword, 'SIP/'.$account);
2014                         } elseif ($keyword == 'mailbox' && $data == '') {
2015                                 $sipfields[] = array($account,'mailbox',$account.'@device');
2016                         } else {
2017                                 $sipfields[] = array($account, $keyword, $data);
2018                         }
2019                 }
2020         }
2021        
2022         if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
2023                 $sipfields = array(
2024                         //array($account,'account',$account),
2025                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
2026                         array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
2027                         array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
2028                         array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
2029                         array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
2030                         array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
2031                         array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
2032                         array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
2033                         array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
2034                         array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
2035                         array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
2036                         array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
2037                         array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
2038                         array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
2039                         array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
2040                         array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
2041                         //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
2042                         //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
2043                         //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
2044                 );
2045         }
2046
2047         // Very bad
2048         $sipfields[] = array($account,'account',$account);     
2049         $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2050        
2051         // Where is this in the interface ??????
2052         $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2053         $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2054
2055         $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
2056         $result = $db->executeMultiple($compiled,$sipfields);
2057         if(DB::IsError($result)) {
2058                 die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table');   
2059         }
2060 }
2061
2062 function core_devices_delsip($account) {
2063         global $db;
2064         global $currentFile;
2065        
2066         $sql = "DELETE FROM sip WHERE id = '$account'";
2067         $result = $db->query($sql);
2068        
2069         if(DB::IsError($result)) {
2070                 die_freepbx($result->getMessage().$sql);
2071         }
2072 }
2073
2074 function core_devices_getsip($account) {
2075         global $db;
2076         $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
2077         $results = $db->getAssoc($sql);
2078         if(DB::IsError($results)) {
2079                 $results = null;
2080         }
2081        
2082         return $results;
2083 }
2084
2085 //add to iax table
2086 function core_devices_addiax2($account) {
2087         global $db;
2088         global $currentFile;
2089        
2090         foreach ($_REQUEST as $req=>$data) {
2091                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2092                         $keyword = substr($req, 8);
2093                         if ( $keyword == 'dial' && $data == '' ) {
2094                                 $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
2095                         } elseif ($keyword == 'mailbox' && $data == '') {
2096                                 $iaxfields[] = array($account,'mailbox',$account.'@device');
2097                         } else {
2098                                 $iaxfields[] = array($account, $keyword, $data);
2099                         }
2100                 }
2101         }
2102        
2103         if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
2104                 $iaxfields = array(
2105                         //array($account,'account',$account),
2106                         array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
2107                         array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
2108                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
2109                         array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
2110                         array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
2111                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
2112                         array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
2113                         array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
2114                         array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
2115                         array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
2116                         array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
2117                         array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
2118                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
2119                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
2120                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
2121                 );
2122         }
2123
2124         // Very bad
2125         $iaxfields[] = array($account,'account',$account);     
2126         $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2127         // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
2128         // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
2129         // callerid as a variable which gets picked up in macro-callerid.
2130         // Ref - http://bugs.digium.com/view.php?id=456
2131         $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
2132        
2133         // Where is this in the interface ??????
2134         $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2135         $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2136        
2137         $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
2138         $result = $db->executeMultiple($compiled,$iaxfields);
2139         if(DB::IsError($result)) {
2140                 die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
2141         }
2142 }
2143
2144 function core_devices_deliax2($account) {
2145         global $db;
2146         global $currentFile;
2147        
2148         $sql = "DELETE FROM iax WHERE id = '$account'";
2149         $result = $db->query($sql);
2150        
2151         if(DB::IsError($result)) {
2152                 die_freepbx($result->getMessage().$sql);
2153         }
2154 }
2155
2156 function core_devices_getiax2($account) {
2157         global $db;
2158         $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
2159         $results = $db->getAssoc($sql);
2160         if(DB::IsError($results)) {
2161                 $results = null;
2162         }
2163        
2164         return $results;
2165 }
2166
2167 function core_devices_addzap($account) {
2168         global $db;
2169         global $currentFile;
2170        
2171         foreach ($_REQUEST as $req=>$data) {
2172                 if ( substr($req, 0, 8) == 'devinfo_' ) {
2173                         $keyword = substr($req, 8);
2174                         if ( $keyword == 'dial' && $data == '' ) {
2175                                 $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
2176                                 $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
2177                         } elseif ($keyword == 'mailbox' && $data == '') {
2178                                 $zapfields[] = array($account,'mailbox',$account.'@device');
2179                         } else {
2180                                 $zapfields[] = array($account, $keyword, $data);
2181                         }
2182                 }
2183         }
2184        
2185         if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
2186                 $zapfields = array(
2187                         //array($account,'account',$account),
2188                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
2189                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
2190                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
2191                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
2192                         array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
2193                         array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
2194                         array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
2195                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),       
2196                         array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
2197                         array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
2198                         array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
2199                         array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
2200                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),     
2201                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
2202                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
2203                         array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
2204                 );
2205         }
2206
2207         // Very bad
2208         $zapfields[] = array($account,'account',$account);     
2209         $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
2210        
2211         // Where is this in the interface ??????
2212         $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
2213         $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
2214
2215         $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
2216         $result = $db->executeMultiple($compiled,$zapfields);
2217         if(DB::IsError($result)) {
2218                 die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
2219         }
2220 }
2221
2222 function core_devices_delzap($account) {
2223         global $db;
2224         global $currentFile;
2225        
2226         $sql = "DELETE FROM zap WHERE id = '$account'";
2227         $result = $db->query($sql);
2228         if(DB::IsError($result)) {
2229                 die_freepbx($result->getMessage().$sql);
2230         }
2231 }
2232
2233 function core_devices_getzap($account) {
2234         global $db;
2235         $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
2236         $results = $db->getAssoc($sql);
2237         if(DB::IsError($results)) {
2238                 $results = null;
2239         }
2240         return $results;
2241 }
2242 /* end page.devices.php functions */
2243
2244
2245
2246
2247 function core_hint_get($account){
2248         global $astman;
2249
2250         // We should always check the AMPUSER in case they logged into a device
2251         // but we will fall back to the old methond if $astman not open although
2252         // I'm pretty sure everything else will puke anyhow if not running
2253         //
2254         if ($astman) {
2255                 $device=$astman->database_get("AMPUSER",$account."/device");
2256                 $device_arr = explode('&',$device);
2257                 $sql = "SELECT dial from devices where id in ('".implode("','",$device_arr)."')";
2258         } else {
2259                 $sql = "SELECT dial from devices where user = '{$account}'";
2260         }
2261         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2262        
2263         //create an array of strings
2264         if (is_array($results)){
2265                 foreach ($results as $result) {
2266                         $dial[] = $result['dial'];
2267                 }
2268         }
2269        
2270         //create a string with & delimiter
2271         if (isset($dial) && is_array($dial)){
2272                 $hint = implode($dial,"&");
2273         } else {
2274                 if (isset($results[0]['dial'])) {
2275                         $hint = $results[0]['dial'];
2276                 } else {
2277                         $hint = null;
2278                 }
2279         }
2280        
2281         return $hint;
2282 }
2283
2284
2285
2286 /* begin page.users.php functions */
2287
2288 // get the existing extensions
2289 // the returned arrays contain [0]:extension [1]:name
2290 function core_users_list() {
2291         $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
2292
2293         //only allow extensions that are within administrator's allowed range
2294         foreach($results as $result){
2295                 if (checkRange($result[0])){
2296                         $extens[] = array($result[0],$result[1],$result[2]);
2297                 }
2298         }
2299        
2300         if (isset($extens)) {
2301                 sort($extens);
2302                 return $extens;
2303         } else {
2304                 return null;
2305         }
2306 }
2307
2308 function core_check_extensions($exten=true) {
2309         global $amp_conf;
2310
2311         $extenlist = array();
2312         if (is_array($exten) && empty($exten)) {
2313                 return $extenlist;
2314         }
2315         $sql = "SELECT extension, name FROM users ";
2316         if (is_array($exten)) {
2317                 $sql .= "WHERE extension in ('".implode("','",$exten)."')";
2318         }
2319         $sql .= " ORDER BY extension";
2320         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2321
2322         foreach ($results as $result) {
2323                 $thisexten = $result['extension'];
2324                 $extenlist[$thisexten]['description'] = _("User Extension: ").$result['name'];
2325                 $extenlist[$thisexten]['status'] = 'INUSE';
2326                 $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
2327                 $extenlist[$thisexten]['edit_url'] = "config.php?type=setup&display=$display&extdisplay=".urlencode($thisexten)."&skip=0";
2328         }
2329         return $extenlist;
2330 }
2331
2332 function core_check_destinations($dest=true) {
2333         global $active_modules;
2334
2335         $destlist = array();
2336         if (is_array($dest) && empty($dest)) {
2337                 return $destlist;
2338         }
2339         $sql = "SELECT extension, cidnum, description, destination FROM incoming ";
2340         if ($dest !== true) {
2341                 $sql .= "WHERE destination in ('".implode("','",$dest)."')";
2342         }
2343         $sql .= "ORDER BY extension, cidnum";
2344         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2345
2346         //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
2347
2348         foreach ($results as $result) {
2349                 $thisdest = $result['destination'];
2350                 $thisid   = $result['extension'].'/'.$result['cidnum'];
2351                 $destlist[] = array(
2352                         'dest' => $thisdest,
2353                         'description' => 'Inbound Route: '.$result['description'].' ('.$thisid.')',
2354                         'edit_url' => 'config.php?display=did&extdisplay='.urlencode($thisid),
2355                 );
2356         }
2357         return $destlist;
2358 }
2359
2360 function core_sipname_check($sipname, $extension) {
2361         global $db;
2362         if (!isset($sipname) || trim($sipname)=='')
2363                 return true;
2364
2365         $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
2366         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2367         if(DB::IsError($results)) {
2368         die_freepbx($results->getMessage().$sql);
2369         }
2370        
2371         if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
2372                 return false;
2373         else
2374                 return true;
2375 }
2376
2377 function core_users_add($vars, $editmode=false) {
2378         extract($vars);
2379        
2380         global $db;
2381         global $amp_conf;
2382         global $astman;
2383
2384         $thisexten = isset($thisexten) ? $thisexten : '';
2385
2386         if (trim($extension) == '' ) {
2387                 echo "<script>javascript:alert('"._("You must put in an extension (or user) number")."');</script>";
2388                 return false;
2389         }
2390
2391         //ensure this id is not already in use
2392         $extens = core_users_list();
2393         if(is_array($extens)) {
2394                 foreach($extens as $exten) {
2395                         if ($exten[0]===$extension) {
2396                                 echo "<script>javascript:alert('".sprintf(_("This user/extension %s is already in use"),$extension)."');</script>";
2397                                 return false;
2398                         }
2399                 }
2400         }
2401
2402         // clean and check the did to make sure it is not being used by another extension or in did routing
2403         //
2404         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2405         if (trim($directdid) != "") {
2406                 $existing=core_did_get($directdid,"");
2407                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2408                 if (!empty($existing) || !empty($existing_directdid)) {
2409                         if (!empty($existing)) {
2410                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2411                         } else {
2412                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2413                         }
2414                         return false;
2415                 }
2416         }
2417
2418         $sipname = preg_replace("/\s/" ,"", trim($sipname));
2419         if (! core_sipname_check($sipname, $extension)) {
2420                 echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
2421                 return false;
2422         }
2423        
2424         //build the recording variable
2425         $recording = "out=".$record_out."|in=".$record_in;
2426        
2427         //escape quotes and any other bad chars:
2428         if(!get_magic_quotes_gpc()) {
2429                 $outboundcid = addslashes($outboundcid);
2430                 $name = addslashes($name);
2431         }
2432
2433         //if voicemail is enabled, set the box@context to use
2434         //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
2435         if ( function_exists('voicemail_mailbox_get') ) {
2436                 $vmbox = voicemail_mailbox_get($extension);
2437                 if ( $vmbox == null ) {
2438                         $voicemail = "novm";
2439                         $vmx_state = "false";
2440                 } else {
2441                         $voicemail = $vmbox['vmcontext'];
2442                 }
2443         }
2444
2445         // MODIFICATION: (PL)
2446         // Added for directdid and didalert l for Alert Info distinctive ring)
2447         //
2448         // cleanup any non dial pattern characters prior to inserting into the database
2449         // then add directdid to the insert command.
2450         //
2451         // Clean replace any <> with () in display name - should have javascript stopping this but ...
2452         //
2453         $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
2454        
2455         //insert into users table
2456         $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
2457         $sql.= "$extension\", \"";
2458         $sql.= isset($password)?$password:'';
2459         $sql.= "\", \"";
2460         $sql.= isset($name)?$name:'';
2461         $sql.= "\", \"";
2462         $sql.= isset($voicemail)?$voicemail:'default';
2463         $sql.= "\", \"";
2464         $sql.= isset($ringtimer)?$ringtimer:'';
2465         $sql.= "\", \"";
2466         $sql.= isset($noanswer)?$noanswer:'';
2467         $sql.= "\", \"";
2468         $sql.= isset($recording)?$recording:'';
2469         $sql.= "\", \"";
2470         $sql.= isset($outboundcid)?$outboundcid:'';
2471         $sql.= "\", \"";
2472         $sql.= isset($directdid)?$directdid:'';
2473         $sql.= "\", \"";
2474         $sql.= isset($didalert)?$didalert:'';
2475
2476         $sql.= "\", \"";
2477         $sql.= isset($faxexten)?$faxexten:'';
2478         $sql.= "\", \"";
2479         $sql.= isset($faxemail)?$faxemail:'';
2480         $sql.= "\", \"";
2481         $sql.= isset($answer)?$answer:'';
2482         $sql.= "\", \"";
2483         $sql.= isset($wait)?$wait:'';
2484         $sql.= "\", \"";
2485         $sql.= isset($privacyman)?$privacyman:'';
2486         $sql.= "\", \"";
2487         $sql.= isset($mohclass)?$mohclass:'';
2488         $sql.= "\", \"";
2489         $sql.= isset($sipname)?$sipname:'';
2490         $sql.= "\")";
2491         sql($sql);
2492
2493         //write to astdb
2494         if ($astman) {
2495                 $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
2496                 $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
2497                 $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
2498                 $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
2499                 $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
2500                 $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
2501                 $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
2502                 $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
2503                 $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
2504                 if (!$editmode) {
2505                         $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
2506                 }
2507
2508                 if (trim($callwaiting) == 'enabled') {
2509                         $astman->database_put("CW",$extension,"\"ENABLED\"");
2510                 } else if (trim($callwaiting) == 'disabled') {
2511                         $astman->database_del("CW",$extension);
2512                 } else {
2513                         echo "ERROR: this state should not exist<br>";
2514                 }
2515
2516                 if ($vmx_state && $voicemail != "novm") {
2517
2518                         $unavail_mode="enabled";
2519                         $busy_mode="disabled";
2520                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2521
2522                         if (trim($vmx_state) == 'blocked') {
2523
2524                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
2525                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
2526
2527                         } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
2528
2529                                 $repeat="1";
2530                                 $timeout="2";
2531                                 $vmxopts_timeout="";
2532                                 $loops="1";
2533
2534                                 $mode="unavail";
2535                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
2536                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2537
2538                                 $mode="busy";
2539                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
2540                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
2541                                
2542                         }
2543                 } else {
2544                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2545                         if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
2546                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
2547                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
2548                         }
2549                 }
2550         } else {
2551                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2552         }
2553         return true;
2554 }
2555
2556 function core_users_get($extension){
2557         global $db;
2558         global $amp_conf;
2559         global $astman;
2560         //get all the variables for the meetme
2561         $sql = "SELECT * FROM users WHERE extension = '$extension'";
2562         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2563         if(DB::IsError($results)) {
2564                 die_freepbx($results->getMessage().$sql);
2565         }
2566         if (empty($results)) {
2567                 return $results;
2568         }
2569        
2570         //explode recording vars
2571         $recording = explode("|",$results['recording']);
2572         if (isset($recording[1])) {
2573                 $recout = substr($recording[0],4);
2574                 $recin = substr($recording[1],3);
2575                 $results['record_in']=$recin;
2576                 $results['record_out']=$recout;
2577         } else {
2578                 $results['record_in']='Adhoc';
2579                 $results['record_out']='Adhoc';
2580         }
2581         if ($astman) {
2582                 $cw = $astman->database_get("CW",$extension);
2583                 $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
2584                 $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
2585                 $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
2586                 $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
2587         } else {
2588                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2589         }
2590
2591         return $results;
2592 }
2593
2594 function core_users_del($extension, $editmode=false){
2595         global $db;
2596         global $amp_conf;
2597         global $astman;
2598        
2599         //delete from devices table
2600         $sql="DELETE FROM users WHERE extension = \"$extension\"";
2601         $results = $db->query($sql);
2602         if(DB::IsError($results)) {
2603                 die_freepbx($results->getMessage().$sql);
2604         }
2605
2606         //delete details to astdb
2607         if ($astman && !$editmode) {
2608                 $astman->database_del("AMPUSER",$extension."/password");
2609                 $astman->database_del("AMPUSER",$extension."/ringtimer");
2610                 $astman->database_del("AMPUSER",$extension."/noanswer");
2611                 $astman->database_del("AMPUSER",$extension."/recording");
2612                 $astman->database_del("AMPUSER",$extension."/outboundcid");
2613                 $astman->database_del("AMPUSER",$extension."/cidname");
2614                 $astman->database_del("AMPUSER",$extension."/cidnum");
2615                 $astman->database_del("AMPUSER",$extension."/voicemail");
2616                 $astman->database_del("AMPUSER",$extension."/device");
2617         }
2618 }
2619
2620 function core_users_directdid_get($directdid=""){
2621         if (empty($directdid)) {
2622                 return array();
2623         } else {
2624                 $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
2625                 return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2626         }
2627 }
2628
2629 function core_users_cleanastdb($extension) {
2630         // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
2631         // call forwarding, call waiting settings could hang around and bite someone if they
2632         // recycle an extension. Is called from page.xtns and page.users.
2633         global $amp_conf;
2634         global $astman;
2635
2636         if ($astman) {
2637                 $astman->database_del("CW",$extension);
2638                 $astman->database_del("CF",$extension);
2639                 $astman->database_del("CFB",$extension);
2640                 $astman->database_del("CFU",$extension);
2641                 $astman->database_deltree("AMPUSER/".$extension."/vmx");
2642
2643         } else {
2644                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2645         }
2646 }
2647
2648 function core_users_edit($extension,$vars){
2649         global $db;
2650         global $amp_conf;
2651         global $astman;
2652        
2653         //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
2654         if ($astman) {
2655                 $ud = $astman->database_get("AMPUSER",$extension."/device");
2656                 $current_vmcontext = $astman->database_get("AMPUSER",$extension."/voicemail");
2657                 $new_vmcontext = isset($vars['vmcontext']) ? $vars['vmcontext'] : 'novm';
2658                 $vars['device'] = $ud;
2659         } else {
2660                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
2661         }
2662        
2663         $directdid=$vars['directdid'];
2664         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
2665         // clean and check the did to make sure it is not being used by another extension or in did routing
2666         //
2667         if (trim($directdid) != "") {
2668                 $existing=core_did_get($directdid,"");
2669                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
2670                 if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
2671                         if (!empty($existing)) {
2672                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
2673                         } else {
2674                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
2675                         }
2676                         return false;
2677                 }
2678         }
2679
2680         //delete and re-add
2681         if (core_sipname_check($vars['sipname'],$extension)) {
2682                 core_users_del($extension, true);
2683                 core_users_add($vars, true);
2684
2685                 // If the vmcontext has changed, we need to change all the links. In extension mode, the link
2686                 // to the current fixed device will get changed, but none others will
2687                 //
2688                 if ($current_vmcontext != $new_vmcontext) {
2689                         $user_devices = explode('&',$ud);
2690                         foreach ($user_devices as $user_device) {
2691                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$user_device);
2692                                 if ($new_context != 'novm') {
2693                                         exec("/bin/ln -s /var/spool/asterisk/voicemail/".$new_vmcontext."/".$extension."/ /var/spool/asterisk/voicemail/device/".$user_device);
2694                                 }
2695                         }
2696                 }
2697         }
2698         return true;
2699 }
2700
2701 function core_directdid_list(){
2702         $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
2703         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2704 }
2705
2706
2707
2708 function core_zapchandids_add($description, $channel, $did) {
2709         global $db;
2710
2711
2712         if (!ctype_digit(trim($channel)) || trim($channel) == '') {
2713                 echo "<script>javascript:alert('"._('Invalid Channel Number, must be numeric and not blank')."')</script>";
2714                 return false;
2715         }
2716         if (trim($did) == '') {
2717                 echo "<script>javascript:alert('"._('Invalid DID, must be a non-blank DID')."')</script>";
2718                 return false;
2719         }
2720
2721         $description = q($description);
2722         $channel     = q($channel);
2723         $did         = q($did);
2724
2725         $sql = "INSERT INTO zapchandids (channel, description, did) VALUES ($channel, $description, $did)";
2726         $results = $db->query($sql);
2727         if (DB::IsError($results)) {
2728                 if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) {
2729                         echo "<script>javascript:alert('"._("Error Duplicate Channel Entry")."')</script>";
2730                         return false;
2731                 } else {
2732                         die_freepbx($results->getMessage()."<br><br>".$sql);
2733                 }
2734         }
2735         return true;
2736 }
2737
2738 function core_zapchandids_edit($description, $channel, $did) {
2739         global $db;
2740
2741         $description = q($description);
2742         $channel     = q($channel);
2743         $did         = q($did);
2744
2745         $sql = "UPDATE zapchandids SET description = $description, did = $did WHERE channel = $channel";
2746         $results = $db->query($sql);
2747         if (DB::IsError($results)) {
2748                 die_freepbx($results->getMessage()."<br><br>".$sql);
2749         }
2750         return true;
2751 }
2752
2753 function core_zapchandids_delete($channel) {
2754         global $db;
2755
2756         $channel     = q($channel);
2757
2758         $sql = "DELETE FROM zapchandids WHERE channel = $channel";
2759         $results = $db->query($sql);
2760         if (DB::IsError($results)) {
2761                 die_freepbx($results->getMessage()."<br><br>".$sql);
2762         }
2763         return true;
2764 }
2765
2766 function core_zapchandids_list() {
2767         global $db;
2768
2769         $sql = "SELECT * FROM zapchandids ORDER BY channel";
2770         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
2771 }
2772
2773 function core_zapchandids_get($channel) {
2774         global $db;
2775
2776         $channel     = q($channel);
2777
2778         $sql = "SELECT * FROM zapchandids WHERE channel = $channel";
2779         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
2780 }
2781
2782 /* end page.users.php functions */
2783
2784
2785
2786
2787
2788 /* begin page.trunks.php functions */
2789
2790 // we're adding ,don't require a $trunknum
2791 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2792         global $db;
2793        
2794         // find the next available ID
2795         $trunknum = 1;
2796
2797         // This is pretty ugle, will fix when we redo trunks and routes with proper uniqueids.
2798         // get the list, sort them, then look for a hole and use it, or overflow to the end if
2799         // not and use that
2800         //
2801         $trunk_hash = array();
2802         foreach(core_trunks_list() as $trunk) {
2803                 $trunknum = ltrim($trunk[0],"OUT_");
2804                 $trunk_hash[] = $trunknum;
2805         }
2806         sort($trunk_hash);
2807         $trunknum = 1;
2808         foreach ($trunk_hash as $trunk_id) {
2809                 if ($trunk_id != $trunknum) {
2810                         break;
2811                 }
2812                 $trunknum++;
2813         }
2814        
2815         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2816        
2817         return $trunknum;
2818 }
2819
2820 function core_trunks_del($trunknum, $tech = null) {
2821         global $db;
2822        
2823         if ($tech === null) { // in EditTrunk, we get this info anyways
2824                 $tech = core_trunks_getTrunkTech($trunknum);
2825         }
2826
2827         //delete from globals table
2828         sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
2829        
2830         //write outids
2831         core_trunks_writeoutids();
2832
2833         // conditionally, delete from iax or sip
2834         switch (strtolower($tech)) {
2835                 case "iax":
2836                 case "iax2":
2837                         sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2838                 break;
2839                 case "sip":
2840                         sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
2841                 break;
2842         }
2843 }
2844
2845 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2846         //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2847         $tech = core_trunks_getTrunkTech($trunknum);
2848         core_trunks_del($trunknum, $tech);
2849         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
2850 }
2851
2852 // just used internally by addTrunk() and editTrunk()
2853 //obsolete
2854 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
2855         global $db;
2856        
2857         if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
2858        
2859         //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
2860        
2861         // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
2862         $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
2863         $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
2864        
2865         $glofields = array(
2866                         array('OUT_'.$trunknum, $outval),
2867                         array('OUTPREFIX_'.$trunknum, $dialoutprefix),
2868                         array('OUTMAXCHANS_'.$trunknum, $maxchans),
2869                         array('OUTCID_'.$trunknum, $outcid),
2870                         array('OUTKEEPCID_'.$trunknum, $keepcid),
2871                         array('OUTFAIL_'.$trunknum, $failtrunk),
2872                         array('OUTDISABLE_'.$trunknum, $disabletrunk),
2873                         );
2874                        
2875         unset($techtemp);
2876        
2877         $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
2878         $result = $db->executeMultiple($compiled,$glofields);
2879         if(DB::IsError($result)) {
2880                 die_freepbx($result->getMe