Ticket #2695: functions.inc.php

File functions.inc.php, 221.0 kB (added by robmac, 4 years ago)
Line 
1 <?php
2
3 class core_conf {
4   var $_sip_general    = array();
5   var $_iax_general    = array();
6   var $_h323_general    = array();
7   var $_mgcp_general    = array();
8   var $_skinny_general    = array();
9   var $_featuregeneral = array();
10   var $_featuremap     = array();
11   var $_applicationmap = array();
12   // return an array of filenames to write
13   function get_filename() {
14     $files = array(
15       'zapata_additional.conf',
16       'sip_additional.conf',
17       'sip_registrations.conf',
18       'sip_general_additional.conf',
19       'iax_additional.conf',
20       'iax_registrations.conf',
21       'iax_general_additional.conf',
22       'ooh323_additional.conf',
23       'ooh323_registrations.conf',
24       'ooh323_general_additional.conf',
25       'mgcp_additional.conf',
26       'mgcp_registrations.conf',
27       'mgcp_general_additional.conf',
28       'skinny_additional.conf',
29       'skinny_registrations.conf',
30       'skinny_general_additional.conf',
31       'features_general_additional.conf',
32       'features_applicationmap_additional.conf',
33       'features_featuremap_additional.conf',
34       );
35     return $files;
36   }
37  
38   // return the output that goes in each of the files
39   function generateConf($file) {
40     global $version;
41
42     switch ($file) {
43       case 'sip_general_additional.conf':
44         return $this->generate_sip_general_additional($version);
45         break;
46       case 'sip_additional.conf':
47         return $this->generate_sip_additional($version);
48         break;
49       case 'sip_registrations.conf':
50         return $this->generate_sip_registrations($version);
51         break;
52       case 'iax_general_additional.conf':
53         return $this->generate_iax_general_additional($version);
54         break;
55       case 'iax_additional.conf':
56         return $this->generate_iax_additional($version);
57         break;
58       case 'iax_registrations.conf':
59         return $this->generate_iax_registrations($version);
60         break;
61       case 'ooh323_general_additional.conf':
62         return $this->generate_h323_general_additional($version);
63         break;
64       case 'ooh323_additional.conf':
65         return $this->generate_h323_additional($version);
66         break;
67       case 'ooh323_registrations.conf':
68         return $this->generate_h323_registrations($version);
69         break;
70       case 'mgcp_general_additional.conf':
71         return $this->generate_mgcp_general_additional($version);
72         break;
73       case 'mgcp_additional.conf':
74         return $this->generate_mgcp_additional($version);
75         break;
76       case 'mgcp_registrations.conf':
77         return $this->generate_mgcp_registrations($version);
78         break;
79       case 'skinny_general_additional.conf':
80         return $this->generate_skinny_general_additional($version);
81         break;
82       case 'skinny_additional.conf':
83         return $this->generate_skinny_additional($version);
84         break;
85       case 'skinny_registrations.conf':
86         return $this->generate_skinny_registrations($version);
87         break;
88       case 'zapata_additional.conf':
89         return $this->generate_zapata_additional($version);
90         break;
91       case 'features_general_additional.conf':
92         return $this->generate_featuregeneral_additional($version);
93         break;
94       case 'features_applicationmap_additional.conf':
95         return $this->generate_applicationmap_additional($version);
96         break;
97       case 'features_featuremap_additional.conf':
98         return $this->generate_featuremap_additional($version);
99         break;
100     }
101   }
102
103   function addSipGeneral($key, $value) {
104     $this->_sip_general[] = array('key' => $key, 'value' => $value);
105   }
106
107   function generate_sip_general_additional($ast_version) {
108     $output = '';
109
110     if (isset($this->_sip_general) && is_array($this->_sip_general)) {
111       foreach ($this->_sip_general as $values) {
112         $output .= $values['key']."=".$values['value']."\n";
113       }
114     }
115     return $output;
116   }
117
118   function addIaxGeneral($key, $value) {
119     $this->_iax_general[] = array('key' => $key, 'value' => $value);
120   }
121
122   function generate_iax_general_additional($ast_version) {
123     $output = '';
124
125     if (isset($this->_iax_general) && is_array($this->_iax_general)) {
126       foreach ($this->_iax_general as $values) {
127         $output .= $values['key']."=".$values['value']."\n";
128       }
129     }
130     return $output;
131   }
132
133   function addH323General($key, $value) {
134     $this->_h323_general[] = array('key' => $key, 'value' => $value);
135   }
136
137   function generate_h323_general_additional($ast_version) {
138     $output = '';
139
140     if (isset($this->_h323_general) && is_array($this->_h323_general)) {
141       foreach ($this->_h323_general as $values) {
142         $output .= $values['key']."=".$values['value']."\n";
143       }
144     }
145     return $output;
146   }
147
148   function addMgcpGeneral($key, $value) {
149     $this->_mgcp_general[] = array('key' => $key, 'value' => $value);
150   }
151
152   function generate_mgcp_general_additional($ast_version) {
153     $output = '';
154
155     if (isset($this->_mgcp_general) && is_array($this->_mgcp_general)) {
156       foreach ($this->_mgcp_general as $values) {
157         $output .= $values['key']."=".$values['value']."\n";
158       }
159     }
160     return $output;
161   }
162
163   function addSkinnyGeneral($key, $value) {
164     $this->_skinny_general[] = array('key' => $key, 'value' => $value);
165   }
166
167   function generate_skinny_general_additional($ast_version) {
168     $output = '';
169
170     if (isset($this->_skinny_general) && is_array($this->_skinny_general)) {
171       foreach ($this->_skinny_general as $values) {
172         $output .= $values['key']."=".$values['value']."\n";
173       }
174     }
175     return $output;
176   }
177
178   function addFeatureGeneral($key, $value) {
179     $this->_featuregeneral[] = array('key' => $key, 'value' => $value);
180   }
181
182   function generate_featuregeneral_additional($ast_version) {
183     $output = '';
184
185     if (isset($this->_featuregeneral) && is_array($this->_featuregeneral)) {
186       foreach ($this->_featuregeneral as $values) {
187         $output .= $values['key']."=".$values['value']."\n";
188       }
189     }
190     return $output;
191   }
192
193   function addFeatureMap($key, $value) {
194     $this->_featuremap[] = array('key' => $key, 'value' => $value);
195   }
196
197   function generate_featuremap_additional($ast_version) {
198     $output = '';
199
200     if (isset($this->_featuremap) && is_array($this->_featuremap)) {
201       foreach ($this->_featuremap as $values) {
202         $output .= $values['key']."=".$values['value']."\n";
203       }
204     }
205     return $output;
206   }
207
208   function addApplicationMap($key, $value) {
209     $this->_applicationmap[] = array('key' => $key, 'value' => $value);
210   }
211
212   function generate_applicationmap_additional($ast_version) {
213     $output = '';
214
215     if (isset($this->_applicationmap) && is_array($this->_applicationmap)) {
216       foreach ($this->_applicationmap as $values) {
217         $output .= $values['key']."=".$values['value']."\n";
218       }
219     }
220     return $output;
221   }
222
223   function generate_sip_additional($ast_version) {
224     global $db;
225
226     $table_name = "sip";
227     $additional = "";
228     $output = "";
229
230     // Asterisk 1.4 requires call-limit be set for hints to work properly
231     //
232     if (version_compare($ast_version, "1.4", "ge")) {
233       $call_limit = "call-limit=50\n";
234       $ver12 = false;
235     } else {
236       $call_limit = "";
237       $ver12 = true;
238     }
239
240     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
241     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
242     if(DB::IsError($results)) {
243       die($results->getMessage());
244     }
245     foreach ($results as $result) {
246       if ($ver12) {
247         $additional .= $result['keyword']."=".$result['data']."\n";
248       } else {
249         $option = $result['data'];
250         switch ($result['keyword']) {
251           case 'allow':
252           case 'disallow':
253             if ($option != '')
254               $additional .= $result['keyword']."=$option\n";
255             break;
256           default:
257             $additional .= $result['keyword']."=$option\n";
258         }
259       }
260     }
261
262     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
263     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
264     if(DB::IsError($results)) {
265       die($results->getMessage());
266     }
267
268     foreach ($results as $result) {
269       $account = $result['data'];
270       $id = $result['id'];
271       $output .= "[$account]\n";
272  
273       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
274       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
275       if(DB::IsError($results2)) {
276         die($results2->getMessage());
277       }
278       foreach ($results2 as $result2) {
279         $options = explode("&", $result2['data']);
280         if ($ver12) {
281           foreach ($options as $option) {
282             $output .= $result2['keyword']."=$option\n";
283           }
284         } else {
285           foreach ($options as $option) {
286             switch ($result2['keyword']) {
287               case 'allow':
288               case 'disallow':
289                 if ($option != '')
290                   $output .= $result2['keyword']."=$option\n";
291                 break;
292               default:
293                 $output .= $result2['keyword']."=$option\n";
294             }
295           }
296         }
297       }
298       if ($call_limit && (substr($id,0,4) != "9999" | $id < 99990)) {
299
300         $output .= $call_limit;
301       }
302       $output .= $additional."\n";
303     }
304     return $output;
305   }
306
307   function generate_sip_registrations($ast_version) {
308     global $db;
309
310     $table_name = "sip";
311     $output = "";
312
313     // items with id like 9999999% get put in registrations file
314     //
315     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
316     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
317     if(DB::IsError($results)) {
318       die($results->getMessage());
319     }
320
321     foreach ($results as $result) {
322       $output .= $result['keyword']."=".$result['data']."\n";
323     }
324
325     return $output;
326   }
327
328   function generate_iax_additional($ast_version) {
329     global $db;
330
331     $table_name = "iax";
332     $additional = "";
333     $output = "";
334
335     $ver12 = version_compare($ast_version, '1.4', 'lt');
336
337     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
338     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
339     if(DB::IsError($results)) {
340       die($results->getMessage());
341     }
342     foreach ($results as $result) {
343       if ($ver12) {
344         $additional .= $result['keyword']."=".$result['data']."\n";
345       } else {
346         $option = $result['data'];
347         switch ($result['keyword']) {
348           case 'notransfer':
349             if (strtolower($option) == 'yes') {
350               $additional .= "transfer=no\n";
351             } else if (strtolower($option) == 'no') {
352               $additional .= "transfer=yes\n";
353             } else if (strtolower($option) == 'mediaonly') {
354               $additional .= "transfer=mediaonly\n";
355             } else {
356               $additional .= $result['keyword']."=$option\n";
357             }
358             break;
359           case 'allow':
360           case 'disallow':
361             if ($option != '')
362               $additional .= $result['keyword']."=$option\n";
363             break;
364           default:
365             $additional .= $result['keyword']."=$option\n";
366         }
367       }
368     }
369
370     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
371     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
372     if(DB::IsError($results)) {
373       die($results->getMessage());
374     }
375    
376     foreach ($results as $result) {
377       $account = $result['data'];
378       $id = $result['id'];
379       $output .= "[$account]\n";
380  
381       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
382       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
383       if(DB::IsError($results2)) {
384         die($results2->getMessage());
385       }
386       foreach ($results2 as $result2) {
387         $options = explode("&", $result2['data']);
388         if ($ver12) {
389           foreach ($options as $option) {
390             $output .= $result2['keyword']."=$option\n";
391           }
392         } else {
393           foreach ($options as $option) {
394             switch ($result2['keyword']) {
395               case 'notransfer':
396                 if (strtolower($option) == 'yes') {
397                   $output .= "transfer=no\n";
398                 } else if (strtolower($option) == 'no') {
399                   $output .= "transfer=yes\n";
400                 } else if (strtolower($option) == 'mediaonly') {
401                   $output .= "transfer=mediaonly\n";
402                 } else {
403                   $output .= $result2['keyword']."=$option\n";
404                 }
405                 break;
406               case 'allow':
407               case 'disallow':
408                 if ($option != '')
409                   $output .= $result2['keyword']."=$option\n";
410                 break;
411               default:
412                 $output .= $result2['keyword']."=$option\n";
413             }
414           }
415         }
416       }
417       $output .= $additional."\n";
418     }
419     return $output;
420   }
421
422   function generate_iax_registrations($ast_version) {
423     global $db;
424
425     $table_name = "iax";
426     $output = "";
427
428     // items with id like 9999999% get put in the registration file
429     //
430     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
431     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
432     if(DB::IsError($results)) {
433       die($results->getMessage());
434     }
435
436     foreach ($results as $result) {
437       $output .= $result['keyword']."=".$result['data']."\n";
438     }
439
440     return $output;
441   }
442
443   function generate_h323_additional($ast_version) {
444     global $db;
445
446     $table_name = "h323";
447     $additional = "";
448     $output = "";
449
450     $ver12 = version_compare($ast_version, '1.4', 'lt');
451
452     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
453     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
454     if(DB::IsError($results)) {
455       die($results->getMessage());
456     }
457     foreach ($results as $result) {
458       if ($ver12) {
459         $additional .= $result['keyword']."=".$result['data']."\n";
460       } else {
461         $option = $result['data'];
462         switch ($result['keyword']) {
463           case 'notransfer':
464             if (strtolower($option) == 'yes') {
465               $additional .= "transfer=no\n";
466             } else if (strtolower($option) == 'no') {
467               $additional .= "transfer=yes\n";
468             } else if (strtolower($option) == 'mediaonly') {
469               $additional .= "transfer=mediaonly\n";
470             } else {
471               $additional .= $result['keyword']."=$option\n";
472             }
473             break;
474           case 'allow':
475           case 'disallow':
476             if ($option != '')
477               $additional .= $result['keyword']."=$option\n";
478             break;
479           default:
480             $additional .= $result['keyword']."=$option\n";
481         }
482       }
483     }
484
485     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
486     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
487     if(DB::IsError($results)) {
488       die($results->getMessage());
489     }
490    
491     foreach ($results as $result) {
492       $account = $result['data'];
493       $id = $result['id'];
494       $output .= "[$account]\n";
495  
496       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
497       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
498       if(DB::IsError($results2)) {
499         die($results2->getMessage());
500       }
501       foreach ($results2 as $result2) {
502         $options = explode("&", $result2['data']);
503         if ($ver12) {
504           foreach ($options as $option) {
505             $output .= $result2['keyword']."=$option\n";
506           }
507         } else {
508           foreach ($options as $option) {
509             switch ($result2['keyword']) {
510               case 'notransfer':
511                 if (strtolower($option) == 'yes') {
512                   $output .= "transfer=no\n";
513                 } else if (strtolower($option) == 'no') {
514                   $output .= "transfer=yes\n";
515                 } else if (strtolower($option) == 'mediaonly') {
516                   $output .= "transfer=mediaonly\n";
517                 } else {
518                   $output .= $result2['keyword']."=$option\n";
519                 }
520                 break;
521               case 'allow':
522               case 'disallow':
523                 if ($option != '')
524                   $output .= $result2['keyword']."=$option\n";
525                 break;
526               default:
527                 $output .= $result2['keyword']."=$option\n";
528             }
529           }
530         }
531       }
532       $output .= $additional."\n";
533     }
534     return $output;
535   }
536
537   function generate_h323_registrations($ast_version) {
538     global $db;
539
540     $table_name = "h323";
541     $output = "";
542
543     // items with id like 9999999% get put in the registration file
544     //
545     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
546     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
547     if(DB::IsError($results)) {
548       die($results->getMessage());
549     }
550
551     foreach ($results as $result) {
552       $output .= $result['keyword']."=".$result['data']."\n";
553     }
554
555     return $output;
556   }
557
558   function generate_mgcp_additional($ast_version) {
559     global $db;
560
561     $table_name = "mgcp";
562     $additional = "";
563     $output = "";
564
565     $ver12 = version_compare($ast_version, '1.4', 'lt');
566
567     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
568     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
569     if(DB::IsError($results)) {
570       die($results->getMessage());
571     }
572     foreach ($results as $result) {
573       if ($ver12) {
574         $additional .= $result['keyword']."=".$result['data']."\n";
575       } else {
576         $option = $result['data'];
577         switch ($result['keyword']) {
578           case 'notransfer':
579             if (strtolower($option) == 'yes') {
580               $additional .= "transfer=no\n";
581             } else if (strtolower($option) == 'no') {
582               $additional .= "transfer=yes\n";
583             } else if (strtolower($option) == 'mediaonly') {
584               $additional .= "transfer=mediaonly\n";
585             } else {
586               $additional .= $result['keyword']."=$option\n";
587             }
588             break;
589           case 'allow':
590           case 'disallow':
591             if ($option != '')
592               $additional .= $result['keyword']."=$option\n";
593             break;
594           default:
595             $additional .= $result['keyword']."=$option\n";
596         }
597       }
598     }
599
600     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
601     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
602     if(DB::IsError($results)) {
603       die($results->getMessage());
604     }
605    
606     foreach ($results as $result) {
607       $account = $result['data'];
608       $id = $result['id'];
609       $output .= "[$account]\n";
610  
611       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
612       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
613       if(DB::IsError($results2)) {
614         die($results2->getMessage());
615       }
616       foreach ($results2 as $result2) {
617         $options = explode("&", $result2['data']);
618         if ($ver12) {
619           foreach ($options as $option) {
620             $output .= $result2['keyword']."=$option\n";
621           }
622         } else {
623           foreach ($options as $option) {
624             switch ($result2['keyword']) {
625               case 'notransfer':
626                 if (strtolower($option) == 'yes') {
627                   $output .= "transfer=no\n";
628                 } else if (strtolower($option) == 'no') {
629                   $output .= "transfer=yes\n";
630                 } else if (strtolower($option) == 'mediaonly') {
631                   $output .= "transfer=mediaonly\n";
632                 } else {
633                   $output .= $result2['keyword']."=$option\n";
634                 }
635                 break;
636               case 'allow':
637               case 'disallow':
638                 if ($option != '')
639                   $output .= $result2['keyword']."=$option\n";
640                 break;
641               default:
642                 $output .= $result2['keyword']."=$option\n";
643             }
644           }
645         }
646       }
647       $output .= $additional."\n";
648     }
649     return $output;
650   }
651
652   function generate_mgcp_registrations($ast_version) {
653     global $db;
654
655     $table_name = "mgcp";
656     $output = "";
657
658     // items with id like 9999999% get put in the registration file
659     //
660     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
661     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
662     if(DB::IsError($results)) {
663       die($results->getMessage());
664     }
665
666     foreach ($results as $result) {
667       $output .= $result['keyword']."=".$result['data']."\n";
668     }
669
670     return $output;
671   }
672
673   function generate_skinny_additional($ast_version) {
674     global $db;
675
676     $table_name = "skinny";
677     $additional = "";
678     $output = "";
679
680     $ver12 = version_compare($ast_version, '1.4', 'lt');
681
682     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
683     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
684     if(DB::IsError($results)) {
685       die($results->getMessage());
686     }
687     foreach ($results as $result) {
688       if ($ver12) {
689         $additional .= $result['keyword']."=".$result['data']."\n";
690       } else {
691         $option = $result['data'];
692         switch ($result['keyword']) {
693           case 'notransfer':
694             if (strtolower($option) == 'yes') {
695               $additional .= "transfer=no\n";
696             } else if (strtolower($option) == 'no') {
697               $additional .= "transfer=yes\n";
698             } else if (strtolower($option) == 'mediaonly') {
699               $additional .= "transfer=mediaonly\n";
700             } else {
701               $additional .= $result['keyword']."=$option\n";
702             }
703             break;
704           case 'allow':
705           case 'disallow':
706             if ($option != '')
707               $additional .= $result['keyword']."=$option\n";
708             break;
709           default:
710             $additional .= $result['keyword']."=$option\n";
711         }
712       }
713     }
714
715     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
716     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
717     if(DB::IsError($results)) {
718       die($results->getMessage());
719     }
720    
721     foreach ($results as $result) {
722       $account = $result['data'];
723       $id = $result['id'];
724       $output .= "[$account]\n";
725  
726       $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC";
727       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
728       if(DB::IsError($results2)) {
729         die($results2->getMessage());
730       }
731       foreach ($results2 as $result2) {
732         $options = explode("&", $result2['data']);
733         if ($ver12) {
734           foreach ($options as $option) {
735             $output .= $result2['keyword']."=$option\n";
736           }
737         } else {
738           foreach ($options as $option) {
739             switch ($result2['keyword']) {
740               case 'notransfer':
741                 if (strtolower($option) == 'yes') {
742                   $output .= "transfer=no\n";
743                 } else if (strtolower($option) == 'no') {
744                   $output .= "transfer=yes\n";
745                 } else if (strtolower($option) == 'mediaonly') {
746                   $output .= "transfer=mediaonly\n";
747                 } else {
748                   $output .= $result2['keyword']."=$option\n";
749                 }
750                 break;
751               case 'allow':
752               case 'disallow':
753                 if ($option != '')
754                   $output .= $result2['keyword']."=$option\n";
755                 break;
756               default:
757                 $output .= $result2['keyword']."=$option\n";
758             }
759           }
760         }
761       }
762       $output .= $additional."\n";
763     }
764     return $output;
765   }
766
767   function generate_skinny_registrations($ast_version) {
768     global $db;
769
770     $table_name = "skinny";
771     $output = "";
772
773     // items with id like 9999999% get put in the registration file
774     //
775     $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1";
776     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
777     if(DB::IsError($results)) {
778       die($results->getMessage());
779     }
780
781     foreach ($results as $result) {
782       $output .= $result['keyword']."=".$result['data']."\n";
783     }
784
785     return $output;
786   }
787
788   function generate_zapata_additional($ast_version) {
789     global $db;
790
791     $table_name = "zap";
792
793     $additional = "";
794     $output = '';
795
796     $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1";
797     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
798     if(DB::IsError($results)) {
799       die($results->getMessage());
800     }
801     foreach ($results as $result) {
802       $additional .= $result['keyword']."=".$result['data']."\n";
803     }
804
805     $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data";
806     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
807     if(DB::IsError($results)) {
808       die($results->getMessage());
809     }
810
811     foreach ($results as $result) {
812       $account = $result['data'];
813       $id = $result['id'];
814       $output .= ";;;;;;[$account]\n";
815  
816       $sql = "SELECT keyword,data from $table_name where id=$id and keyword <> 'account' and flags <> 1 order by keyword DESC";
817       $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC);
818       if(DB::IsError($results2)) {
819         die($results2->getMessage());
820       }
821       $zapchannel="";
822       foreach ($results2 as $result2) {
823         if ($result2['keyword'] == 'channel') {
824           $zapchannel = $result2['data'];
825         } else {
826           $output .= $result2['keyword']."=".$result2['data']."\n";
827         }
828       }
829       $output .= "channel=>$zapchannel\n";
830       $output .= $additional."\n";
831     }
832     return $output;
833   }
834 }
835
836 // The destinations this module provides
837 // returns a associative arrays with keys 'destination' and 'description'
838 function core_destinations() {
839   //static destinations
840   $extens = array();
841   $category = 'Terminate Call';
842   $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category);
843   $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category);
844   $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category);
845   $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category);
846   $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category);
847   $extens[] = array('destination' => 'app-blackhole,ring,1', 'description' => 'Play ringtones to caller until they hangup', 'category' => $category);
848  
849   //get the list of meetmes
850   $results = core_users_list();
851  
852   if (isset($results) && function_exists('voicemail_getVoicemail')) {
853     //get voicemail
854     $uservm = voicemail_getVoicemail();
855     $vmcontexts = array_keys($uservm);
856     foreach ($results as $thisext) {
857       $extnum = $thisext[0];
858       // search vm contexts for this extensions mailbox
859       foreach ($vmcontexts as $vmcontext) {
860         if(isset($uservm[$vmcontext][$extnum])){
861           //$vmname = $uservm[$vmcontext][$extnum]['name'];
862           //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>');
863           $vmboxes[$extnum] = true;
864         }
865       }
866     }
867   }
868  
869   // return an associative array with destination and description
870   // core provides both users and voicemail boxes as destinations
871   if (isset($results)) {
872     foreach($results as $result) {
873       $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions');
874       if(isset($vmboxes[$result['0']])) {
875         $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail');
876         $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail');
877         $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail');
878       }
879     }
880   }
881  
882   if (isset($extens))
883     return $extens;
884   else
885     return null;
886 }
887
888 function core_getdest($exten) {
889   $dests[] = 'from-did-direct,'.$exten.',1';
890   if (!function_exists('voicemail_mailbox_get')) {
891     return $dests;
892   }
893   $box = voicemail_mailbox_get($exten);
894   if ($box == null) {
895     return $dests;
896   }
897   $dests[] = 'ext-local,vmb'.$exten.',1';
898   $dests[] = 'ext-local,vmu'.$exten.',1';
899   $dests[] = 'ext-local,vms'.$exten.',1';
900
901   return $dests;
902 }
903
904 function core_getdestinfo($dest) {
905   global $active_modules;
906
907   // Check for Extension Number Destinations
908   //
909   if (substr(trim($dest),0,16) == 'from-did-direct,') {
910     $exten = explode(',',$dest);
911     $exten = $exten[1];
912     $thisexten = core_users_get($exten);
913     if (empty($thisexten)) {
914       return array();
915     } else {
916       //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
917       $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
918       return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
919                    'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
920                   );
921     }
922
923   // Check for voicemail box destinations
924   //
925   } else if (substr(trim($dest),0,12) == 'ext-local,vm') {
926     $exten = explode(',',$dest);
927     $exten = substr($exten[1],3);
928     if (!function_exists('voicemail_mailbox_get')) {
929       return array();
930     }
931     $thisexten = core_users_get($exten);
932     if (empty($thisexten)) {
933       return array();
934     }
935     $box = voicemail_mailbox_get($exten);
936     if ($box == null) {
937       return array();
938     }
939     $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
940     return array('description' => 'User Extension '.$exten.': '.$thisexten['name'],
941                  'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0",
942                 );
943
944   // Check for blackhole Termination Destinations
945   //
946   } else if (substr(trim($dest),0,14) == 'app-blackhole,') {
947     $exten = explode(',',$dest);
948     $exten = $exten[1];
949
950     switch ($exten) {
951       case 'hangup':
952         $description = 'Hangup';
953         break;
954       case 'congestion':
955         $description = 'Congestion';
956         break;
957       case 'busy':
958         $description = 'Busy';
959         break;
960       case 'zapateller':
961         $description = 'Play SIT Tone (Zapateller)';
962         break;
963       case 'musiconhold':
964         $description = 'Put caller on hold forever';
965         break;
966       case 'ring':
967         $description = 'Play ringtones to caller';
968         break;
969       default:
970         $description = false;
971     }
972     if ($description) {
973       return array('description' => 'Core: '.$description,
974                    'edit_url' => false,
975                    );
976     } else {
977       return array();
978     }
979
980   // None of the above, so not one of ours
981   //
982   } else {
983     return false;
984   }
985 }
986 /*  Generates dialplan for "core" components (extensions & inbound routing)
987   We call this with retrieve_conf
988 */
989 function core_get_config($engine) {
990   global $ext;  // is this the best way to pass this?
991   global $version;  // this is not the best way to pass this, this should be passetd together with $engine
992   global $amp_conf;
993   global $core_conf;
994
995   $modulename = "core";
996  
997   switch($engine) {
998     case "asterisk":
999
1000       // Now add to sip_general_addtional.conf
1001       //
1002       if (isset($core_conf) && is_a($core_conf, "core_conf")) {
1003         $core_conf->addSipGeneral('bindport','5060');
1004         $core_conf->addSipGeneral('bindaddr','0.0.0.0');
1005         $core_conf->addSipGeneral('disallow','all');
1006         $core_conf->addSipGeneral('allow','ulaw');
1007         $core_conf->addSipGeneral('allow','alaw');
1008         $core_conf->addSipGeneral('context','from-sip-external');
1009         $core_conf->addSipGeneral('callerid','Unknown');
1010         $core_conf->addSipGeneral('notifyringing','yes');
1011         if (version_compare($version, '1.4', 'ge')) {
1012           $core_conf->addSipGeneral('notifyhold','yes');
1013           $core_conf->addSipGeneral('limitonpeers','yes');
1014           $core_conf->addSipGeneral('tos_sip','cs3');    // Recommended setting from doc/ip-tos.txt
1015           $core_conf->addSipGeneral('tos_audio','ef');   // Recommended setting from doc/ip-tos.txt
1016           $core_conf->addSipGeneral('tos_video','af41'); // Recommended setting from doc/ip-tos.txt
1017         } else {
1018           $core_conf->addSipGeneral('tos','0x68'); // This really doesn't do anything with astersk not running as root
1019         }
1020         $core_conf->addIaxGeneral('bindport','4569');
1021         $core_conf->addIaxGeneral('bindaddr','0.0.0.0');
1022         $core_conf->addIaxGeneral('disallow','all');
1023         $core_conf->addIaxGeneral('allow','ulaw');
1024         $core_conf->addIaxGeneral('allow','alaw');
1025         $core_conf->addIaxGeneral('allow','gsm');
1026         $core_conf->addIaxGeneral('mailboxdetail','yes');
1027         if (version_compare($version, '1.4', 'ge')) {
1028           $core_conf->addIaxGeneral('tos','ef'); // Recommended setting from doc/ip-tos.txt
1029         }
1030         $core_conf->addH323General('bindport','1720');
1031         $core_conf->addH323General('bindaddr','0.0.0.0');
1032         $core_conf->addH323General('h225portrange','12030,12230');
1033         $core_conf->addH323General('h323id','ObjSysAsterisk');
1034         $core_conf->addH323General('gatekeeper','DISABLE');
1035         $core_conf->addH323General('faststart','no');
1036         $core_conf->addH323General('rtptimeout','10');
1037         $core_conf->addH323General('dtmfmode','rfc2833');
1038         $core_conf->addH323General('canreinvite','no');
1039         $core_conf->addH323General('disallow','all');
1040         $core_conf->addH323General('allow','ulaw');
1041         $core_conf->addH323General('allow','gsm');
1042         $core_conf->addH323General('context','from-internal');
1043         $core_conf->addMgcpGeneral('port','2427');
1044         $core_conf->addMgcpGeneral('bindaddr','0.0.0.0');
1045         $core_conf->addMgcpGeneral('canreinvite','no');
1046         $core_conf->addMgcpGeneral('wcardep','*');
1047         $core_conf->addSkinnyGeneral('port','2000');
1048         $core_conf->addSkinnyGeneral('bindaddr','0.0.0.0');
1049         $core_conf->addSkinnyGeneral('dateFormat','D-M-Y');
1050         $core_conf->addSkinnyGeneral('keepAlive','120');
1051
1052         $fcc = new featurecode($modulename, 'blindxfer');
1053         $code = $fcc->getCodeActive();
1054         unset($fcc);
1055         if ($code != '') {
1056           $core_conf->addFeatureMap('blindxfer',$code);
1057         }
1058
1059         $fcc = new featurecode($modulename, 'atxfer');
1060         $code = $fcc->getCodeActive();
1061         unset($fcc);
1062         if ($code != '') {
1063           $core_conf->addFeatureMap('atxfer',$code);
1064         }
1065
1066         $fcc = new featurecode($modulename, 'automon');
1067         $code = $fcc->getCodeActive();
1068         unset($fcc);
1069         if ($code != '') {
1070           $core_conf->addFeatureMap('automon',$code);
1071         }
1072
1073         $core_conf->addFeatureMap('disconnect','**');
1074       }
1075
1076       // FeatureCodes
1077       $fcc = new featurecode($modulename, 'userlogon');
1078       $fc_userlogon = $fcc->getCodeActive();
1079       unset($fcc);
1080
1081       $fcc = new featurecode($modulename, 'userlogoff');
1082       $fc_userlogoff = $fcc->getCodeActive();
1083       unset($fcc);
1084
1085       $fcc = new featurecode($modulename, 'zapbarge');
1086       $fc_zapbarge = $fcc->getCodeActive();
1087       unset($fcc);
1088
1089       $fcc = new featurecode($modulename, 'chanspy');
1090       $fc_chanspy = $fcc->getCodeActive();
1091       unset($fcc);
1092
1093       $fcc = new featurecode($modulename, 'simu_pstn');
1094       $fc_simu_pstn = $fcc->getCodeActive();
1095       unset($fcc);
1096
1097       $fcc = new featurecode($modulename, 'simu_fax');
1098       $fc_simu_fax = $fcc->getCodeActive();
1099       unset($fcc);
1100
1101       $fcc = new featurecode($modulename, 'pickup');
1102       $fc_pickup = $fcc->getCodeActive();
1103       unset($fcc);
1104
1105       // Log on / off -- all in one context
1106       if ($fc_userlogoff != '' || $fc_userlogon != '') {
1107         $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal
1108        
1109         if ($fc_userlogoff != '') {
1110           $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
1111           $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup(''));
1112         }
1113  
1114         if ($fc_userlogon != '') {
1115           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
1116           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
1117          
1118           $clen = strlen($fc_userlogon);
1119           $fc_userlogon = "_$fc_userlogon.";
1120           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}'));
1121           $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
1122         }
1123       }
1124
1125       // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
1126       // when a user pushes a flashing BLF.
1127       if ($fc_pickup != '') {
1128         $ext->addInclude('from-internal-additional', 'app-pickup');
1129         $fclen = strlen($fc_pickup);
1130         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}'));
1131         if (strstr($version, 'BRI'))
1132           $ext->add('app-pickup', "_$fc_pickup.", '', new ext_dpickup('${EXTEN:'.$fclen.'}'));
1133         else
1134           $ext->add('app-pickup', "_$fc_pickup.", '', new ext_pickup('${EXTEN:'.$fclen.'}'));
1135       }
1136      
1137      
1138       // zap barge
1139       if ($fc_zapbarge != '') {
1140         $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal
1141        
1142         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
1143         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}'));
1144         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
1145         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
1146         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
1147         $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
1148       }
1149
1150       // chan spy
1151       if ($fc_chanspy != '') {
1152         $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal
1153         $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
1154         $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
1155         $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
1156         $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
1157         $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
1158       }
1159      
1160       // Simulate options (ext-test)
1161       if ($fc_simu_pstn != '' || $fc_simu_fax != '') {
1162         $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal
1163        
1164         if ($fc_simu_pstn != '') {
1165           $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
1166         }
1167
1168         if ($fc_simu_fax != '') {
1169           $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax'));
1170         }
1171
1172         $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
1173       }
1174      
1175       /* Always have Fax detection in ext-did, no matter what */
1176       $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax'));
1177
1178       /* inbound routing extensions */
1179       $didlist = core_did_list();
1180       if(is_array($didlist)){
1181         $catchall = false;
1182         $catchall_context='ext-did-catchall';
1183         foreach($didlist as $item) {
1184           $did = core_did_get($item['extension'],$item['cidnum']);
1185           $exten = $did['extension'];
1186           $cidnum = $did['cidnum'];
1187
1188           $exten = (empty($exten)?"s":$exten);
1189           $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it
1190
1191           $context = "ext-did";
1192
1193           $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
1194           // always set callerID name
1195           $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
1196           $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
1197           $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
1198
1199           if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
1200             $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
1201             $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
1202           }
1203
1204           // If we require RINGING, signal it as soon as we enter.
1205           if ($item['ringing'] === "CHECKED") {
1206             $ext->add($context, $exten, '', new ext_ringing(''));
1207           }
1208
1209           if ($exten == "s" && $context == "ext-did") { 
1210             //if the exten is s, then also make a catchall for undefined DIDs
1211             $catchaccount = "_.".(empty($cidnum)?"":"/".$cidnum);
1212             if ($catchaccount =="_." && ! $catchall) {
1213               $catchall = true;
1214               $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
1215               $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did'));
1216             }
1217           }
1218          
1219           if ($item['faxexten'] != "default") {
1220             $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
1221           }
1222           if (!empty($item['faxemail'])) {
1223             $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
1224           }
1225           if ($item['answer'] == "1") {
1226             $ext->add($context, $exten, '', new ext_answer(''));
1227             $ext->add($context, $exten, '', new ext_wait($item['wait']));
1228           }
1229           if ($item['answer'] == "2") { // NVFaxDetect
1230             $ext->add($context, $exten, '', new ext_answer(''));
1231             $ext->add($context, $exten, '', new ext_playtones('ring'));
1232             $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
1233           }
1234           if ($item['privacyman'] == "1") {
1235             $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
1236           }
1237           if (!empty($item['alertinfo'])) {
1238             $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo'])));
1239           }
1240           // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should
1241           // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different
1242           // modules.
1243           //
1244           // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here.
1245           //
1246           // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX)
1247           //
1248           if (!empty($item['grppre'])) {
1249             $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre']));
1250             $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
1251           }
1252          
1253           //the goto destination
1254           // destination field in 'incoming' database is backwards from what ext_goto expects
1255           $goto_context = strtok($did['destination'],',');
1256           $goto_exten = strtok(',');
1257           $goto_pri = strtok(',');
1258           $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
1259          
1260         }
1261         // If there's not a catchall, make one with an error message
1262         if (!$catchall) {
1263           $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
1264           $ext->add($catchall_context, 's', '', new ext_answer(''));
1265           $ext->add($catchall_context, 's', '', new ext_wait('2'));
1266           $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
1267           $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
1268           $ext->add($catchall_context, '_[*#X].', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
1269           $ext->add($catchall_context, '_[*#X].', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
1270           $ext->add($catchall_context, '_[*#X].', '', new ext_goto('1','s','ext-did'));
1271         }
1272          
1273       }
1274
1275       /* MODIFIED (PL)
1276        *
1277        * Add Direct DIDs
1278        *
1279        * This functions creates a new context, ext-did-direct, used to route an incoming DID directly to the specified user.
1280        * The purpose is to use when a user has a personal external DID. This keeps it clean and easy to administer.
1281        * Any conflict with those routes will depend on which of the two contexts are included first in the extensions.conf file.
1282        *
1283        * Calls are sent to context from-did-direct though this feature. You must create that context in extenions.conf or
1284        * in extensions_custom.conf and it should look something like:
1285        *
1286        * [from-did-direct]
1287        * include => ext-findmefollow
1288        * include => ext-local
1289        *
1290        * This is so that personal ring groups are used if they exist for the direct did and if not, then the local extension.
1291        * If the module is not implented, it will just go to the users extension.
1292        */
1293
1294       $directdidlist = core_directdid_list();
1295       if(is_array($directdidlist)){
1296         $context = "ext-did";
1297         if(!is_array($didlist)){
1298           /* if not set above, add one here */
1299           $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
1300         }
1301         foreach($directdidlist as $item) {
1302           $exten = $item['directdid'];
1303           $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
1304           // always set callerID name
1305           $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
1306           $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
1307           $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
1308
1309           if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
1310             $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
1311             $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
1312           }
1313          
1314           if ($item['faxexten'] != "default") {
1315             $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
1316           }
1317           if (!empty($item['faxemail'])) {
1318             $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
1319           }
1320           if ($item['answer'] == "1") {
1321             $ext->add($context, $exten, '', new ext_answer(''));
1322             $ext->add($context, $exten, '', new ext_wait($item['wait']));
1323           }
1324           if ($item['answer'] == "2") { // NVFaxDetect
1325             $ext->add($context, $exten, '', new ext_answer(''));
1326             $ext->add($context, $exten, '', new ext_playtones('ring'));
1327             $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
1328           }
1329           if ($item['privacyman'] == "1") {
1330             $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
1331           }
1332
1333
1334           if (!empty($item['didalert'])) {
1335             $ext->add($context, $exten, '', new ext_setvar("_ALERT_INFO", str_replace(';', '\;', $item['didalert'])));
1336           }
1337           $goto_context = 'from-did-direct';
1338           $goto_exten = $item['extension'];
1339           $goto_pri = 1;
1340           $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
1341
1342         }
1343       }
1344
1345       // Now create macro-from-zaptel-nnn for each defined channel to route it to the DID routing
1346       // Send it to from-trunk so it is handled as other dids would be handled.
1347       //
1348       foreach (core_zapchandids_list() as $row) {
1349         $channel = $row['channel'];
1350         $did     = $row['did'];
1351
1352         $zap_context = "macro-from-zaptel-{$channel}";
1353         $ext->add($zap_context, 's', '', new ext_noop('Entering '.$zap_context.' with DID = ${DID} and setting to: '.$did));
1354         $ext->add($zap_context, 's', '', new ext_setvar('__FROM_DID',$did));
1355         $ext->add($zap_context, 's', '', new ext_goto('1',$did,'from-trunk'));
1356       }
1357
1358       /* user extensions */
1359       $ext->addInclude('from-internal-additional','ext-local');
1360
1361       // If running in Dynamic mode, this will insert the hints through an Asterisk #exec call.
1362       // which require "execincludes=yes" to be set in the [options] section of asterisk.conf
1363       //
1364       if ($amp_conf['DYNAMICHINTS']) {
1365         $ext->addExec('ext-local',$amp_conf['AMPBIN'].'/generate_hints.php');
1366       }
1367       $userlist = core_users_list();
1368       if (is_array($userlist)) {
1369         foreach($userlist as $item) {
1370           $exten = core_users_get($item[0]);
1371           $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']);
1372
1373           if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0)
1374             $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer']));
1375          
1376           $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension']));
1377           $ext->add('ext-local', $exten['extension'], '', new ext_hangup(''));
1378          
1379           if($vm != "novm") {
1380             $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',"$vm,DIRECTDIAL"));
1381             $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_hangup(''));
1382             $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',"$vm,BUSY"));
1383             $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_hangup(''));
1384             $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',"$vm,NOANSWER"));
1385             $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_hangup(''));
1386             $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',"$vm,NOMESSAGE"));
1387             $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_hangup(''));
1388           }
1389            
1390           // Create the hints if running in normal mode
1391           //
1392           if (!$amp_conf['DYNAMICHINTS']) {
1393             $hint = core_hint_get($exten['extension']);
1394             if (!empty($hint)) {
1395               $ext->addHint('ext-local', $exten['extension'], $hint);
1396             }
1397           }
1398           if ($exten['sipname']) {
1399             $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal'));
1400           }
1401           // Now make a special context for the IVR inclusions of local extension dialing so that
1402           // when people use the Queues breakout ability, and break out to someone's extensions, voicemail
1403           // works.
1404           //
1405           $ivr_context = 'from-did-direct-ivr';
1406           $ext->add($ivr_context, $exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
1407           $ext->add($ivr_context, $exten['extension'],'', new ext_setvar('__NODEST', ''));
1408           $ext->add($ivr_context, $exten['extension'],'', new ext_goto('1',$exten['extension'],'from-did-direct'));
1409           if($vm != "novm") {
1410             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}'));
1411             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_setvar('__NODEST', ''));
1412             $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_macro('vm',"$vm,DIRECTDIAL"));
1413           }
1414         }
1415       }
1416
1417       // create from-trunk context for each trunk that adds counts to channels
1418       //
1419       $trunklist = core_trunks_list(true);
1420       if (is_array($trunklist)) {
1421         foreach ($trunklist as $trunkprops) {
1422           if (trim($trunkprops['value']) == 'on') {
1423             // value of on is disabled and for zap we don't create a context
1424             continue;
1425           }
1426           switch ($trunkprops['tech']) {
1427             case 'H323':
1428             case 'IAX':
1429             case 'IAX2':
1430             case 'MGCP':
1431             case 'Skinny':
1432             case 'SIP':
1433               $trunkgroup = $trunkprops['globalvar'];
1434               $trunkcontext  = "from-trunk-".strtolower($trunkprops['tech'])."-".$trunkprops['name'];
1435               $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup));
1436               $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk'));
1437               break;
1438             case 'DUNDI':
1439               $macro_name = 'macro-dundi-'.substr($trunkprops['globalvar'],4);
1440               $ext->addSwitch($macro_name,'DUNDI/'.$trunkprops['name']);
1441               $ext->add($macro_name, 's', '', new ext_goto('1','${ARG1}'));
1442               break;
1443             default:
1444           }
1445         }
1446       }
1447
1448       /* dialplan globals */
1449       // modules should NOT use the globals table to store anything!
1450       // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
1451       // I'm cheating for core functionality - do as I say, not as I do ;-)   
1452
1453       // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
1454       //
1455       $amp_conf_globals = array(
1456         "ASTETCDIR",
1457         "ASTMODDIR",
1458         "ASTVARLIBDIR",
1459         "ASTAGIDIR",
1460         "ASTSPOOLDIR",
1461         "ASTRUNDIR",
1462         "ASTLOGDIR",
1463         "CWINUSEBUSY",
1464         "AMPMGRUSER",
1465         "AMPMGRPASS"
1466       );
1467
1468       $sql = "SELECT * FROM globals";
1469       $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1470       foreach($globals as $global) {
1471         $ext->addGlobal($global['variable'],$global['value']);
1472
1473         // now if for some reason we have a variable in the global table
1474         // that is in our $amp_conf_globals list, then remove it so we
1475         // don't duplicate, the sql table will take precedence
1476         //
1477         if (array_key_exists($global['variable'],$amp_conf_globals)) {
1478           $rm_keys = array_keys($amp_conf_globals,$global['variable']);
1479           foreach ($rm_keys as $index) {
1480             unset($amp_conf_globals[$index]);
1481           }
1482         }
1483       }
1484       foreach ($amp_conf_globals as $global) {
1485         if (isset($amp_conf[$global])) {
1486           $value = $amp_conf[$global];
1487           if ($value === true || $value === false) {
1488             $value = ($value) ? 'true':'false';
1489           }
1490           $ext->addGlobal($global, $value);
1491           out("Added to globals: $global = $value");
1492         }
1493       }
1494       // Put the asterisk version in a global for agi etc.
1495       $ext->addGlobal('ASTVERSION', $version);
1496
1497       /* outbound routes */
1498       // modules should use their own table for storage (and module_get_config() to add dialplan)
1499       // modules should NOT use the extension table to store anything!
1500       $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application";
1501       $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1502       $ext->addInclude('from-internal-additional','outbound-allroutes');
1503       $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
1504       foreach($outrts as $outrt) {
1505         $ext->addInclude('outbound-allroutes',$outrt['application']);
1506         $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC";
1507         $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1508         $lastexten = false;
1509         foreach($thisrt as $exten) {
1510           //if emergencyroute, then set channel var
1511           if(strpos($exten['args'],"EMERGENCYROUTE") !== false)
1512             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15)));
1513           if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false)
1514             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18)));
1515           // Don't set MOHCLASS if already set, threre may be a feature code that overrode it
1516           if(strpos($exten['args'],"MOHCLASS") !== false)
1517             $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' ));
1518           if(strpos($exten['args'],"dialout-trunk") !== false || strpos($exten['args'],"dialout-enum") !== false || strpos($exten['args'],"dialout-dundi") !== false) {
1519             if ($exten['extension'] !== $lastexten) {
1520
1521               // If NODEST is set, clear it. No point in remembering since dialout-trunk will just end in the
1522               // bit bucket. But if answered by an outside line with transfer capability, we want NODEST to be
1523               // clear so a subsequent transfer to an internal extension works and goes to voicmail or other
1524               // destinations.
1525               //
1526               // Then do one call to user-callerid and record-enable instead of each time as in the past
1527               //
1528               $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('user-callerid,SKIPTTL'));
1529               $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("_NODEST",""));
1530               $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('record-enable,${AMPUSER},OUT'));
1531               $lastexten = $exten['extension'];
1532             }
1533             $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
1534           }
1535           if(strpos($exten['args'],"outisbusy") !== false)
1536             $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy"));
1537         }
1538       }
1539
1540       general_generate_indications();
1541
1542       // "blackhole" destinations
1543       $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
1544       $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
1545
1546       $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
1547       $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
1548       $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
1549       // Should hangup ?
1550       // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
1551          
1552       $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
1553       $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
1554       $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
1555
1556       $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
1557       $ext->add('app-blackhole', 'congestion', '', new ext_answer());
1558       $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
1559       $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
1560       $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
1561
1562       $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
1563       $ext->add('app-blackhole', 'busy', '', new ext_answer());
1564       $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy'));
1565       $ext->add('app-blackhole', 'busy', '', new ext_busy());
1566       $ext->add('app-blackhole', 'busy', '', new ext_hangup());
1567
1568       $ext->add('app-blackhole', 'ring', '', new ext_noop('Blackhole Dest: Ring'));
1569       $ext->add('app-blackhole', 'ring', '', new ext_answer());
1570       $ext->add('app-blackhole', 'ring', '', new ext_playtones('ring'));
1571       $ext->add('app-blackhole', 'ring', '', new ext_wait(300));
1572       $ext->add('app-blackhole', 'ring', '', new ext_hangup());
1573
1574       if ($amp_conf['AMPBADNUMBER'] !== false) {
1575         $context = 'bad-number';
1576         $exten = '_X.';
1577         $ext->add($context, $exten, '', new extension('ResetCDR()'));
1578         $ext->add($context, $exten, '', new extension('NoCDR()'));
1579         $ext->add($context, $exten, '', new ext_wait('1'));
1580         $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1581         $ext->add($context, $exten, '', new ext_wait('1'));
1582         $ext->add($context, $exten, '', new ext_congestion('20'));
1583         $ext->add($context, $exten, '', new ext_hangup());
1584
1585         $exten = '_*.';
1586         $ext->add($context, $exten, '', new extension('ResetCDR()'));
1587         $ext->add($context, $exten, '', new extension('NoCDR()'));
1588         $ext->add($context, $exten, '', new ext_wait('1'));
1589         $ext->add($context, $exten, '', new ext_playback('silence/1&feature-not-avail-line&silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
1590         $ext->add($context, $exten, '', new ext_wait('1'));
1591         $ext->add($context, $exten, '', new ext_congestion('20'));
1592         $ext->add($context, $exten, '', new ext_hangup());
1593       }
1594
1595       $context = 'macro-dialout-trunk';
1596       $exten = 's';
1597      
1598       /*
1599        * dialout using a trunk, using pattern matching (don't strip any prefix)
1600        * arg1 = trunk number, arg2 = number, arg3 = route password
1601        *
1602        * MODIFIED (PL)
1603        *
1604        * Modified both Dial() commands to include the new TRUNK_OPTIONS from the general
1605        * screen of AMP
1606        */
1607       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1608       $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1609       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
1610       $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this
1611       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company
1612       $ext->add($context, $exten, '', new ext_set('GROUP()', 'OUT_${DIAL_TRUNK}'));
1613       $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
1614       $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} > ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
1615       $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));  // Set to YES if treated like internal
1616       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}'));
1617       $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
1618       $ext->add($context, $exten, 'skipoutcid', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1619       $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number
1620       $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}'));  // Custom trunks are prefixed with "AMP:"
1621    
1622       // Back to normal processing, whether intracompany or not.
1623       // But add the macro-setmusic if we don't want music on this outbound call
1624       $ext->add($context, $exten, '', new ext_gotoif('$[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]', 'gocall'));  // Set to YES if we should pump silence
1625       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', 'M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));  // set MoH or off
1626    
1627       // This macro call will always be blank and is provided as a hook for customization required prior to making a call
1628       // such as adding SIP header information or other requirements. All the channel variables from above are present
1629      
1630       $ext->add($context, $exten, 'gocall', new ext_macro('dialout-trunk-predial-hook'));
1631       $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
1632    
1633       $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
1634       $ext->add($context, $exten, '', new ext_dial('${OUT_${DIAL_TRUNK}}/${OUTNUM}', '300,${DIAL_TRUNK_OPTIONS}'));  // Regular Trunk Dial
1635       $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1636      
1637       $ext->add($context, $exten, 'customtrunk', new ext_set('pre_num', '${CUT(OUT_${DIAL_TRUNK},$,1)}'));
1638       $ext->add($context, $exten, '', new ext_set('the_num', '${CUT(OUT_${DIAL_TRUNK},$,2)}'));  // this is where we expect to find string OUTNUM
1639       $ext->add($context, $exten, '', new ext_set('post_num', '${CUT(OUT_${DIAL_TRUNK},$,3)}'));
1640       $ext->add($context, $exten, '', new ext_gotoif('$["${the_num}" = "OUTNUM"]', 'outnum', 'skipoutnum'));  // if we didn't find "OUTNUM", then skip to Dial
1641       $ext->add($context, $exten, 'outnum', new ext_set('the_num', '${OUTNUM}'));  // replace "OUTNUM" with the actual number to dial
1642       $ext->add($context, $exten, 'skipoutnum', new ext_dial('${pre_num:4}${the_num}${post_num}', '300,${DIAL_TRUNK_OPTIONS}'));
1643       $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1644      
1645       $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
1646    
1647       $exten = 's-BUSY';
1648       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
1649       $ext->add($context, $exten, '', new ext_playtones('busy'));
1650       $ext->add($context, $exten, '', new ext_busy(20));
1651    
1652       $exten = 's-NOANSWER';
1653       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
1654       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1655       $ext->add($context, $exten, '', new ext_congestion(20));
1656    
1657       $exten = 's-CANCEL';
1658       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up'));
1659       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1660       $ext->add($context, $exten, '', new ext_congestion(20));
1661    
1662       $exten = '_s-.';
1663       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport'));
1664       $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
1665       $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks'));
1666      
1667       $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
1668       $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook'));
1669    
1670       $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1671
1672
1673
1674
1675       $context = 'macro-dialout-dundi';
1676       $exten = 's';
1677      
1678       /*
1679        * Dialout Dundi Trunk
1680        */
1681       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1682       $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1683       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1'));
1684       $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this
1685       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company
1686       $ext->add($context, $exten, '', new ext_set('GROUP()', 'OUT_${DIAL_TRUNK}'));
1687       $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax'));
1688       $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} > ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull'));
1689       $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid'));  // Set to YES if treated like internal
1690       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}'));
1691       $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}'));
1692       $ext->add($context, $exten, 'skipoutcid', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1693       $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}'));  // OUTNUM is the final dial number
1694
1695       // Back to normal processing, whether intracompany or not.
1696       // But add the macro-setmusic if we don't want music on this outbound call
1697       $ext->add($context, $exten, '', new ext_gotoif('$[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]', 'gocall'));  // Set to YES if we should pump silence
1698       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', 'M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}'));  // set MoH or off
1699    
1700       // This macro call will always be blank and is provided as a hook for customization required prior to making a call
1701       // such as adding SIP header information or other requirements. All the channel variables from above are present
1702      
1703       $ext->add($context, $exten, 'gocall', new ext_macro('dialout-dundi-predial-hook'));
1704       $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1'));
1705    
1706       $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk'));
1707
1708       $ext->add($context, $exten, '', new ext_macro('dundi-${DIAL_TRUNK}','${OUTNUM}'));
1709       $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}'));
1710      
1711       $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up'));
1712    
1713       $exten = 's-BUSY';
1714       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up'));
1715       $ext->add($context, $exten, '', new ext_playtones('busy'));
1716       $ext->add($context, $exten, '', new ext_busy(20));
1717    
1718       $exten = 's-NOANSWER';
1719       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up'));
1720       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1721       $ext->add($context, $exten, '', new ext_congestion(20));
1722    
1723       $exten = 's-CANCEL';
1724       $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up'));
1725       $ext->add($context, $exten, '', new ext_playtones('congestion'));
1726       $ext->add($context, $exten, '', new ext_congestion(20));
1727    
1728       $exten = '_s-.';
1729       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport'));
1730       $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}'));
1731       $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks'));
1732      
1733       $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk'));
1734       $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-dundi-predial-hook'));
1735    
1736       $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1737
1738
1739
1740       /*
1741        * sets the callerid of the device to that of the logged in user
1742        *
1743        * ${AMPUSER} is set upon return to the real user despite any aliasing that may
1744        * have been set as a result of the AMPUSER/<nnn>/cidnum field. This is used by
1745        * features like DND, CF, etc. to set the proper structure on aliased instructions
1746        */
1747       $context = 'macro-user-callerid';
1748       $exten = 's';
1749      
1750       $ext->add($context, $exten, '', new ext_noop('user-callerid: ${CALLERID(name)} ${CALLERID(number)}'));
1751              
1752       // make sure AMPUSER is set if it doesn't get set below     
1753       $ext->add($context, $exten, '', new ext_set('AMPUSER', '${IF($["foo${AMPUSER}" = "foo"]?${CALLERID(number)}:${AMPUSER})}'));
1754       $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}" = "Local"]', 'report'));
1755       $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}'));
1756       $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1757       $ext->add($context, $exten, '', new ext_set('AMPUSER', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1758       $ext->add($context, $exten, '', new ext_set('AMPUSERCIDNAME', '${DB(AMPUSER/${AMPUSER}/cidname)}'));
1759       $ext->add($context, $exten, '', new ext_gotoif('$["x${AMPUSERCIDNAME:1:2}" = "x"]', 'report'));
1760
1761       // user may masquerade as a different user internally, so set the internal cid as indicated
1762       // but keep the REALCALLERID which is used to determine their true identify and lookup info
1763       // during outbound calls.
1764       $ext->add($context, $exten, '', new ext_set('AMPUSERCID', '${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}'));
1765       $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '"${AMPUSERCIDNAME}" <${AMPUSERCID}>'));
1766       $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${DB(DEVICE/${REALCALLERIDNUM}/user)}'));
1767       if (version_compare($version, "1.4", "ge")) {
1768         $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/language)}" != ""]', 'Set', 'CHANNEL(language)=${DB(AMPUSER/${AMPUSER}/language)}'));
1769       } else {
1770         $ext->add($context, $exten, '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/language)}" != ""]', 'Set', 'LANGUAGE()=${DB(AMPUSER/${AMPUSER}/language)}'));
1771       }
1772       $ext->add($context, $exten, 'report', new ext_noop('TTL: ${TTL} ARG1: ${ARG1}'));
1773       $ext->add($context, $exten, '', new ext_gotoif('$[ "${ARG1}" = "SKIPTTL" ]', 'continue'));
1774       $ext->add($context, $exten, 'report2', new ext_set('__TTL', '${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}'));
1775       $ext->add($context, $exten, '', new ext_gotoif('$[ ${TTL} > 0 ]', 'continue'));
1776       $ext->add($context, $exten, '', new ext_wait('${RINGTIMER}'));  // wait for a while, to give it a chance to be picked up by voicemail
1777       $ext->add($context, $exten, '', new ext_answer());
1778       $ext->add($context, $exten, '', new ext_wait('2'));
1779       $ext->add($context, $exten, '', new ext_playback('im-sorry&an-error-has-occured&with&call-forwarding'));
1780       $ext->add($context, $exten, '', new ext_macro('hangupcall'));
1781       $ext->add($context, $exten, '', new ext_congestion(20));
1782       $ext->add($context, $exten, 'continue', new ext_noop('Using CallerID ${CALLERID(all)}'));
1783       $ext->add($context, 'h', '', new ext_macro('hangupcall'));
1784      
1785       /*
1786        * arg1 = trunk number, arg2 = number
1787        *
1788        * Re-written to use enumlookup.agi
1789        */
1790  
1791       $context = 'macro-dialout-enum';
1792       $exten = 's';
1793  
1794       $ext->add($context, $exten, '', new ext_execif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]', 'Authenticate', '${ARG3}'));
1795       $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${ARG1}'));
1796       $ext->add($context, $exten, '', new ext_set('GROUP()', 'OUT_${ARG1}'));
1797       $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${ARG1}}foo" = "foo"]', 'nomax'));
1798       $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${ARG1})} > ${OUTMAXCHANS_${ARG1}} ]', 'nochans'));
1799       $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}'));
1800       $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}'));
1801       $ext->add($context, $exten, '', new ext_agi('fixlocalprefix'));  // this sets DIAL_NUMBER to the proper dial string for this trunk
1802       //  Replacement for asterisk's ENUMLOOKUP function
1803       $ext->add($context, $exten, '', new ext_agi('enumlookup.agi'));
1804       // Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority
1805       // Loop through them trying them in order.
1806       $ext->add($context, $exten, 'dialloop', new ext_gotoif('$["foo${DIALARR}"="foo"]', 'end'));
1807       $ext->add($context, $exten, '', new ext_set('TRYDIAL', '${CUT(DIALARR,%,1)}'));
1808       $ext->add($context, $exten, '', new ext_set('DIALARR', '${CUT(DIALARR,%,2-)}'));
1809       $ext->add($context, $exten, '', new ext_dial('${TRYDIAL}', ''));
1810       $ext->add($context, $exten, '', new ext_noop('Dial exited in macro-enum-dialout with ${DIALSTATUS}'));
1811       // Now, if we're still here, that means the Dial failed for some reason.
1812       // If it's CONGESTION or CHANUNAVAIL we want to try again on a different
1813       // different channel. If there's no more left, the dialloop tag will exit.
1814       $ext->add($context, $exten, '', new ext_gotoif('$[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]', 'dialloop'));
1815       // If we're here, then it's BUSY or NOANSWER or something and well, deal with it.
1816       $ext->add($context, $exten, 'dialfailed', new ext_goto(1, 's-${DIALSTATUS}'));
1817       // Here are the exit points for the macro.
1818       $ext->add($context, $exten, 'nochans', new ext_noop('max channels used up'));
1819       $ext->add($context, $exten, 'end', new ext_noop('Exiting macro-dialout-enum'));
1820       $ext->add($context, 's-BUSY', '', new ext_noop('Trunk is reporting BUSY'));
1821       $ext->add($context, 's-BUSY', '', new ext_busy(20));
1822       $ext->add($context, '_s-.', '', new ext_noop('Dial failed due to ${DIALSTATUS}'));     
1823      
1824       /*
1825        * overrides callerid out trunks
1826        * arg1 is trunk
1827        * macro-user-callerid should be called _before_ using this macro
1828        */
1829
1830       $context = 'macro-outbound-callerid';
1831       $exten = 's';
1832      
1833       // Keep the original CallerID number, for failover to the next trunk.
1834       $ext->add($context, $exten, '', new ext_gotoif('$["${REALCALLERIDNUM:1:2}" != ""]', 'start'));
1835       $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${CALLERID(number)}'));
1836       $ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}'));
1837
1838       // If this came through a ringgroup or CF, then we want to retain original CID unless
1839       // OUTKEEPCID_${trunknum} is set.
1840       // Save then CIDNAME while it is still intact in case we end up sending out this same CID
1841       $ext->add($context, $exten, '', new ext_gotoif('$["${KEEPCID}" != "TRUE"]', 'normcid'));  // Set to TRUE if coming from ringgroups, CF, etc.
1842       $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTKEEPCID_${ARG1}}" = "xon"]', 'normcid'));
1843       $ext->add($context, $exten, '', new ext_gotoif('$["foo${REALCALLERIDNUM}" = "foo"]', 'normcid'));  // if not set to anything, go through normal processing
1844       $ext->add($context, $exten, '', new ext_set('USEROUTCID', '${REALCALLERIDNUM}'));
1845       //$ext->add($context, $exten, '', new ext_set('REALCALLERIDNAME', '${CALLERID(name)}'));
1846
1847       // 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
1848       <