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

Revision 7893, 137.4 kB (checked in by p_lindheimer, 9 months ago)

Merged revisions 7892 via svnmerge from
http://svn.freepbx.org/modules/branches/2.4

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

r7890 | p_lindheimer | 2009-07-05 10:37:32 -0700 (Sun, 05 Jul 2009) | 1 line


fixes #3744 found a good way to get proper sequences without multiple ugly queries

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

  • 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 // The destinations this module provides
4 // returns a associative arrays with keys 'destination' and 'description'
5 function core_destinations() {
6         //static destinations
7         $extens = array();
8         $category = 'Terminate Call';
9         $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category);
10         $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category);
11         $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category);
12         $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category);
13         $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category);
14        
15         //get the list of meetmes
16         $results = core_users_list();
17        
18         if (isset($results) && function_exists('voicemail_getVoicemail')) {
19                 //get voicemail
20                 $uservm = voicemail_getVoicemail();
21                 $vmcontexts = array_keys($uservm);
22                 foreach ($results as $thisext) {
23                         $extnum = $thisext[0];
24                         // search vm contexts for this extensions mailbox
25                         foreach ($vmcontexts as $vmcontext) {
26                                 if(isset($uservm[$vmcontext][$extnum])){
27                                         //$vmname = $uservm[$vmcontext][$extnum]['name'];
28                                         //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>');
29                                         $vmboxes[$extnum] = true;
30                                 }
31                         }
32                 }
33         }
34        
35         // return an associative array with destination and description
36         // core provides both users and voicemail boxes as destinations
37         if (isset($results)) {
38                 foreach($results as $result) {
39                         $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions');
40                         if(isset($vmboxes[$result['0']])) {
41                                 $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail');
42                                 $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail');
43                                 $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail');
44                         }
45                 }
46         }
47        
48         if (isset($extens))
49                 return $extens;
50         else
51                 return null;
52
53 }
54
55 /*      Generates dialplan for "core" components (extensions & inbound routing)
56         We call this with retrieve_conf
57 */
58 function core_get_config($engine) {
59         global $ext;  // is this the best way to pass this?
60         global $version;  // this is not the best way to pass this, this should be passetd together with $engine
61         global $amp_conf;
62
63         $modulename = "core";
64        
65         switch($engine) {
66                 case "asterisk":
67                         // FeatureCodes
68                         $fcc = new featurecode($modulename, 'userlogon');
69                         $fc_userlogon = $fcc->getCodeActive();
70                         unset($fcc);
71
72                         $fcc = new featurecode($modulename, 'userlogoff');
73                         $fc_userlogoff = $fcc->getCodeActive();
74                         unset($fcc);
75
76                         $fcc = new featurecode($modulename, 'zapbarge');
77                         $fc_zapbarge = $fcc->getCodeActive();
78                         unset($fcc);
79
80                         $fcc = new featurecode($modulename, 'chanspy');
81                         $fc_chanspy = $fcc->getCodeActive();
82                         unset($fcc);
83
84                         $fcc = new featurecode($modulename, 'simu_pstn');
85                         $fc_simu_pstn = $fcc->getCodeActive();
86                         unset($fcc);
87
88                         $fcc = new featurecode($modulename, 'simu_fax');
89                         $fc_simu_fax = $fcc->getCodeActive();
90                         unset($fcc);
91
92                         $fcc = new featurecode($modulename, 'pickup');
93                         $fc_pickup = $fcc->getCodeActive();
94                         unset($fcc);
95
96                         // Log on / off -- all in one context
97                         if ($fc_userlogoff != '' || $fc_userlogon != '') {
98                                 $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal
99                                
100                                 if ($fc_userlogoff != '') {
101                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff'));
102                                         $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup(''));
103                                 }
104        
105                                 if ($fc_userlogon != '') {
106                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon'));
107                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
108                                        
109                                         $clen = strlen($fc_userlogon);
110                                         $fc_userlogon = "_$fc_userlogon.";
111                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}'));
112                                         $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup(''));
113                                 }
114                         }
115
116                         // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial
117                         // when a user pushes a flashing BLF.
118                         if ($fc_pickup != '') {
119                                 $ext->addInclude('from-internal-additional', 'app-pickup');
120                                 $fclen = strlen($fc_pickup);
121                                 $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}'));
122                                 if (strstr($version, 'BRI'))
123                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_dpickup('${EXTEN:'.$fclen.'}'));
124                                 else
125                                         $ext->add('app-pickup', "_$fc_pickup.", '', new ext_pickup('${EXTEN:'.$fclen.'}'));
126                         }
127                        
128                        
129                         // zap barge
130                         if ($fc_zapbarge != '') {
131                                 $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal
132                                
133                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid'));
134                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}'));
135                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer(''));
136                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1));
137                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge(''));
138                                 $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup(''));
139                         }
140
141                         // chan spy
142                         if ($fc_chanspy != '') {
143                                 $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal
144                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid'));
145                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer(''));
146                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1));
147                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy(''));
148                                 $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup(''));
149                         }
150                        
151                         // Simulate options (ext-test)
152                         if ($fc_simu_pstn != '' || $fc_simu_fax != '') {
153                                 $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal
154                                
155                                 if ($fc_simu_pstn != '') {
156                                         $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn'));
157                                 }
158
159                                 if ($fc_simu_fax != '') {
160                                         $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax'));
161                                 }
162
163                                 $ext->add('ext-test', 'h', '', new ext_macro('hangupcall'));
164                         }
165                        
166                         /* Always have Fax detection in ext-did, no matter what */
167                         $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax'));
168
169                         /* inbound routing extensions */
170                         $didlist = core_did_list();
171                         if(is_array($didlist)){
172                                 $catchall = false;
173                                 $catchall_context='ext-did-catchall';
174                                 foreach($didlist as $item) {
175                                         $did = core_did_get($item['extension'],$item['cidnum'],$item['channel']);
176                                         $exten = $did['extension'];
177                                         $cidnum = $did['cidnum'];
178                                         $channel = $did['channel'];
179
180                                         $exten = (empty($exten)?"s":$exten);
181                                         $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it
182
183                                         if (empty($channel))
184                                                 $context = "ext-did";
185                                         else {
186                                                 $context = "macro-from-zaptel-{$channel}";
187                                                 if (!isset($zapchan[$channel])) {
188                                                         // create the macro-from-zaptel-$chan context and load up the
189                                                         // startup settings
190                                                         $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
191                                                         $ext->add($context, 's', '', new ext_noop('Entering '.$context.' with DID = ${DID}'));
192                                                         $zapchan[$channel] = "unfinished";
193                                                 }
194                                         }
195
196                                         // Start inbound processing. Unneeded line to be possibly overridden by something in
197                                         // extensions_custom.conf
198                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
199                                         // always set callerID name
200                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
201                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
202                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
203
204                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
205                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
206                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
207                                         }
208
209                                         // If we require RINGING, signal it as soon as we enter.
210                                         if ($item['ringing'] === "CHECKED") {
211                                                 $ext->add($context, $exten, '', new ext_ringing(''));
212                                         }
213
214                                         if ($exten == "s" && $context == "ext-did") { 
215                                                 //if the exten is s, then also make a catchall for undefined DIDs if it's not a zaptel route
216                                                 $catchaccount = "_X.".(empty($cidnum)?"":"/".$cidnum);
217                                                 if ($catchaccount == "_X.")
218                                                         $catchall = true;
219                                                 $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.'));
220                                                 $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did'));
221                                         }
222                                        
223                                         if ($item['faxexten'] != "default") {
224                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
225                                         }
226                                         if (!empty($item['faxemail'])) {
227                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
228                                         }
229                                         if ($item['answer'] == "1") {
230                                                 $ext->add($context, $exten, '', new ext_answer(''));
231                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
232                                         }
233                                         if ($item['answer'] == "2") { // NVFaxDetect
234                                                 $ext->add($context, $exten, '', new ext_answer(''));
235                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
236                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
237                                         }
238                                         if ($item['privacyman'] == "1") {
239                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
240                                         }
241                                         if (!empty($item['alertinfo'])) {
242                                                 $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo'])));
243                                         }
244                                         // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should
245                                         // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different
246                                         // modules.
247                                         //
248                                         // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here.
249                                         //
250                                         // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX)
251                                         //
252                                         if (!empty($item['grppre'])) {
253                                                 $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre']));
254                                                 $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
255                                         }
256                                        
257                                         // If we're doing a zaptel route, now we need to do the gotos ONLY IF it's the first time round.
258                                         // Except for the fact that this doesn't work. Not at all. Dial returns -1 and hangs up the
259                                         // call. This is fixed in 1.4 with TryExec(), but until then, we can't match on zap
260                                         // _and_ anything else.  When we decide to say 'Only 1.4!' then we can reenable this
261                                         // and use TryExec(Goto..) and then check ${TRYSTATUS} for FAILED or SUCCESS. I didn't
262                                         // bother actually writing that, as the syntax may change.
263                                         //if (isset($zapchan[$channel]) && $zapchan[$channel] == "unfinished") {
264                                         //      $ext->add($context, 's', '', new ext_gotoif('$[ "${DID}" = "s" ]', 'nos', 'sok'));
265                                         //      $ext->add($context, 's', 'nos', new ext_noop('Skipping ${DID} because it is s'));
266                                         //      $ext->add($context, 's', '', new ext_goto("trycid"));
267                                         //      $ext->add($context, 's', 'sok', new ext_noop('Trying ${DID}'));
268                                         //      $ext->add($context, 's', '', new ext_goto("1", '${DID}'));
269                                         //      $ext->add($context, 's', 'trycid', new ext_gotoif('$[ "${CALLERID(num)}" = "" ]', 'nocid', 'cidok'));
270                                         //      $ext->add($context, 's', 'nocid', new ext_noop('Skipping empty CallerID Num'));
271                                         //      $ext->add($context, 's', '', new ext_goto("end"));
272                                         //      $ext->add($context, 's', 'cidok', new ext_noop('Trying ${DID}/${CALLERID(num)}'));
273                                         //      $ext->add($context, 's', '', new ext_goto("1", '${DID}/${CALLERID(num)}'));
274                                         //      $ext->add($context, 's', 'end', new ext_noop('End of macro init'));
275                                                 // Now set $zapchan[$channel] so we don't do this again
276                                                 $zapchan[$channel] = "set";
277                                         //}
278                                         //the goto destination
279                                         // destination field in 'incoming' database is backwards from what ext_goto expects
280                                         $goto_context = strtok($did['destination'],',');
281                                         $goto_exten = strtok(',');
282                                         $goto_pri = strtok(',');
283                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
284                                        
285                                 }
286                                 // If there's not a catchall, make one with an error message
287                                 if (!$catchall) {
288                                         $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match"));
289                                         $ext->add($catchall_context, 's', '', new ext_answer(''));
290                                         $ext->add($catchall_context, 's', '', new ext_wait('2'));
291                                         $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice'));
292                                         $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}'));
293                                         $ext->add($catchall_context, '_[*#X].', '', new ext_setvar('__FROM_DID', '${EXTEN}'));
294                                         $ext->add($catchall_context, '_[*#X].', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}'));
295                                         $ext->add($catchall_context, '_[*#X].', '', new ext_goto('1','s','ext-did'));
296                                 }
297                                        
298                         }
299
300                         /* MODIFIED (PL)
301                          *
302                          * Add Direct DIDs
303                          *
304                          * This functions creates a new context, ext-did-direct, used to route an incoming DID directly to the specified user.
305                          * The purpose is to use when a user has a personal external DID. This keeps it clean and easy to administer.
306                          * Any conflict with those routes will depend on which of the two contexts are included first in the extensions.conf file.
307                          *
308                          * Calls are sent to context from-did-direct though this feature. You must create that context in extenions.conf or
309                          * in extensions_custom.conf and it should look something like:
310                          *
311                          * [from-did-direct]
312                          * include => ext-findmefollow
313                          * include => ext-local
314                          *
315                          * This is so that personal ring groups are used if they exist for the direct did and if not, then the local extension.
316                          * If the module is not implented, it will just go to the users extension.
317                          */
318
319                         $directdidlist = core_directdid_list();
320                         if(is_array($directdidlist)){
321                                 $context = "ext-did";
322                                 if(!is_array($didlist)){
323                                         /* if not set above, add one here */
324                                         $ext->add($context, 'fax', '', new ext_goto('1','in_fax','ext-fax'));
325                                 }
326                                 foreach($directdidlist as $item) {
327                                         $exten = $item['directdid'];
328                                         $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}'));
329                                         // always set callerID name
330                                         $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok'));
331                                         $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}'));
332                                         $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}'));
333
334                                         if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') {
335                                                 $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass']));
336                                                 $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass']));
337                                         }
338                                        
339                                         if ($item['faxexten'] != "default") {
340                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten']));
341                                         }
342                                         if (!empty($item['faxemail'])) {
343                                                 $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail']));
344                                         }
345                                         if ($item['answer'] == "1") {
346                                                 $ext->add($context, $exten, '', new ext_answer(''));
347                                                 $ext->add($context, $exten, '', new ext_wait($item['wait']));
348                                         }
349                                         if ($item['answer'] == "2") { // NVFaxDetect
350                                                 $ext->add($context, $exten, '', new ext_answer(''));
351                                                 $ext->add($context, $exten, '', new ext_playtones('ring'));
352                                                 $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']));
353                                         }
354                                         if ($item['privacyman'] == "1") {
355                                                 $ext->add($context, $exten, '', new ext_macro('privacy-mgr'));
356                                         }
357
358
359                                         if (!empty($item['didalert'])) {
360                                                 $ext->add($context, $exten, '', new ext_setvar("_ALERT_INFO", str_replace(';', '\;', $item['didalert'])));
361                                         }
362                                         $goto_context = 'from-did-direct';
363                                         $goto_exten = $item['extension'];
364                                         $goto_pri = 1;
365                                         $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
366
367                                 }
368                         }
369
370                        
371                         /* user extensions */
372                         $ext->addInclude('from-internal-additional','ext-local');
373                         $userlist = core_users_list();
374                         if (is_array($userlist)) {
375                                 foreach($userlist as $item) {
376                                         $exten = core_users_get($item[0]);
377                                         $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']);
378
379                                         if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0)
380                                                 $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer']));
381                                        
382                                         $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension']));
383                                         $ext->add('ext-local', $exten['extension'], '', new ext_hangup(''));
384                                        
385                                         if($vm != "novm") {
386                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',"$vm,DIRECTDIAL"));
387                                                 $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_hangup(''));
388                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',"$vm,BUSY"));
389                                                 $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_hangup(''));
390                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',"$vm,NOANSWER"));
391                                                 $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_hangup(''));
392                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',"$vm,NOMESSAGE"));
393                                                 $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_hangup(''));
394                                         }
395                                                
396                                         $hint = core_hint_get($exten['extension']);
397                                         if (!empty($hint))
398                                                 $ext->addHint('ext-local', $exten['extension'], $hint);
399                                         if ($exten['sipname']) {
400                                                 $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal'));
401                                         }
402                                 }
403                         }
404
405                         // create from-trunk context for each trunk that adds counts to channels
406                         //
407                         $trunklist = core_trunks_list(true);
408                         if (is_array($trunklist)) {
409                                 foreach ($trunklist as $trunkprops) {
410                                         if (trim($trunkprops['value']) == 'on') {
411                                                 // value of on is disabled and for zap we don't create a context
412                                                 continue;
413                                         }
414                                         switch ($trunkprops['tech']) {
415                                                 case 'IAX':
416                                                 case 'IAX2':
417                                                 case 'SIP':
418                                                         $trunkgroup = $trunkprops['globalvar'];
419                                                         $trunkcontext  = "from-trunk-".$trunkprops['name'];
420                                                         $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup));
421                                                         $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk'));
422                                                         break;
423                                                 default:
424                                         }
425                                 }
426                         }
427
428                         /* dialplan globals */
429                         // modules should NOT use the globals table to store anything!
430                         // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead
431                         // I'm cheating for core functionality - do as I say, not as I do ;-)           
432
433                         // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table.
434                         //
435                         $amp_conf_globals = array(
436                                 "ASTETCDIR",
437                                 "ASTMODDIR",
438                                 "ASTVARLIBDIR",
439                                 "ASTAGIDIR",
440                                 "ASTSPOOLDIR",
441                                 "ASTRUNDIR",
442                                 "ASTLOGDIR",
443                                 "CWINUSEBUSY",
444                                 "AMPMGRUSER",
445                                 "AMPMGRPASS"
446                         );
447
448                         $sql = "SELECT * FROM globals";
449                         $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
450                         foreach($globals as $global) {
451                                 $ext->addGlobal($global['variable'],$global['value']);
452
453                                 // now if for some reason we have a variable in the global table
454                                 // that is in our $amp_conf_globals list, then remove it so we
455                                 // don't duplicate, the sql table will take precedence
456                                 //
457                                 if (array_key_exists($global['variable'],$amp_conf_globals)) {
458                                         $rm_keys = array_keys($amp_conf_globals,$global['variable']);
459                                         foreach ($rm_keys as $index) {
460                                                 unset($amp_conf_globals[$index]);
461                                         }
462                                 }
463                         }
464                         foreach ($amp_conf_globals as $global) {
465                                 if (isset($amp_conf[$global])) {
466                                         $value = $amp_conf[$global];
467                                         if ($value === true || $value === false) {
468                                                 $value = ($value) ? 'true':'false';
469                                         }
470                                         $ext->addGlobal($global, $value);
471                                         out("Added to globals: $global = $value");
472                                 }
473                         }
474                        
475                         /* outbound routes */
476                         // modules should use their own table for storage (and module_get_config() to add dialplan)
477                         // modules should NOT use the extension table to store anything!
478                         $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application";
479                         $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
480                         $ext->addInclude('from-internal-additional','outbound-allroutes');
481                         $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar'));
482                         foreach($outrts as $outrt) {
483                                 $ext->addInclude('outbound-allroutes',$outrt['application']);
484                                 $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC";
485                                 $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
486                                 foreach($thisrt as $exten) {
487                                         //if emergencyroute, then set channel var
488                                         if(strpos($exten['args'],"EMERGENCYROUTE") !== false)
489                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15)));
490                                         if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false)
491                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18)));
492                                         // Don't set MOHCLASS if already set, threre may be a feature code that overrode it
493                                         if(strpos($exten['args'],"MOHCLASS") !== false)
494                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' ));
495                                         if(strpos($exten['args'],"dialout-trunk") !== false)
496                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
497                                         if(strpos($exten['args'],"dialout-enum") !== false)
498                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args']));
499                                         if(strpos($exten['args'],"outisbusy") !== false)
500                                                 $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy"));
501                                 }
502                         }
503                         general_generate_indications();
504
505                         // "blackhole" destinations
506                         $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup'));
507                         $ext->add('app-blackhole', 'hangup', '', new ext_hangup());
508
509                         $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone'));
510                         $ext->add('app-blackhole', 'zapateller', '', new ext_answer());
511                         $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller());
512                         // Should hangup ?
513                         // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup());
514                                        
515                         $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever'));
516                         $ext->add('app-blackhole', 'musiconhold', '', new ext_answer());
517                         $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold());
518
519                         $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion'));
520                         $ext->add('app-blackhole', 'congestion', '', new ext_answer());
521                         $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion'));
522                         $ext->add('app-blackhole', 'congestion', '', new ext_congestion());
523                         $ext->add('app-blackhole', 'congestion', '', new ext_hangup());
524
525                         $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy'));
526                         $ext->add('app-blackhole', 'busy', '', new ext_answer());
527                         $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy'));
528                         $ext->add('app-blackhole', 'busy', '', new ext_busy());
529                         $ext->add('app-blackhole', 'busy', '', new ext_hangup());
530
531                         if ($amp_conf['AMPBADNUMBER'] !== false) {
532                                 $context = 'bad-number';
533                                 $exten = '_X.';
534                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
535                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
536                                 $ext->add($context, $exten, '', new ext_wait('1'));
537                                 $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
538                                 $ext->add($context, $exten, '', new ext_wait('1'));
539                                 $ext->add($context, $exten, '', new ext_congestion('20'));
540                                 $ext->add($context, $exten, '', new ext_hangup());
541
542                                 $exten = '_*.';
543                                 $ext->add($context, $exten, '', new extension('ResetCDR()'));
544                                 $ext->add($context, $exten, '', new extension('NoCDR()'));
545                                 $ext->add($context, $exten, '', new ext_wait('1'));
546                                 $ext->add($context, $exten, '', new ext_playback('silence/1&feature-not-avail-line&silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer'));
547                                 $ext->add($context, $exten, '', new ext_wait('1'));
548                                 $ext->add($context, $exten, '', new ext_congestion('20'));
549                                 $ext->add($context, $exten, '', new ext_hangup());
550                         }
551
552                 break;
553         }
554 }
555
556
557
558
559
560
561
562
563
564
565
566 /* begin page.ampusers.php functions */
567
568 function core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections) {
569         $sql = "INSERT INTO ampusers (username, password, extension_low, extension_high, deptname, sections) VALUES (";
570         $sql .= "'".$username."',";
571         $sql .= "'".$password."',";
572         $sql .= "'".$extension_low."',";
573         $sql .= "'".$extension_high."',";
574         $sql .= "'".$deptname."',";
575         $sql .= "'".implode(";",$sections)."');";
576        
577         sql($sql,"query");
578 }
579
580 function core_ampusers_del($username) {
581         $sql = "DELETE FROM ampusers WHERE username = '".$username."'";
582         sql($sql,"query");
583 }
584
585 function core_ampusers_list() {
586         $sql = "SELECT username FROM ampusers ORDER BY username";
587         return sql($sql,"getAll");
588 }
589
590 /* end page.ampusers.php functions */
591
592
593
594
595
596
597
598
599
600 /* begin page.did.php functions */
601
602 function core_did_list($order='extension'){
603         switch ($order) {
604                 case 'description':
605                         $sql = "SELECT * FROM incoming ORDER BY description,extension,cidnum";
606                         break;
607                 case 'extension':
608                 default:
609                         $sql = "SELECT * FROM incoming ORDER BY extension,cidnum";
610         }
611         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
612 }
613
614 function core_did_get($extension="",$cidnum="",$channel=""){
615         $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\" AND channel = \"$channel\"";
616         return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
617 }
618
619 function core_did_del($extension,$cidnum, $channel){
620         $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\" AND channel = \"$channel\"";
621         sql($sql);
622 }
623
624 function core_did_edit($old_extension,$old_cidnum, $old_channel, $incoming){
625
626         $old_extension = addslashes(trim($old_extension));
627         $old_cidnum = addslashes(trim($old_cidnum));
628         $old_channel = addslashes(trim($old_channel));
629
630         $incoming['extension'] = trim($incoming['extension']);
631         $incoming['cidnum'] = trim($incoming['cidnum']);
632         $incoming['channel'] = trim($incoming['channel']);
633
634         $extension = addslashes($incoming['extension']);
635         $cidnum = addslashes($incoming['cidnum']);
636         $channel = addslashes($incoming['channel']);
637
638         // if did or cid changed, then check to make sure that this pair is not already being used.
639         //
640         if (($extension != $old_extension) || ($cidnum != $old_cidnum)) {
641                 $existing=core_did_get($extension,$cidnum,$channel);
642                 if (empty($existing) && (trim($cidnum) == "")) {
643                         $existing_directdid = core_users_directdid_get($extension);
644                 } else {
645                         $existing_directdid = "";
646                 }
647         } else {
648                 $existing = $existing_directdid = "";
649         }
650
651         if (empty($existing) && empty($existing_directdid)) {
652                 core_did_del($old_extension,$old_cidnum,$old_channel);
653                 core_did_add($incoming);
654                 return true;
655         } else {
656                 if (!empty($existing)) {
657                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
658                 } else {
659                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
660                 }
661                 return false;
662         }
663 }
664
665 function core_did_add($incoming){
666         foreach ($incoming as $key => $val) { ${$key} = addslashes($val); } // create variables from request
667
668         // Check to make sure the did is not being used elsewhere
669         //
670         $existing=core_did_get($extension,$cidnum,$channel);
671         if (empty($existing) && (trim($cidnum) == "")) {
672                 $existing_directdid = core_users_directdid_get($extension);
673         } else {
674                 $existing_directdid = "";
675         }
676
677         if (empty($existing) && empty($existing_directdid)) {
678                 $destination=${$goto0.'0'};
679                 $sql="INSERT INTO incoming (cidnum,extension,destination,faxexten,faxemail,answer,wait,privacyman,alertinfo, channel, ringing, mohclass, description, grppre) values ('$cidnum','$extension','$destination','$faxexten','$faxemail','$answer','$wait','$privacyman','$alertinfo', '$channel', '$ringing', '$mohclass', '$description', '$grppre')";
680                 sql($sql);
681                 return true;
682         } else {
683                 if (!empty($existing)) {
684                         echo "<script>javascript:alert('"._("A route for this DID/CID already exists!")." => ".$existing['extension']."/".$existing['cidnum']."')</script>";
685                 } else {
686                         echo "<script>javascript:alert('"._("A directdid for this DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
687                 }
688                 return false;
689         }
690 }
691
692 /* end page.did.php functions */
693
694
695
696
697
698
699
700 /* begin page.devices.php functions */
701
702 //get the existing devices
703 function core_devices_list($tech="all") {
704         $sql = "SELECT id,description FROM devices";
705         switch (strtoupper($tech)) {
706                 case "IAX":
707                         $sql .= " WHERE tech = 'iax2'";
708                         break;
709                 case "IAX2":
710                 case "SIP":
711                 case "ZAP":
712                         $sql .= " WHERE tech = '".strtolower($tech)."'";
713                         break;
714                 case "ALL":
715                 default:
716         }
717         $sql .= ' ORDER BY id';
718         $results = sql($sql,"getAll");
719
720         foreach($results as $result){
721                 if (checkRange($result[0])){
722                         $extens[] = array(
723                                 0=>$result[0],  // for backwards compatibility
724                                 1=>$result[1],
725                                 'id'=>$result[0], // FETCHMODE_ASSOC emulation
726                                 'description'=>$result[1],
727                         );
728                 }
729         }
730         if (isset($extens)) {
731                 return $extens;
732         } else {
733                 return null;
734         }
735 }
736
737
738 function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){
739         global $amp_conf;
740         global $currentFile;
741         global $astman;
742
743         $display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
744
745         if (trim($id) == '' ) {
746                 if ($display != 'extensions') {
747                         echo "<script>javascript:alert('"._("You must put in a device id")."');</script>";
748                 }
749                 return false;
750         }
751        
752         //ensure this id is not already in use
753         $devices = core_devices_list();
754         if (is_array($devices)) {
755                 foreach($devices as $device) {
756                         if ($device[0] === $id) {
757                                 if ($display <> 'extensions') echo "<script>javascript:alert('"._("This device id is already in use")."');</script>";
758                                 return false;
759                         }
760                 }
761         }
762         //unless defined, $dial is TECH/id
763         if ( $dial == '' ) {
764                 //zap is an exception
765                 if ( strtolower($tech) == "zap" ) {
766                         $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
767                         $dial = 'ZAP/'.$zapchan;
768                 } else {
769                         $dial = strtoupper($tech)."/".$id;
770                 }
771         }
772        
773         //check to see if we are requesting a new user
774         if ($user == "new") {
775                 $user = $id;
776                 $jump = true;
777         }
778        
779         if(!get_magic_quotes_gpc()) {
780                 if(!empty($emergency_cid))
781                         $emergency_cid = addslashes($emergency_cid);
782                 if(!empty($description))
783                         $description = addslashes($description);
784         }
785        
786         //insert into devices table
787         $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")";
788         sql($sql);
789        
790         //add details to astdb
791         if ($astman) {
792                 // if adding or editting a fixed device, user property should always be set
793                 if ($devicetype == 'fixed' || !$editmode) {
794                         $astman->database_put("DEVICE",$id."/user",$user);
795                 }
796                 // If changing from a fixed to an adhoc, the user property should be intialized
797                 // to the new default, not remain as the previous fixed user
798                 if ($editmode) {
799                         $previous_type = $astman->database_get("DEVICE",$id."/type");
800                         if ($previous_type == 'fixed' && $devicetype == 'adhoc') {
801                                 $astman->database_put("DEVICE",$id."/user",$user);
802                         }
803                 }
804                 $astman->database_put("DEVICE",$id."/dial",$dial);
805                 $astman->database_put("DEVICE",$id."/type",$devicetype);
806                 $astman->database_put("DEVICE",$id."/default_user",$user);
807                 if(!empty($emergency_cid)) {
808                         $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\"");
809                 }
810
811                 if ($user != "none") {
812                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
813                         if (empty($existingdevices)) {
814                                 $astman->database_put("AMPUSER",$user."/device",$id);
815                         } else {
816                                 $existingdevices_array = explode('&',$existingdevices);
817                                 if (!in_array($id, $existingdevices_array)) {
818                                         $existingdevices_array[]=$id;
819                                         $existingdevices = implode('&',$existingdevices_array);
820                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices);
821                                 }
822                         }
823                 }
824
825         } else {
826                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
827         }
828        
829         // create a voicemail symlink if needed
830         $thisUser = core_users_get($user);
831         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
832                 if(empty($thisUser['voicemail']))
833                         $vmcontext = "default";
834                 else
835                         $vmcontext = $thisUser['voicemail'];
836                
837                 //voicemail symlink
838                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
839                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
840         }
841                
842         //take care of sip/iax/zap config
843         $funct = "core_devices_add".strtolower($tech);
844         if(function_exists($funct)){
845                 $funct($id);
846         }
847        
848 /*      if($user != "none") {
849                 core_hint_add($user);
850         }*/
851        
852         //if we are requesting a new user, let's jump to users.php
853         if (isset($jump)) {
854                 echo("<script language=\"JavaScript\">window.location=\"config.php?display=users&extdisplay={$id}&name={$description}\";</script>");
855         }
856         return true;
857 }
858
859 function core_devices_del($account,$editmode=false){
860         global $amp_conf;
861         global $currentFile;
862         global $astman;
863        
864         //get all info about device
865         $devinfo = core_devices_get($account);
866        
867         //delete details to astdb
868         if ($astman) {
869                 // If a user was selected, remove this device from the user
870                 $deviceuser = $astman->database_get("DEVICE",$account."/user");
871                 if (isset($deviceuser) && $deviceuser != "none") {
872                         // Remove the device record from the user's device list
873                         $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device");
874
875                         // We need to remove just this user and leave the rest alone
876                         $userdevicesarr = explode("&", $userdevices);
877                         $userdevicesarr_hash = array_flip($userdevicesarr);
878                         unset($userdevicesarr_hash[$account]);
879                         $userdevicesarr = array_flip($userdevicesarr_hash);
880                         $userdevices = implode("&", $userdevicesarr);
881                        
882                         if (empty($userdevices)) {
883                                         $astman->database_del("AMPUSER",$deviceuser."/device");
884                         } else {
885                                         $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices);
886                         }
887                 }
888                 if (! $editmode) {
889                         $astman->database_del("DEVICE",$account."/dial");
890                         $astman->database_del("DEVICE",$account."/type");
891                         $astman->database_del("DEVICE",$account."/user");
892                         $astman->database_del("DEVICE",$account."/default_user");
893                         $astman->database_del("DEVICE",$account."/emergency_cid");
894                 }
895
896                 //delete from devices table
897                 $sql="DELETE FROM devices WHERE id = \"$account\"";
898                 sql($sql);
899
900                 //voicemail symlink
901                 exec("rm -f /var/spool/asterisk/voicemail/device/".$account);
902         } else {
903                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
904         }
905        
906         //take care of sip/iax/zap config
907         $funct = "core_devices_del".strtolower($devinfo['tech']);
908         if(function_exists($funct)){
909                 $funct($account);
910         }
911 }
912
913 function core_devices_get($account){
914         //get all the variables for the meetme
915         $sql = "SELECT * FROM devices WHERE id = '$account'";
916         $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC);
917        
918         //take care of sip/iax/zap config
919         $funct = "core_devices_get".strtolower($results['tech']);
920         if (!empty($results['tech']) && function_exists($funct)) {
921                 $devtech = $funct($account);
922                 if (is_array($devtech)){
923                         $results = array_merge($results,$devtech);
924                 }
925         }
926        
927         return $results;
928 }
929
930 // this function rebuilds the astdb based on device table contents
931 // used on devices.php if action=resetall
932 function core_devices2astdb(){
933         global $astman;
934         global $amp_conf;
935
936         $sql = "SELECT * FROM devices";
937         $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
938
939         //add details to astdb
940         if ($astman) {
941                 $astman->database_deltree("DEVICE");
942                 foreach ($devresults as $dev) {
943                         extract($dev); 
944                         $astman->database_put("DEVICE",$id."/dial",$dial);
945                         $astman->database_put("DEVICE",$id."/type",$devicetype);
946                         $astman->database_put("DEVICE",$id."/user",$user);             
947                         // If a user is selected, add this device to the user
948                         if ($user != "none") {
949                                         $existingdevices = $astman->database_get("AMPUSER",$user."/device");
950                                         if (!empty($existingdevices)) {
951                                                         $existingdevices .= "&";
952                                         }
953                                         $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id);
954                         }
955                        
956                         // create a voicemail symlink if needed
957                         $thisUser = core_users_get($user);
958                         if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) {
959                                 if(empty($thisUser['voicemail']))
960                                         $vmcontext = "default";
961                                 else
962                                         $vmcontext = $thisUser['voicemail'];
963                                 //voicemail symlink
964                                 exec("rm -f /var/spool/asterisk/voicemail/device/".$id);
965                                 exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id);
966                         }
967                 }
968                 return true;
969         } else {
970                 return false;
971         }
972 }
973
974 // this function rebuilds the astdb based on users table contents
975 // used on devices.php if action=resetall
976 function core_users2astdb(){
977         global $amp_conf;
978         global $astman;
979
980         $sql = "SELECT * FROM users";
981         $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
982        
983         //add details to astdb
984         if ($astman) {
985                 foreach($userresults as $usr) {
986                         extract($usr);
987                         $astman->database_put("AMPUSER",$extension."/password",$password);
988                         $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer);
989                         $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer);
990                         $astman->database_put("AMPUSER",$extension."/recording",$recording);
991                         $astman->database_put("AMPUSER",$extension."/outboundcid","\"".addslashes($outboundcid)."\"");
992                         $astman->database_put("AMPUSER",$extension."/cidname","\"".addslashes($name)."\"");
993                         $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\"");
994                 }       
995                 return true;
996         } else {
997                 return false;
998         }
999
1000 //      TODO: this was...       
1001 //      return $astman->disconnect();
1002 //      is "true" the correct value...?
1003 }
1004
1005 //add to sip table
1006 function core_devices_addsip($account) {
1007         global $db;
1008         global $currentFile;
1009
1010         foreach ($_REQUEST as $req=>$data) {
1011                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1012                         $keyword = substr($req, 8);
1013                         if ( $keyword == 'dial' && $data == '' ) {
1014                                 $sipfields[] = array($account, $keyword, 'SIP/'.$account);
1015                         } elseif ($keyword == 'mailbox' && $data == '') {
1016                                 $sipfields[] = array($account,'mailbox',$account.'@device');
1017                         } else {
1018                                 $sipfields[] = array($account, $keyword, $data);
1019                         }
1020                 }
1021         }
1022        
1023         if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why !
1024                 $sipfields = array(
1025                         //array($account,'account',$account),
1026                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1027                         array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''),
1028                         array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'),
1029                         array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'),
1030                         array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''),
1031                         array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'),
1032                         array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'),
1033                         array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'),
1034                         array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account),
1035                         array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'),
1036                         array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'),
1037                         array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'),
1038                         array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''),
1039                         array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''),
1040                         array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''),
1041                         array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'')
1042                         //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'),
1043                         //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'),
1044                         //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1045                 );
1046         }
1047
1048         // Very bad
1049         $sipfields[] = array($account,'account',$account);     
1050         $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1051        
1052         // Where is this in the interface ??????
1053         $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1054         $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1055
1056         $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)');
1057         $result = $db->executeMultiple($compiled,$sipfields);
1058         if(DB::IsError($result)) {
1059                 die_freepbx($result->getDebugInfo()."<br><br>".'error adding to SIP table');   
1060         }
1061 }
1062
1063 function core_devices_delsip($account) {
1064         global $db;
1065         global $currentFile;
1066        
1067         $sql = "DELETE FROM sip WHERE id = '$account'";
1068         $result = $db->query($sql);
1069        
1070         if(DB::IsError($result)) {
1071                 die_freepbx($result->getMessage().$sql);
1072         }
1073 }
1074
1075 function core_devices_getsip($account) {
1076         global $db;
1077         $sql = "SELECT keyword,data FROM sip WHERE id = '$account'";
1078         $results = $db->getAssoc($sql);
1079         if(DB::IsError($results)) {
1080                 $results = null;
1081         }
1082        
1083         return $results;
1084 }
1085
1086 //add to iax table
1087 function core_devices_addiax2($account) {
1088         global $db;
1089         global $currentFile;
1090        
1091         foreach ($_REQUEST as $req=>$data) {
1092                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1093                         $keyword = substr($req, 8);
1094                         if ( $keyword == 'dial' && $data == '' ) {
1095                                 $iaxfields[] = array($account, $keyword, 'IAX2/'.$account);
1096                         } elseif ($keyword == 'mailbox' && $data == '') {
1097                                 $iaxfields[] = array($account,'mailbox',$account.'@device');
1098                         } else {
1099                                 $iaxfields[] = array($account, $keyword, $data);
1100                         }
1101                 }
1102         }
1103        
1104         if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why !
1105                 $iaxfields = array(
1106                         //array($account,'account',$account),
1107                         array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''),
1108                         array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'),
1109                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1110                         array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'),
1111                         array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'),
1112                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1113                         array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account),
1114                         array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'),
1115                         array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'),
1116                         array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''),
1117                         array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''),
1118                         array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'')
1119                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),
1120                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1121                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>')
1122                 );
1123         }
1124
1125         // Very bad
1126         $iaxfields[] = array($account,'account',$account);     
1127         $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1128         // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID
1129         // set in iax.conf. As we rely on this for pretty much everything, we need to specify the
1130         // callerid as a variable which gets picked up in macro-callerid.
1131         // Ref - http://bugs.digium.com/view.php?id=456
1132         $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account");
1133        
1134         // Where is this in the interface ??????
1135         $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1136         $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1137        
1138         $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)');
1139         $result = $db->executeMultiple($compiled,$iaxfields);
1140         if(DB::IsError($result)) {
1141                 die_freepbx($result->getMessage()."<br><br>error adding to IAX table");
1142         }
1143 }
1144
1145 function core_devices_deliax2($account) {
1146         global $db;
1147         global $currentFile;
1148        
1149         $sql = "DELETE FROM iax WHERE id = '$account'";
1150         $result = $db->query($sql);
1151        
1152         if(DB::IsError($result)) {
1153                 die_freepbx($result->getMessage().$sql);
1154         }
1155 }
1156
1157 function core_devices_getiax2($account) {
1158         global $db;
1159         $sql = "SELECT keyword,data FROM iax WHERE id = '$account'";
1160         $results = $db->getAssoc($sql);
1161         if(DB::IsError($results)) {
1162                 $results = null;
1163         }
1164        
1165         return $results;
1166 }
1167
1168 function core_devices_addzap($account) {
1169         global $db;
1170         global $currentFile;
1171        
1172         foreach ($_REQUEST as $req=>$data) {
1173                 if ( substr($req, 0, 8) == 'devinfo_' ) {
1174                         $keyword = substr($req, 8);
1175                         if ( $keyword == 'dial' && $data == '' ) {
1176                                 $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel'];
1177                                 $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan);
1178                         } elseif ($keyword == 'mailbox' && $data == '') {
1179                                 $zapfields[] = array($account,'mailbox',$account.'@device');
1180                         } else {
1181                                 $zapfields[] = array($account, $keyword, $data);
1182                         }
1183                 }
1184         }
1185        
1186         if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why !
1187                 $zapfields = array(
1188                         //array($account,'account',$account),
1189                         array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'),
1190                         array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'),
1191                         //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'),
1192                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),
1193                         array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'),
1194                         array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'),
1195                         array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'),
1196                         array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'),       
1197                         array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'),
1198                         array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'),
1199                         array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'),
1200                         array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'),
1201                         //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'),     
1202                         //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'),
1203                         array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''),
1204                         array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'')
1205                 );
1206         }
1207
1208         // Very bad
1209         $zapfields[] = array($account,'account',$account);     
1210         $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>');
1211        
1212         // Where is this in the interface ??????
1213         $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand');
1214         $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand');
1215
1216         $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)');
1217         $result = $db->executeMultiple($compiled,$zapfields);
1218         if(DB::IsError($result)) {
1219                 die_freepbx($result->getMessage()."<br><br>error adding to ZAP table");
1220         }
1221 }
1222
1223 function core_devices_delzap($account) {
1224         global $db;
1225         global $currentFile;
1226        
1227         $sql = "DELETE FROM zap WHERE id = '$account'";
1228         $result = $db->query($sql);
1229         if(DB::IsError($result)) {
1230                 die_freepbx($result->getMessage().$sql);
1231         }
1232 }
1233
1234 function core_devices_getzap($account) {
1235         global $db;
1236         $sql = "SELECT keyword,data FROM zap WHERE id = '$account'";
1237         $results = $db->getAssoc($sql);
1238         if(DB::IsError($results)) {
1239                 $results = null;
1240         }
1241         return $results;
1242 }
1243 /* end page.devices.php functions */
1244
1245
1246
1247
1248 function core_hint_get($account){
1249         //determine what devices this user is associated with
1250         $sql = "SELECT dial from devices where user = '{$account}'";
1251         $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1252         //print_r($results);
1253        
1254         //create an array of strings
1255         if (is_array($results)){
1256                 foreach ($results as $result) {
1257                         $dial[] = $result['dial'];
1258                 }
1259         }
1260        
1261         //create a string with & delimiter
1262         if (isset($dial) && is_array($dial)){
1263                 $hint = implode($dial,"&");
1264         } else {
1265                 if (isset($results[0]['dial'])) {
1266                         $hint = $results[0]['dial'];
1267                 } else {
1268                         $hint = null;
1269                 }
1270         }
1271        
1272         return $hint;
1273 }
1274
1275
1276
1277 /* begin page.users.php functions */
1278
1279 // get the existing extensions
1280 // the returned arrays contain [0]:extension [1]:name
1281 function core_users_list() {
1282         $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll");
1283
1284         //only allow extensions that are within administrator's allowed range
1285         foreach($results as $result){
1286                 if (checkRange($result[0])){
1287                         $extens[] = array($result[0],$result[1]);
1288                 }
1289         }
1290        
1291         if (isset($extens)) {
1292                 sort($extens);
1293                 return $extens;
1294         } else {
1295                 return null;
1296         }
1297 }
1298
1299 function core_sipname_check($sipname, $extension) {
1300         global $db;
1301         if (!isset($sipname) || trim($sipname)=='')
1302                 return true;
1303
1304         $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'";
1305         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1306         if(DB::IsError($results)) {
1307         die_freepbx($results->getMessage().$sql);
1308         }
1309        
1310         if (isset($results['sipname']) && trim($results['sipname']) == $sipname)
1311                 return false;
1312         else
1313                 return true;
1314 }
1315
1316 function core_users_add($vars) {
1317         extract($vars);
1318        
1319         global $db;
1320         global $amp_conf;
1321         global $astman;
1322
1323         $thisexten = isset($thisexten) ? $thisexten : '';
1324
1325         if (trim($extension) == '' ) {
1326                 echo "<script>javascript:alert('"._("You must put in an extension (or user) number")."');</script>";
1327                 return false;
1328         }
1329
1330         //ensure this id is not already in use
1331         $extens = core_users_list();
1332         if(is_array($extens)) {
1333                 foreach($extens as $exten) {
1334                         if ($exten[0]===$extension) {
1335                                 echo "<script>javascript:alert('".sprintf(_("This user/extension %s is already in use"),$extension)."');</script>";
1336                                 return false;
1337                         }
1338                 }
1339         }
1340
1341         // clean and check the did to make sure it is not being used by another extension or in did routing
1342         //
1343         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1344         if (trim($directdid) != "") {
1345                 $existing=core_did_get($directdid,"","");
1346                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1347                 if (!empty($existing) || !empty($existing_directdid)) {
1348                         if (!empty($existing)) {
1349                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1350                         } else {
1351                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1352                         }
1353                         return false;
1354                 }
1355         }
1356
1357         $sipname = preg_replace("/\s/" ,"", trim($sipname));
1358         if (! core_sipname_check($sipname, $extension)) {
1359                 echo "<script>javascript:alert('"._("This sipname: {$sipname} is already in use")."');</script>";
1360                 return false;
1361         }
1362        
1363         //build the recording variable
1364         $recording = "out=".$record_out."|in=".$record_in;
1365        
1366         //escape quotes and any other bad chars:
1367         if(!get_magic_quotes_gpc()) {
1368                 $outboundcid = addslashes($outboundcid);
1369                 $name = addslashes($name);
1370         }
1371
1372         //if voicemail is enabled, set the box@context to use
1373         //havn't checked but why is voicemail needed on users anyway?  Doesn't exactly make it modular !
1374         if ( function_exists('voicemail_mailbox_get') ) {
1375                 $vmbox = voicemail_mailbox_get($extension);
1376                 if ( $vmbox == null ) {
1377                         $voicemail = "novm";
1378                         $vmx_state = "false";
1379                 } else {
1380                         $voicemail = $vmbox['vmcontext'];
1381                 }
1382         }
1383
1384         // MODIFICATION: (PL)
1385         // Added for directdid and didalert l for Alert Info distinctive ring)
1386         //
1387         // cleanup any non dial pattern characters prior to inserting into the database
1388         // then add directdid to the insert command.
1389         //
1390         // Clean replace any <> with () in display name - should have javascript stopping this but ...
1391         //
1392         $name = preg_replace(array('/</','/>/'), array('(',')'), trim($name));
1393        
1394         //insert into users table
1395         $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,directdid,didalert,faxexten,faxemail,answer,wait,privacyman,mohclass,sipname) values (\"";
1396         $sql.= "$extension\", \"";
1397         $sql.= isset($password)?$password:'';
1398         $sql.= "\", \"";
1399         $sql.= isset($name)?$name:'';
1400         $sql.= "\", \"";
1401         $sql.= isset($voicemail)?$voicemail:'default';
1402         $sql.= "\", \"";
1403         $sql.= isset($ringtimer)?$ringtimer:'';
1404         $sql.= "\", \"";
1405         $sql.= isset($noanswer)?$noanswer:'';
1406         $sql.= "\", \"";
1407         $sql.= isset($recording)?$recording:'';
1408         $sql.= "\", \"";
1409         $sql.= isset($outboundcid)?$outboundcid:'';
1410         $sql.= "\", \"";
1411         $sql.= isset($directdid)?$directdid:'';
1412         $sql.= "\", \"";
1413         $sql.= isset($didalert)?$didalert:'';
1414
1415         $sql.= "\", \"";
1416         $sql.= isset($faxexten)?$faxexten:'';
1417         $sql.= "\", \"";
1418         $sql.= isset($faxemail)?$faxemail:'';
1419         $sql.= "\", \"";
1420         $sql.= isset($answer)?$answer:'';
1421         $sql.= "\", \"";
1422         $sql.= isset($wait)?$wait:'';
1423         $sql.= "\", \"";
1424         $sql.= isset($privacyman)?$privacyman:'';
1425         $sql.= "\", \"";
1426         $sql.= isset($mohclass)?$mohclass:'';
1427         $sql.= "\", \"";
1428         $sql.= isset($sipname)?$sipname:'';
1429         $sql.= "\")";
1430         sql($sql);
1431
1432         //write to astdb
1433         if ($astman) {
1434                 $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension;
1435                 $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:'');
1436                 $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:'');
1437                 $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:'');
1438                 $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:'');
1439                 $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":'');
1440                 $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":'');
1441                 $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade);
1442                 $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\"");
1443                 $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\"");
1444
1445                 if (trim($callwaiting) == 'enabled') {
1446                         $astman->database_put("CW",$extension,"\"ENABLED\"");
1447                 } else if (trim($callwaiting) == 'disabled') {
1448                         $astman->database_del("CW",$extension);
1449                 } else {
1450                         echo "ERROR: this state should not exist<br>";
1451                 }
1452
1453                 if ($vmx_state && $voicemail != "novm") {
1454
1455                         $unavail_mode="enabled";
1456                         $busy_mode="disabled";
1457                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1458
1459                         if (trim($vmx_state) == 'blocked') {
1460
1461                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "$unavail_mode");
1462                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "$busy_mode");
1463
1464                         } elseif (trim($vmx_state) != 'enabled' && trim($vmx_state) != 'disabled') {
1465
1466                                 $repeat="1";
1467                                 $timeout="2";
1468                                 $vmxopts_timeout="";
1469                                 $loops="1";
1470
1471                                 $mode="unavail";
1472                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$unavail_mode");
1473                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1474                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1475                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1476                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1477
1478                                 $mode="busy";
1479                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/state", "$busy_mode");
1480                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/repeat", "$repeat");
1481                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/timeout", "$timeout");
1482                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/vmxopts/timeout", "$vmxopts_timeout");
1483                                 $astman->database_put("AMPUSER", "$extension/vmx/$mode/loops", "$loops");
1484                                
1485                         }
1486                 } else {
1487                         $vmx_state=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1488                         if (trim($vmx_state) == 'enabled' || trim($vmx_state) == 'disabled' || trim($vmx_state) == 'blocked') {
1489                                 $astman->database_put("AMPUSER", "$extension/vmx/unavail/state", "blocked");
1490                                 $astman->database_put("AMPUSER", "$extension/vmx/busy/state", "blocked");
1491                         }
1492                 }
1493         } else {
1494                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1495         }
1496         return true;
1497 }
1498
1499 function core_users_get($extension){
1500         global $db;
1501         global $amp_conf;
1502         global $astman;
1503         //get all the variables for the meetme
1504         $sql = "SELECT * FROM users WHERE extension = '$extension'";
1505         $results = $db->getRow($sql,DB_FETCHMODE_ASSOC);
1506         if(DB::IsError($results)) {
1507                 die_freepbx($results->getMessage().$sql);
1508         }
1509        
1510         //explode recording vars
1511         $recording = explode("|",$results['recording']);
1512         if (isset($recording[1])) {
1513                 $recout = substr($recording[0],4);
1514                 $recin = substr($recording[1],3);
1515                 $results['record_in']=$recin;
1516                 $results['record_out']=$recout;
1517         } else {
1518                 $results['record_in']='Adhoc';
1519                 $results['record_out']='Adhoc';
1520         }
1521         if ($astman) {
1522                 $cw = $astman->database_get("CW",$extension);
1523                 $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled';
1524                 $results['vmx_state']=$astman->database_get("AMPUSER",$extension."/vmx/unavail/state");
1525                 $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum");
1526                 $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension;
1527         } else {
1528                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1529         }
1530
1531         return $results;
1532 }
1533
1534 function core_users_del($extension){
1535         global $db;
1536         global $amp_conf;
1537         global $astman;
1538        
1539         //delete from devices table
1540         $sql="DELETE FROM users WHERE extension = \"$extension\"";
1541         $results = $db->query($sql);
1542         if(DB::IsError($results)) {
1543                 die_freepbx($results->getMessage().$sql);
1544         }
1545
1546         //delete details to astdb
1547         if ($astman) {
1548                 $astman->database_del("AMPUSER",$extension."/password");
1549                 $astman->database_del("AMPUSER",$extension."/ringtimer");
1550                 $astman->database_del("AMPUSER",$extension."/noanswer");
1551                 $astman->database_del("AMPUSER",$extension."/recording");
1552                 $astman->database_del("AMPUSER",$extension."/outboundcid");
1553                 $astman->database_del("AMPUSER",$extension."/cidname");
1554                 $astman->database_del("AMPUSER",$extension."/cidnum");
1555                 $astman->database_del("AMPUSER",$extension."/voicemail");
1556                 $astman->database_del("AMPUSER",$extension."/device");
1557         } else {
1558                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1559         }
1560 }
1561
1562 function core_users_directdid_get($directdid=""){
1563         if (empty($directdid)) {
1564                 return array();
1565         } else {
1566                 $sql = "SELECT * FROM users WHERE directdid = \"$directdid\"";
1567                 return sql($sql,"getRow",DB_FETCHMODE_ASSOC);
1568         }
1569 }
1570
1571 function core_users_cleanastdb($extension) {
1572         // This is called to remove any ASTDB traces of the user after a deletion. Otherwise,
1573         // call forwarding, call waiting settings could hang around and bite someone if they
1574         // recycle an extension. Is called from page.xtns and page.users.
1575         global $amp_conf;
1576         global $astman;
1577
1578         if ($astman) {
1579                 $astman->database_del("CW",$extension);
1580                 $astman->database_del("CF",$extension);
1581                 $astman->database_del("CFB",$extension);
1582                 $astman->database_del("CFU",$extension);
1583                 $astman->database_deltree("AMPUSER/".$extension."/vmx");
1584
1585         } else {
1586                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1587         }
1588 }
1589
1590 function core_users_edit($extension,$vars){
1591         global $db;
1592         global $amp_conf;
1593         global $astman;
1594        
1595         //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add
1596         if ($astman) {
1597                 $ud = $astman->database_get("AMPUSER",$extension."/device");
1598                 $vars['device'] = $ud;
1599         } else {
1600                 fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1601         }
1602        
1603         $directdid=$vars['directdid'];
1604         $directdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($directdid));
1605         // clean and check the did to make sure it is not being used by another extension or in did routing
1606         //
1607         if (trim($directdid) != "") {
1608                 $existing=core_did_get($directdid,"","");
1609                 $existing_directdid = empty($existing)?core_users_directdid_get($directdid):$existing;
1610                 if (!empty($existing) || (!empty($existing_directdid) && $existing_directdid['extension'] != $extension)) {
1611                         if (!empty($existing)) {
1612                                 echo "<script>javascript:alert('"._("A route with this DID already exists:")." ".$existing['extension']."')</script>";
1613                         } else {
1614                                 echo "<script>javascript:alert('"._("This DID is already associated with extension:")." ".$existing_directdid['extension']." (".$existing_directdid['name'].")')</script>";
1615                         }
1616                         return false;
1617                 }
1618         }
1619
1620         //delete and re-add
1621         if (core_sipname_check($vars['sipname'],$extension)) {
1622                 core_users_del($extension);
1623                 core_users_add($vars);
1624         }
1625         return true;
1626        
1627 }
1628
1629 function core_directdid_list(){
1630         $sql = "SELECT extension, directdid, didalert, mohclass, faxexten, faxemail, answer, wait, privacyman FROM users WHERE directdid IS NOT NULL AND directdid != ''";
1631         return sql($sql,"getAll",DB_FETCHMODE_ASSOC);
1632 }
1633
1634
1635
1636 /* end page.users.php functions */
1637
1638
1639
1640
1641
1642 /* begin page.trunks.php functions */
1643
1644 // we're adding ,don't require a $trunknum
1645 function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1646         global $db;
1647        
1648         // find the next available ID
1649         $trunknum = 1;
1650         foreach(core_trunks_list() as $trunk) {
1651                 if ($trunknum == ltrim($trunk[0],"OUT_")) {
1652                         $trunknum++;
1653                 }
1654         }
1655        
1656         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1657        
1658         return $trunknum;
1659 }
1660
1661 function core_trunks_del($trunknum, $tech = null) {
1662         global $db;
1663        
1664         if ($tech === null) { // in EditTrunk, we get this info anyways
1665                 $tech = core_trunks_getTrunkTech($trunknum);
1666         }
1667
1668         //delete from globals table
1669         sql("DELETE FROM globals WHERE variable LIKE '%OUT_$trunknum' OR variable IN ('OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')");
1670        
1671         //write outids
1672         core_trunks_writeoutids();
1673
1674         // conditionally, delete from iax or sip
1675         switch (strtolower($tech)) {
1676                 case "iax":
1677                 case "iax2":
1678                         sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1679                 break;
1680                 case "sip":
1681                         sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'");
1682                 break;
1683         }
1684 }
1685
1686 function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1687         //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1688         $tech = core_trunks_getTrunkTech($trunknum);
1689         core_trunks_del($trunknum, $tech);
1690         core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk);
1691 }
1692
1693 // just used internally by addTrunk() and editTrunk()
1694 //obsolete
1695 function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) {
1696         global $db;
1697        
1698         if  (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL
1699        
1700         //echo  "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)";
1701        
1702         // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..)
1703         $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech);
1704         $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid);
1705        
1706         $glofields = array(
1707                         array('OUT_'.$trunknum, $outval),
1708                         array('OUTPREFIX_'.$trunknum, $dialoutprefix),
1709                         array('OUTMAXCHANS_'.$trunknum, $maxchans),
1710                         array('OUTCID_'.$trunknum, $outcid),
1711                         array('OUTKEEPCID_'.$trunknum, $keepcid),
1712                         array('OUTFAIL_'.$trunknum, $failtrunk),
1713                         array('OUTDISABLE_'.$trunknum, $disabletrunk),
1714                         );
1715                        
1716         unset($techtemp);
1717        
1718         $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1719         $result = $db->executeMultiple($compiled,$glofields);
1720         if(DB::IsError($result)) {
1721                 die_freepbx($result->getMessage()."<br><br>".$sql);
1722         }
1723        
1724         core_trunks_writeoutids();
1725
1726         $disable_flag = ($disabletrunk == "on")?1:0;
1727        
1728         switch (strtolower($tech)) {
1729                 case "iax":
1730                 case "iax2":
1731                         core_trunks_addSipOrIax($peerdetails,'iax',$channelid,$trunknum,$disable_flag);
1732                         if ($usercontext != ""){
1733                                 core_trunks_addSipOrIax($userconfig,'iax',$usercontext,'9'.$trunknum,$disable_flag);
1734                         }
1735                         if ($register != ""){
1736                                 core_trunks_addRegister($trunknum,'iax',$register,$disable_flag);
1737                         }
1738                 break;
1739                 case "sip":
1740                         core_trunks_addSipOrIax($peerdetails,'sip',$channelid,$trunknum,$disable_flag);
1741                         if ($usercontext != ""){
1742                                 core_trunks_addSipOrIax($userconfig,'sip',$usercontext,'9'.$trunknum,$disable_flag);
1743                         }
1744                         if ($register != ""){
1745                                 core_trunks_addRegister($trunknum,'sip',$register,$disable_flag);
1746                         }
1747                 break;
1748         }       
1749 }
1750
1751 function core_trunks_getTrunkTech($trunknum) {
1752
1753         $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1754         if (!$results) {
1755                 return false;
1756         }
1757         if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1758                 $tech = "custom";
1759         } else {
1760                 $tech = strtolower( strtok($results[0][0],'/') ); // the technology.  ie: ZAP/g0 is ZAP
1761                
1762                 if ($tech == "iax2") $tech = "iax"; // same thing, here
1763         }
1764         return $tech;
1765 }
1766
1767 //add trunk info to sip or iax table
1768 function core_trunks_addSipOrIax($config,$table,$channelid,$trunknum,$disable_flag=0) {
1769         global $db;
1770        
1771         $confitem['account'] = $channelid;
1772         $gimmieabreak = nl2br($config);
1773         $lines = split('<br />',$gimmieabreak);
1774         foreach ($lines as $line) {
1775                 $line = trim($line);
1776                 if (count(split('=',$line)) > 1) {
1777                         $tmp = split('=',$line,2);
1778                         $key=trim($tmp[0]);
1779                         $value=trim($tmp[1]);
1780                         if (isset($confitem[$key]) && !empty($confitem[$key]))
1781                                 $confitem[$key].="&".$value;
1782                         else
1783                                 $confitem[$key]=$value;
1784                 }
1785         }
1786         foreach($confitem as $k=>$v) {
1787                 $dbconfitem[]=array($k,$v);
1788         }
1789         $compiled = $db->prepare("INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')");
1790         $result = $db->executeMultiple($compiled,$dbconfitem);
1791         if(DB::IsError($result)) {
1792                 die_freepbx($result->getMessage()."<br><br>INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')");       
1793         }
1794 }
1795
1796 //get unique trunks
1797 function core_trunks_list($assoc = false) {
1798         // TODO: $assoc default to true, eventually..
1799
1800         global $db;
1801         global $amp_conf;
1802        
1803         if ($amp_conf["AMPDBENGINE"] == "sqlite3")
1804         {
1805                 // TODO: sqlite work arround - diego
1806                 // TODO: WILL NOT WORK, need to remove the usage of SUBSTRING
1807                 // need to reorder the trunks in PHP code
1808                 $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1809                 $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\_%') d ";
1810                 $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\_%' ";
1811                 $sqlstr .= "UNION ALL ";
1812                 $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1813                 $sqlstr .= "WHERE v.variable LIKE 'OUT\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1814                 $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\_%' ) ";
1815                 $sqlstr .= "ORDER BY variable";
1816
1817                 //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT_%' ORDER BY variable","getAll");
1818                 $unique_trunks = sql($sqlstr,"getAll");
1819         }
1820         else
1821         {
1822                 // we have to escape _ for mysql: normally a wildcard
1823                 $sqlstr  = "SELECT t.variable, t.value, d.value state FROM `globals` t ";
1824                 $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\\\_%') d ";
1825                 $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\\\_%' ";
1826                 $sqlstr .= "UNION ALL ";
1827                 $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state  FROM `globals` v ";
1828                 $sqlstr .= "WHERE v.variable LIKE 'OUT\\\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN ";
1829                 $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\\\_%' ) ";
1830                 $sqlstr .= "ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0";
1831
1832                 //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT\\\_%' ORDER BY RIGHT( variable, LENGTH( variable ) - 4 )+0","getAll");
1833                 $unique_trunks = sql($sqlstr,"getAll");
1834         }
1835
1836         //if no trunks have ever been defined, then create the proper variables with the default zap trunk
1837         if (count($unique_trunks) == 0)
1838         {
1839                 //If all trunks have been deleted from admin, dialoutids might still exist
1840                 sql("DELETE FROM globals WHERE variable = 'DIALOUTIDS'");
1841        
1842                 $glofields = array(array('OUT_1','ZAP/g0'),
1843                                                         array('DIAL_OUT_1','9'),
1844                                                         array('DIALOUTIDS','1'));
1845                 $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)');
1846                 $result = $db->executeMultiple($compiled,$glofields);
1847                 if(DB::IsError($result))
1848                 {
1849                         die_freepbx($result->getMessage()."<br><br>".$sql);     
1850                 }
1851                 $unique_trunks[] = array('OUT_1','ZAP/g0');
1852         }
1853         // asort($unique_trunks);
1854
1855         if ($assoc) {
1856                 $trunkinfo = array();
1857
1858                 foreach ($unique_trunks as $trunk) {
1859                         list($tech,$name) = explode('/',$trunk[1]);
1860                         $trunkinfo[$name] = array(
1861                                 'name' => $name,
1862                                 'tech' => $tech,
1863                                 'globalvar' => $trunk[0], // ick
1864                                 'value' => $trunk[2], // ??  no idea what this is.
1865                         );     
1866                 }
1867                 return $trunkinfo;
1868         } else {
1869                 return $unique_trunks;
1870         }
1871 }
1872
1873 //write the OUTIDS global variable (used in dialparties.agi)
1874 function core_trunks_writeoutids() {
1875         // we have to escape _ for mysql: normally a wildcard
1876         $unique_trunks = sql("SELECT variable FROM globals WHERE variable LIKE 'OUT\\\_%'","getAll");
1877
1878         $outids = null; // Start off with nothing
1879         foreach ($unique_trunks as $unique_trunk) {
1880                 $outid = strtok($unique_trunk[0],"_");
1881                 $outid = strtok("_");
1882                 $outids .= $outid ."/";
1883         }
1884        
1885         sql("UPDATE globals SET value = '$outids' WHERE variable = 'DIALOUTIDS'");
1886 }
1887
1888 function core_trunks_addRegister($trunknum,$tech,$reg,$disable_flag=0) {
1889         sql("INSERT INTO $tech (id, keyword, data, flags) values ('9999999$trunknum','register','$reg','$disable_flag')");
1890 }
1891
1892
1893 function core_trunks_addDialRules($trunknum, $dialrules) {
1894         $values = array();
1895         $i = 1;
1896         foreach ($dialrules as $rule) {
1897                 $values["rule".$i++] = $rule;
1898         }
1899        
1900         $conf = core_trunks_readDialRulesFile();
1901        
1902         // rewrite for this trunk
1903         $conf["trunk-".$trunknum] = $values;
1904        
1905         core_trunks_writeDialRulesFile($conf);
1906 }
1907
1908 function core_trunks_readDialRulesFile() {
1909         global $amp_conf;
1910         $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1911        
1912         core_trunks_parse_conf($localPrefixFile, $conf, $section);
1913        
1914         return $conf;
1915 }
1916
1917 function core_trunks_writeDialRulesFile($conf) {
1918         global $amp_conf;
1919         $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf";
1920        
1921         $fd = fopen($localPrefixFile,"w");
1922         foreach ($conf as $section=>$values) {
1923                 fwrite($fd, "[".$section."]\n");
1924                 foreach ($values as $key=>$value) {
1925                         fwrite($fd, $key."=".$value."\n");
1926                 }
1927                 fwrite($fd, "\n");
1928         }
1929         fclose($fd);
1930 }
1931
1932 function core_trunks_parse_conf($filename, &$conf, &$section) {
1933         if (is_null($conf)) {
1934                 $conf = array();
1935         }
1936         if (is_null($section)) {
1937                 $section = "general";
1938         }
1939        
1940         if (file_exists($filename)) {
1941                 $fd = fopen($filename, "r");
1942                 while ($line = fgets($fd, 1024)) {
1943                         if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
1944                                 // name = value
1945                                 // option line
1946                                 $conf[$section][ $matches[1] ] = $matches[2];
1947                         } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
1948                                 // section name
1949                                 $section = strtolower($matches[1]);
1950                         } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) {
1951                                 // include another file
1952                                
1953                                 if ($matches[1][0] == "/") {
1954                                         // absolute path
1955                                         $filename = $matches[1];
1956                                 } else {
1957                                         // relative path
1958                                         $filename =  dirname($filename)."/".$matches[1];
1959                                 }
1960                                
1961                                 core_trunks_parse_conf($filename, $conf, $section);
1962                         }
1963                 }
1964         }
1965 }
1966
1967 function core_trunks_getTrunkTrunkName($trunknum) {
1968         $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll");
1969         if (!$results) {
1970                 return false;
1971         }
1972        
1973         if(strpos($results[0][0],"AMP:") === 0) {  //custom trunks begin with AMP:
1974                 $tname = substr($results[0][0],4);
1975         } else {
1976         strtok($results[0][0],'/');
1977                 $tname = strtok('/'); // the text _after_ technology.  ie: ZAP/g0 is g0
1978         }
1979         return $tname;
1980 }
1981
1982 //get and print peer details (prefixed with 4 9's)
1983 function core_trunks_getTrunkPeerDetails($trunknum) {
1984         global $db;
1985        
1986         $tech = core_trunks_getTrunkTech($trunknum);
1987        
1988         if ($tech == "zap") return ""; // zap has no details
1989        
1990         $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999$trunknum' ORDER BY id","getAll");
1991        
1992         foreach ($results as $result) {
1993                 if ($result[0] != 'account') {
1994                         if (isset($confdetail))
1995                                 $confdetail .= $result[0] .'='. $result[1] . "\n";
1996                         else
1997                                 $confdetail = $result[0] .'='. $result[1] . "\n";
1998                 }
1999         }
2000         return $confdetail;
2001 }
2002
2003 //get trunk user context (prefixed with 5 9's)
2004 function core_trunks_getTrunkUserContext($trunknum) {
2005         $tech = core_trunks_getTrunkTech($trunknum);
2006         if ($tech == "zap") return ""; // zap has no account
2007        
2008         $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
2009
2010         foreach ($results as $result) {
2011                 if ($result[0] == 'account') {
2012                         $account = $result[1];
2013                 }
2014         }
2015         return isset($account)?$account:null;
2016 }
2017
2018 //get and print user config (prefixed with 5 9's)
2019 function core_trunks_getTrunkUserConfig($trunknum) {
2020         global $db;
2021        
2022         $tech = core_trunks_getTrunkTech($trunknum);
2023        
2024         if ($tech == "zap") return ""; // zap has no details
2025        
2026         $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY id","getAll");
2027
2028         foreach ($results as $result) {
2029                 if ($result[0] != 'account') {
2030                         if (isset($confdetail))
2031                                 $confdetail .= $result[0] .'='. $result[1] . "\n";
2032                         else
2033                                 $confdetail = $result[0] .'='. $result[1] . "\n";
2034                 }
2035         }
2036         return isset($confdetail)?$confdetail:null;
2037 }
2038
2039 //get trunk account register string
2040 function core_trunks_getTrunkRegister($trunknum) {
2041         $tech = core_trunks_getTrunkTech($trunknum);
2042        
2043         if ($tech == "zap") return ""; // zap has no register
2044        
2045         $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999999$trunknum'","getAll");
2046
2047         foreach ($results as $result) {
2048                         $register = $result[1];
2049         }
2050         return isset($register)?$register:null;
2051 }
2052
2053 function core_trunks_getDialRules($trunknum) {
2054         $conf = core_trunks_readDialRulesFile();
2055         if (isset($conf["trunk-".$trunknum])) {
2056                 return $conf["trunk-".$trunknum];
2057         }
2058         return false;
2059 }
2060
2061 //get outbound routes for a given trunk
2062 function core_trunks_gettrunkroutes($trunknum) {
2063   $sql_code = "SELECT DISTINCT SUBSTRING(context,7) route ,args trunk FROM extensions WHERE context LIKE 'outrt-%' AND
2064     (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%' OR args LIKE 'dialout-dundi,%') ORDER BY context,priority";
2065   $results = sql( $sql_code, "getAll" ,DB_FETCHMODE_ASSOC);
2066   $routeseq = array();
2067   foreach ($results as $entry) {
2068     $pos1 = strpos($entry['trunk'],',')+1;
2069     $routeseq[$entry['route']][] = substr($entry['trunk'],$pos1,strpos($entry['trunk'],',',$pos1)-$pos1);
2070   }
2071   $routes = array();
2072   foreach ($routeseq as $key => $value) {
2073     $pos = array_search($trunknum, array_values(array_unique($value)));
2074     if ($pos !== false) {
2075       $routes[$key] = $pos+1; // start at 1, not 0
2076     }
2077   }
2078   return $routes;
2079 }
2080
2081 function core_trunks_deleteDialRules($trunknum) {
2082         $conf = core_trunks_readDialRulesFile();
2083        
2084         // remove rules for this trunk
2085         unset($conf["trunk-".$trunknum]);
2086        
2087         core_trunks_writeDialRulesFile($conf);
2088 }
2089
2090 /* end page.trunks.php functions */
2091
2092
2093 /* begin page.routing.php functions */
2094
2095 //get unique outbound route names
2096 function core_routing_getroutenames()
2097 {
2098         global $amp_conf;
2099        
2100         if ($amp_conf["AMPDBENGINE"] == "sqlite3")
2101         {
2102                 // SUBSTRING is not supported under sqlite3, we need to filter
2103                 // this in php. I am not sure why "6" and not "7"
2104                 // but I don't really care -> it works :)
2105                 $results = sql("SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2106                 foreach( array_keys($results) as $idx )
2107                 {
2108                          $results[$idx][0] = substr( $results[$idx][0], 6);
2109                 }
2110         }
2111         else
2112         {
2113                 // we SUBSTRING() to remove "outrt-"
2114                 $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2115         }
2116
2117
2118         //TODO: This needs to be yanked, should be in the upgrade script somewhere not here
2119         //
2120         if (count($results) == 0) {
2121                 // see if they're still using the old dialprefix method
2122                 $results = sql("SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\\\_OUT\\\_%'","getAll");
2123                 // we SUBSTRING() to remove "outrt-"
2124                
2125                 if (count($results) > 0) {
2126                         // yes, they are using old method, let's update
2127                        
2128                         // get the default trunk
2129                         $results_def = sql("SELECT value FROM globals WHERE variable = 'OUT'","getAll");
2130                        
2131                         if (preg_match("/{OUT_(\d+)}/", $results_def[0][0], $matches)) {
2132                                 $def_trunk = $matches[1];
2133                         } else {
2134                                 $def_trunk = "";
2135                         }
2136                        
2137                         $default_patterns = array(      // default patterns that used to be in extensions.conf
2138                                                 "NXXXXXX",
2139                                                 "NXXNXXXXXX",
2140                                                 "1800NXXXXXX",
2141                                                 "1888NXXXXXX",
2142                                                 "1877NXXXXXX",
2143                                                 "1866NXXXXXX",
2144                                                 "1NXXNXXXXXX",
2145                                                 "011.",
2146                                                 "911",
2147                                                 "411",
2148                                                 "311",
2149                                                 );
2150                        
2151                         foreach ($results as $temp) {
2152                                 // temp[0] is "DIAL_OUT_1"
2153                                 // temp[1] is the dial prefix
2154                                
2155                                 $trunknum = substr($temp[0],9);
2156                                
2157                                 $name = "route".$trunknum;
2158                                
2159                                 $trunks = array(1=>"OUT_".$trunknum); // only one trunk to use
2160                                
2161                                 $patterns = array();
2162                                 foreach ($default_patterns as $pattern) {
2163                                         $patterns[] = $temp[1]."|".$pattern;
2164                                 }
2165                                
2166                                 if ($trunknum == $def_trunk) {
2167                                         // this is the default trunk, add the patterns with no prefix
2168                                         $patterns = array_merge($patterns, $default_patterns);
2169                                 }
2170                                
2171                                 // add this as a new route
2172                                 core_routing_add($name, $patterns, $trunks,"new");
2173                         }
2174                        
2175                        
2176                         // delete old values
2177                         sql("DELETE FROM globals WHERE (variable LIKE 'DIAL\\\_OUT\\\_%') OR (variable = 'OUT') ");
2178
2179                         // we need to re-generate extensions_additional.conf
2180                         // i'm not sure how to do this from here
2181                        
2182                         // re-run our query
2183                         $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll");
2184                         // we SUBSTRING() to remove "outrt-"
2185                 }
2186                
2187         } // else, it just means they have no routes.
2188        
2189         return $results;
2190 }
2191
2192 function core_routing_setroutepriority($routepriority, $reporoutedirection, $reporoutekey)
2193 {
2194         global $db, $amp_conf;
2195         $counter=-1;
2196         foreach ($routepriority as $tresult)
2197         {
2198                 $counter++;
2199                 if (($counter==($reporoutekey-1)) && ($reporoutedirection=="up")) {
2200                         // swap this one with the one before (move up)
2201                         $temproute = $routepriority[$counter];
2202                         $routepriority[ $counter ] = $routepriority[ $counter+1 ];
2203                         $routepriority[ $counter+1 ] = $temproute;
2204                        
2205                 } else if (($counter==($reporoutekey)) && ($reporoutedirection=="down")) {
2206                         // swap this one with the one after (move down)
2207                         $temproute = $routepriority[ $counter+1 ];
2208                         $routepriority[ $counter+1 ] = $routepriority[ $counter ];
2209                         $routepriority[ $counter ] = $temproute;
2210                 }
2211         }
2212         unset($temptrunk);
2213         $routepriority = array_values($routepriority); // resequence our numbers
2214         $counter=0;
2215         foreach ($routepriority as $tresult) {
2216                 $order=core_routing_setroutepriorityvalue($counter++);
2217                 $sql = sprintf("Update extensions set context='outrt-%s-%s' WHERE context='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2218                 $result = $db->query($sql);
2219                 if(DB::IsError($result)) {     
2220                         die_freepbx($result->getMessage());
2221                 }
2222         }
2223        
2224         // Delete and readd the outbound-allroutes entries
2225         $sql = "delete from  extensions WHERE context='outbound-allroutes'";
2226         $result = $db->query($sql);
2227         if(DB::IsError($result)) {
2228                 die_freepbx($result->getMessage().$sql);
2229         }
2230        
2231         $sql = "SELECT DISTINCT context FROM extensions WHERE context like 'outrt-%' ORDER BY context";
2232         $results = $db->getAll($sql);
2233         if(DB::IsError($results)) {
2234                 die_freepbx($results->getMessage());
2235         }
2236
2237         $priority_loops=1;     
2238         foreach ($results as $row) {
2239                 $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2240                 $sql .= "('outbound-allroutes', ";
2241                 $sql .= "'include', ";
2242                 $sql .= "'".$priority_loops++."', ";
2243                 $sql .= "'".$row[0]."', ";
2244                 $sql .= "'', ";
2245                 $sql .= "'', ";
2246                 $sql .= "'2')";
2247        
2248                 //$sql = sprintf("Update extensions set application='outrt-%s-%s' WHERE context='outbound-allroutes' and  application='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]);
2249                 $result = $db->query($sql);
2250                 if(DB::IsError($result)) {     
2251                         die_freepbx($result->getMessage(). $sql);
2252                 }
2253         }
2254        
2255         if ( $amp_conf["AMPDBENGINE"] == "sqlite3")
2256                 $sql = "SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2257         else
2258                 $sql = "SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ";
2259
2260         // we SUBSTRING() to remove "outrt-"
2261         $routepriority = $db->getAll($sql);
2262         if(DB::IsError($routepriority)) {
2263                 die_freepbx($routepriority->getMessage());
2264         }
2265
2266         // TODO: strip the context on the sqlite3 backend
2267         // not sure where does it effects, since this is working on my setup...
2268         // welcome to funky town
2269         return ($routepriority);
2270 }
2271
2272 function core_routing_setroutepriorityvalue($key)
2273 {
2274         $key=$key+1;
2275         if ($key<10)
2276                 $prefix = sprintf("00%d",$key);
2277         else if ((9<$key)&&($key<100))
2278                 $prefix = sprintf("0%d",$key);
2279         else if ($key>100)
2280                 $prefix = sprintf("%d",$key);
2281         return ($prefix);
2282 }
2283
2284
2285 function core_routing_add($name, $patterns, $trunks, $method, $pass, $emergency = "", $intracompany = "", $mohsilence = "") {
2286
2287         global $db;
2288
2289         $trunktech=array();
2290
2291         //Retrieve each trunk tech for later lookup
2292         $sql="select * from globals WHERE variable LIKE 'OUT\\_%'";
2293         $result = $db->getAll($sql);
2294         if(DB::IsError($result)) {
2295                 die_freepbx($result->getMessage());
2296         }
2297         foreach($result as $tr) {
2298                 $tech = strtok($tr[1], "/");
2299                 $trunktech[$tr[0]]=$tech;
2300         }
2301        
2302         if ($method=="new") {   
2303                 $sql="select DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context";
2304                 $routepriority = $db->getAll($sql);
2305                 if(DB::IsError($result)) {
2306                         die_freepbx($result->getMessage());
2307                 }
2308                 $order=core_routing_setroutepriorityvalue(count($routepriority));
2309                 $name = sprintf ("%s-%s",$order,$name);
2310         }
2311         $trunks = array_values($trunks); // probably already done, but it's important for our dialplan
2312
2313        
2314         foreach ($patterns as $pattern) {
2315                 if (false !== ($pos = strpos($pattern,"|"))) {
2316                         // we have a | meaning to not pass the digits on
2317                         // (ie, 9|NXXXXXX should use the pattern _9NXXXXXX but only pass NXXXXXX, not the leading 9)
2318                        
2319                         $pattern = str_replace("|","",$pattern); // remove all |'s
2320                         $exten = "EXTEN:".$pos; // chop off leading digit
2321                 } else {
2322                         // we pass the full dialed number as-is
2323                         $exten = "EXTEN";
2324                 }
2325                
2326                 if (!preg_match("/^[0-9*]+$/",$pattern)) {
2327                         // note # is not here, as asterisk doesn't recoginize it as a normal digit, thus it requires _ pattern matching
2328                        
2329                         // it's not strictly digits, so it must have patterns, so prepend a _
2330                         $pattern = "_".$pattern;
2331                 }
2332                
2333                 // 1st priority is emergency dialing variable (if set)
2334                 if(!empty($emergency)) {
2335                         $startpriority = 1;
2336                         $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2337                         $sql .= "('outrt-".$name."', ";
2338                         $sql .= "'".$pattern."', ";
2339                         $sql .= "'".$startpriority."', ";
2340                         $sql .= "'SetVar', ";
2341                         $sql .= "'EMERGENCYROUTE=YES', ";
2342                         $sql .= "'Use Emergency CID for device')";
2343                         $result = $db->query($sql);
2344                         if(DB::IsError($result)) {
2345                                 die_freepbx($result->getMessage());
2346                         }
2347                 } else {
2348                         $startpriority = 0;
2349                 }
2350
2351                 // Next Priority (either first or second depending on above)
2352                 if(!empty($intracompany)) {
2353                            $startpriority += 1;
2354                            $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2355                            $sql .= "('outrt-".$name."', ";
2356                            $sql .= "'".$pattern."', ";
2357                            $sql .= "'".$startpriority."', ";
2358                            $sql .= "'SetVar', ";
2359                            $sql .= "'INTRACOMPANYROUTE=YES', ";
2360                            $sql .= "'Preserve Intenal CID Info')";
2361                            $result = $db->query($sql);
2362                                 if(DB::IsError($result)) {
2363                                            die_freepbx($result->getMessage());
2364                                 }
2365                 }
2366
2367                 // Next Priority (either first, second or third depending on above)
2368                 if(!empty($mohsilence) && trim($mohsilence) != 'default') {
2369                            $startpriority += 1;
2370                            $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2371                            $sql .= "('outrt-".$name."', ";
2372                            $sql .= "'".$pattern."', ";
2373                            $sql .= "'".$startpriority."', ";
2374                            $sql .= "'SetVar', ";
2375                            $sql .= "'MOHCLASS=".$mohsilence."', ";
2376                            $sql .= "'Do not play moh on this route')";
2377                            $result = $db->query($sql);
2378                                 if(DB::IsError($result)) {
2379                                            die_freepbx($result->getMessage());
2380                                 }
2381                 }
2382
2383                 $first_trunk = 1;
2384                 foreach ($trunks as $priority => $trunk) {
2385                         $priority += $startpriority;
2386                         $priority += 1; // since arrays are 0-based, but we want priorities to start at 1
2387                        
2388                         $sql = "INSERT INTO extensions (context, extension, priority, application, args) VALUES ";
2389                         $sql .= "('outrt-".$name."', ";
2390                         $sql .= "'".$pattern."', ";
2391                         $sql .= "'".$priority."', ";
2392                         $sql .= "'Macro', ";
2393                         if ($first_trunk)
2394                                 $pass_str = $pass;
2395                         else
2396                                 $pass_str = "";
2397
2398                         if ($trunktech[$trunk] == "ENUM")
2399                                 $sql .= "'dialout-enum,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2400                         else
2401                                 $sql .= "'dialout-trunk,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk
2402                         $sql .= ")";
2403                        
2404                         $result = $db->query($sql);
2405                         if(DB::IsError($result)) {
2406                                 die_freepbx($result->getMessage());
2407                         }
2408                         //To identify the first trunk in a pattern
2409                         //so that passwords are in the first trunk in
2410                         //each pattern
2411                         $first_trunk = 0;
2412                 }
2413                
2414                 $priority += 1;
2415                 $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES ";
2416                 $sql .= "('outrt-".$name."', ";
2417                 $sql .= "'".$pattern."', ";
2418                 $sql .= "'".$priority."', ";
2419                 $sql .= "'Macro', ";
2420                 $sql .= "'outisbusy', ";
2421                 $sql .= "'No available circuits')";
2422                
2423                 $result = $db->query($sql);
2424                 if(DB::IsError($result)) {
2425                         die_freepbx($result->getMessage());
2426                 }
2427         }
2428
2429        
2430         // add an include=>outrt-$name  to [outbound-allroutes]:
2431        
2432         // we have to find the first available priority.. priority doesn't really matter for the include, but
2433         // there is a unique index on (context,extension,priority) so if we don't do this we can't put more than
2434         // one route in the outbound-allroutes context.
2435         $sql = "SELECT priority FROM extensions WHERE context = 'outbound-allroutes' AND extension = 'include'";
2436         $results = $db->getAll($sql);
2437         if(DB::IsError($results)) {
2438                 die_freepbx($results->getMessage());
2439         }
2440         $priorities = array();
2441         foreach ($results as $row) {
2442                 $priorities[] = $row[0];
2443         }
2444         for ($priority = 1; in_array($priority, $priorities); $priority++);
2445        
2446         // $priority should now be the lowest available number
2447        
2448         $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ";
2449         $sql .= "('outbound-allroutes', ";
2450         $sql .= "'include', ";
2451         $sql .= "'".$priority."', ";
2452         $sql .= "'outrt-".$name."', ";
2453         $sql .= "'', ";
2454         $sql .= "'', ";
2455         $sql .= "'2')";
2456        
2457         $result = $db->query($sql);
2458         if(DB::IsError($result)) {
2459                 die_freepbx($priority.$result->getMessage());
2460         }
2461        
2462 }
2463
2464 function core_routing_edit($name, $patterns, $trunks, $pass, $emergency="", $intracompany = "", $mohsilence="") {
2465         core_routing_del($name);
2466         core_routing_add($name, $patterns, $trunks,"edit", $pass, $emergency, $intracompany, $mohsilence);
2467 }
2468
2469 function core_routing_del($name) {
2470         global $db;
2471         $sql = "DELETE FROM extensions WHERE context = 'outrt-".$name."'";
2472         $result = $db->query($sql);
2473         if(DB::IsError($result)) {
2474                 die_freepbx($result->getMessage());
2475         }
2476        
2477         $sql = "DELETE FROM extensions WHERE context = 'outbound-allroutes' AND application = 'outrt-".$name."' ";
2478         $result = $db->query($sql);
2479         if(DB::IsError($result)) {
2480                 die_freepbx($result->getMessage());
2481         }
2482        
2483         return $result;
2484 }
2485
2486 /* Delete all occurences of the specified trunk from all routes that may use it
2487  */
2488 function core_routing_trunk_del($trunknum) {
2489         global $db;
2490
2491   $sql = "DELETE FROM `extensions` WHERE `application` = 'Macro' AND `context` LIKE 'outrt-%' AND `args` LIKE 'dialout-%,$trunknum,%'";
2492         $result = $db->query($sql);
2493 }
2494
2495 function core_routing_rename($oldname, $newname) {
2496         global $db;
2497
2498         $route_prefix=substr($oldname,0,4);
2499         $newname=$route_prefix.$newname;
2500         $sql = "SELECT context FROM extensions WHERE context = 'outrt-".$newname."'";
2501         $results = $db->getAll($sql);
2502         if (count($results) > 0) {
2503                 // there's already a route with this name
2504                 return false;
2505         }
2506        
2507         $sql = "UPDATE extensions SET context = 'outrt-".$newname."' WHERE context = 'outrt-".$oldname."'";
2508         $result = $db->query($sql);
2509         if(DB::IsError($result)) {
2510                 die_freepbx($result->getMessage());
2511         }
2512         $mypriority=sprintf("%d",$route_prefix);       
2513         $sql = "UPDATE extensions SET application = 'outrt-".$newname."', priority = '$mypriority' WHERE context = 'outbound-allroutes' AND application = 'outrt-".$oldname."' ";
2514         $result = $db->query($sql);
2515         if(DB::IsError($result)) {
2516                 die_freepbx($result->getMessage());
2517         }
2518        
2519         return true;
2520 }
2521
2522 //get unique outbound route patterns for a given context
2523 function core_routing_getroutepatterns($route) {
2524         global $db;
2525         $sql = "SELECT extension, args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk%' OR args LIKE'dialout-enum%') ORDER BY extension ";
2526         $results = $db->getAll($sql);
2527         if(DB::IsError($results)) {
2528                 die_freepbx($results->getMessage());
2529         }
2530        
2531         $patterns = array();
2532         foreach ($results as $row) {
2533                 if ($row[0][0] == "_") {
2534                         // remove leading _
2535                         $pattern = substr($row[0],1);
2536                 } else {
2537                         $pattern = $row[0];
2538                 }
2539                
2540                 if (preg_match("/{EXTEN:(\d+)}/", $row[1], $matches)) {
2541                         // this has a digit offset, we need to insert a |
2542                         $pattern = substr($pattern,0,$matches[1])."|".substr($pattern,$matches[1]);
2543                 }
2544                
2545                 $patterns[] = $pattern;
2546         }
2547         return array_unique($patterns);
2548 }
2549
2550 //get unique outbound route trunks for a given context
2551 function core_routing_getroutetrunks($route) {
2552         global $db;
2553         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%') ORDER BY CAST(priority as UNSIGNED) ";
2554         $results = $db->getAll($sql);
2555         if(DB::IsError($results)) {
2556                 die_freepbx($results->getMessage());
2557         }
2558        
2559         $trunks = array();
2560         foreach ($results as $row) {
2561                 if (preg_match('/^dialout-trunk,(\d+)/', $row[0], $matches)) {
2562                         // check in_array -- even though we did distinct
2563                         // we still might get ${EXTEN} and ${EXTEN:1} if they used | to split a pattern
2564                         if (!in_array("OUT_".$matches[1], $trunks)) {
2565                                 $trunks[] = "OUT_".$matches[1];
2566                         }
2567                 } else if (preg_match('/^dialout-enum,(\d+)/', $row[0], $matches)) {
2568                         if (!in_array("OUT_".$matches[1], $trunks)) {
2569                                 $trunks[] = "OUT_".$matches[1];
2570                         }
2571                 }
2572         }
2573         return $trunks;
2574 }
2575
2576
2577 //get password for this route
2578 function core_routing_getroutepassword($route) {
2579         global $db;
2580         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%') ORDER BY CAST(priority as UNSIGNED) ";
2581         $results = $db->getOne($sql);
2582         if(DB::IsError($results)) {
2583                 die_freepbx($results->getMessage());
2584         }
2585         if (preg_match('/^.*,.*,.*,(\d+|\/\S+)/', $results, $matches)) {
2586                 $password = $matches[1];
2587         } else {
2588                 $password = "";
2589         }
2590        
2591         return $password;
2592 }
2593
2594 //get emergency state for this route
2595 function core_routing_getrouteemergency($route) {
2596         global $db;
2597         $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'EMERGENCYROUTE%') ";
2598         $results = $db->getOne($sql);
2599         if(DB::IsError($results)) {
2600                 die_freepbx($results->getMessage());
2601         }
2602         if (preg_match('/^.*=(.*)/', $results, $matches)) {
2603                 $emergency = $matches[1];
2604         } else {
2605                 $emergency = "";
2606         }
2607        
2608         return $emergency;
2609 }
2610
2611 //get intracompany routing status for this route
2612 function core_routing_getrouteintracompany($route) {
2613
2614        global $db;
2615        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'INTRACOMPANYROUTE%') ";
2616        $results = $db->getOne($sql);
2617        if(DB::IsError($results)) {
2618                die_freepbx($results->getMessage());
2619        }
2620        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2621                $intracompany = $matches[1];
2622        } else {
2623                $intracompany = "";
2624        }
2625        return $intracompany;
2626 }
2627
2628 //get mohsilence routing status for this route
2629 function core_routing_getroutemohsilence($route) {
2630
2631        global $db;
2632        $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'MOHCLASS%') ";
2633        $results = $db->getOne($sql);
2634        if(DB::IsError($results)) {
2635                die_freepbx($results->getMessage());
2636        }
2637        if (preg_match('/^.*=(.*)/', $results, $matches)) {
2638                $mohsilence = $matches[1];
2639        } else {
2640                $mohsilence = "";
2641        }
2642        return $mohsilence;
2643 }
2644
2645 function general_get_zonelist() {
2646         return array(
2647  array ( "name" => "Austria",  "iso" => "at", "conf" => "ringcadence = 1000,5000\ndial = 420\nbusy = 420/400,0/400\nring = 420/1000,0/5000\ncongestion = 420/200,0/200\ncallwaiting = 420/40,0/1960\ndialrecall = 420\nrecord = 1400/80,0/14920\ninfo = 950/330,1450/330,1850/330,0/1000\nstutter = 380+420\n"),
2648  array ( "name" => "Australia",  "iso" => "au", "conf" => "ringcadence = 400,200,400,2000\ndial = 413+438\nbusy = 425/375,0/375\nring = 413+438/400,0/200,413+438/400,0/2000\ncongestion = 425/375,0/375,420/375,0/375\ncallwaiting = 425/200,0/200,425/200,0/4400\ndialrecall = 413+438\nrecord = !425/1000,!0/15000,425/360,0/15000\ninfo = 425/2500,0/500\nstd = !525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100\nfacility = 425\nstutter = 413+438/100,0/40\nringmobile = 400+450/400,0/200,400+450/400,0/2000\n"),
2649  array ( "name" => "Brazil",  "iso" => "br", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250,425/750,0/250\ncallwaiting = 425/50,0/1000\ndialrecall = 350+440\nrecord = 425/250,0/250\ninfo = 950/330,1400/330,1800/330\nstutter = 350+440\n"),
2650  array ( "name" => "Belgium",  "iso" => "be", "conf" => "ringcadence = 1000,3000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/3000\ncongestion = 425/167,0/167\ncallwaiting = 1400/175,0/175,1400/175,0/3500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 900/330,1400/330,1800/330,0/1000\nstutter = 425/1000,0/250\n"),
2651  array ( "name" => "Switzerland",  "iso" => "ch", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/200,425/200,0/4000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+340/1100,0/1100\n"),
2652  array ( "name" => "Chile",  "iso" => "cl", "conf" => "ringcadence = 1000,3000\ndial = 400\nbusy = 400/500,0/500\nring = 400/1000,0/3000\ncongestion = 400/200,0/200\ncallwaiting = 400/250,0/8750\ndialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/500,0/15000\ninfo = 950/333,1400/333,1800/333,0/1000\nstutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\n"),
2653  array ( "name" => "China",  "iso" => "cn", "conf" => "ringcadence = 1000,4000\ndial = 450\nbusy = 450/350,0/350\nring = 450/1000,0/4000\ncongestion = 450/700,0/700\ncallwaiting = 450/400,0/4000\ndialrecall = 450\nrecord = 950/400,0/10000\ninfo = 450/100,0/100,450/100,0/100,450/100,0/100,450/400,0/400\nstutter = 450+425\n"),
2654  array ( "name" => "Czech Republic",  "iso" => "cz", "conf" => "ringcadence = 1000,4000\ndial = 425/330,0/330,425/660,0/660\nbusy = 425/330,0/330\nring = 425/1000,0/4000\ncongestion = 425/165,0/165\ncallwaiting = 425/330,0/9000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425/330,0/330,425/660,0/660\nrecord = 1400/500,0/14000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = 425/450,0/50\n"),
2655  array ( "name" => "Germany",  "iso" => "de", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/480,0/480\nring = 425/1000,0/4000\ncongestion = 425/240,0/240\ncallwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+400\n"),
2656  array ( "name" => "Denmark",  "iso" => "dk", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = !425/200,!0/600,!425/200,!0/3000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/450,0/50\n"),
2657  array ( "name" => "Estonia",  "iso" => "ee", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 950/650,0/325,950/325,0/30,1400/1300,0/2600\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2658  array ( "name" => "Spain",  "iso" => "es", "conf" => "ringcadence = 1500,3000\ndial = 425\nbusy = 425/200,0/200\nring = 425/1500,0/3000\ncongestion = 425/200,0/200,425/200,0/200,425/200,0/600\ncallwaiting = 425/175,0/175,425/175,0/3500\ndialrecall = !425/200,!0/200,!425/200,!0/200,!425/200,!0/200,425\nrecord = 1400/500,0/15000\ninfo = 950/330,0/1000\ndialout = 500\n\n"),
2659  array ( "name" => "Finland",  "iso" => "fi", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = 425/650,0/25\n"),
2660  array ( "name" => "France",  "iso" => "fr", "conf" => "ringcadence = 1500,3500\ndial = 440\nbusy = 440/500,0/500\nring = 440/1500,0/3500\ncongestion = 440/250,0/250\ncallwait = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330\nstutter = !440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,440\n"),
2661  array ( "name" => "Greece",  "iso" => "gr", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/300,425/700,0/800\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 425/650,0/25\n"),
2662  array ( "name" => "Hungary",  "iso" => "hu", "conf" => "ringcadence = 1250,3750\ndial = 425\nbusy = 425/300,0/300\nring = 425/1250,0/3750\ncongestion = 425/300,0/300\ncallwaiting = 425/40,0/1960\ndialrecall = 425+450\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 350+375+400\n"),
2663  array ( "name" => "India",  "iso" => "in", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*25\nbusy = 400/750,0/750\nring = 400*25/400,0/200,400*25/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400/200,0/100,400/200,0/7500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2664  array ( "name" => "Israel",  "iso" => "il", "conf" => "ringcadence = 1000,3000\ndial = 414\nbusy = 414/500,0/500\nring = 414/1000,0/3000\ncongestion = 414/250,0/250\ncallwaiting = 414/100,0/100,414/100,0/100,414/600,0/3000 \ndialrecall = !414/100,!0/100,!414/100,!0/100,!414/100,!0/100,414\nrecord = 1400/500,0/15000\ninfo = 1000/330,1400/330,1800/330,0/1000\nstutter = !414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,414 \n"),
2665  array ( "name" => "Italy",  "iso" => "it", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/200,425/600,0/1000\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/400,0/100,425/250,0/100,425/150,0/14000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"),
2666  array ( "name" => "Lithuania",  "iso" => "lt", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/350,0/350\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2667  array ( "name" => "Mexico",  "iso" => "mx", "conf" => "ringcadence = 2000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2668  array ( "name" => "Netherlands",  "iso" => "nl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/500,0/9500\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/500,0/50\n"),
2669  array ( "name" => "Norway",  "iso" => "no", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"),
2670  array ( "name" => "New Zealand",  "iso" => "nz", "conf" => "ringcadence = 400,200,400,2000\ndial = 400\nbusy = 400/250,0/250\nring = 400+450/400,0/200,400+450/400,0/2000\ncongestion = 400/375,0/375\ncallwaiting = !400/200,!0/3000,!400/200,!0/3000,!400/200,!0/3000,!400/200\ndialrecall = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/425,0/15000\ninfo = 400/750,0/100,400/750,0/100,400/750,0/100,400/750,0/400\nstutter = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,!400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\n"),
2671  array ( "name" => "Poland",  "iso" => "pl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/500,0/500\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2672  array ( "name" => "Portugal",  "iso" => "pt", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/5000\ncongestion = 425/200,0/200\ncallwaiting = 440/300,0/10000\ndialrecall = 425/1000,0/200\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2673  array ( "name" => "Russia / ex Soviet Union",  "iso" => "ru", "conf" => "ringcadence = 800,3200\ndial = 425\nbusy = 425/350,0/350\nring = 425/800,0/3200\ncongestion = 425/350,0/350\ncallwaiting = 425/200,0/5000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\n"),
2674  array ( "name" => "Singapore",  "iso" => "sg", "conf" => "ringcadence = 400,200,400,2000\ndial = 425\nring = 425*24/400,0/200,425*24/400,0/2000 ; modulation should be 100%, not 90%\nbusy = 425/750,0/750\ncongestion = 425/250,0/250\ncallwaiting = 425*24/300,0/200,425*24/300,0/3200\nstutter = !425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,425\ninfo = 950/330,1400/330,1800/330,0/1000 ; not currently in use acc. to reference\ndialrecall = 425*24/500,0/500,425/500,0/2500 ; unspecified in IDA reference, use repeating Holding Tone A,B\nrecord = 1400/500,0/15000 ; unspecified in IDA reference, use 0.5s tone every 15s\nnutone = 425/2500,0/500\nintrusion = 425/250,0/2000\nwarning = 425/624,0/4376 ; end of period tone, warning\nacceptance = 425/125,0/125\nholdinga = !425*24/500,!0/500 ; followed by holdingb\nholdingb = !425/500,!0/2500\n"),
2675  array ( "name" => "South Africa",  "iso" => "za", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*33\nbusy = 400/500,0/500\nring = 400*33/400,0/200,400*33/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400*33/250,0/250,400*33/250,0/250,400*33/250,0/250,400*33/250,0/250\ndialrecall = 350+440\nrecord = 1400/500,0/10000\ninfo = 950/330,1400/330,1800/330,0/330\nstutter =!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,400*33 \n"),
2676  array ( "name" => "Sweden",  "iso" => "se", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/5000\ncongestion = 425/250,0/750\ncallwaiting = 425/200,0/500,425/200,0/9100\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/500,0/15000\ninfo = !950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"),
2677  array ( "name" => "United Kingdom",  "iso" => "uk", "conf" => "ringcadence = 400,200,400,2000\ndial = 350+440\nspecialdial = 350+440/750,440/750\nbusy = 400/375,0/375\ncongestion = 400/400,0/350,400/225,0/525\nspecialcongestion = 400/200,1004/300\nunobtainable = 400\nring = 400+450/400,0/200,400+450/400,0/2000\ncallwaiting = 400/100,0/4000\nspecialcallwaiting = 400/250,0/250,400/250,0/250,400/250,0/5000\ncreditexpired = 400/125,0/125\nconfirm = 1400\nswitching = 400/200,0/400,400/2000,0/400\ninfo = 950/330,0/15,1400/330,0/15,1800/330,0/1000\nrecord = 1400/500,0/60000\nstutter = 350+440/750,440/750\n"),
2678  array ( "name" => "United States / North America",  "iso" => "us", "conf" => "ringcadence = 2000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/2000,0/4000\ncongestion = 480+620/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2679  array ( "name" => "United States Circa 1950/ North America",  "iso" => "us-old", "conf" => "ringcadence = 2000,4000\ndial = 600*120\nbusy = 500*100/500,0/500\nring = 420*40/2000,0/4000\ncongestion = 500*100/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\n"),
2680  array ( "name" => "Taiwan",  "iso" => "tw", "conf" => "ringcadence = 1000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/1000,0/2000\ncongestion = 480+620/250,0/250\ncallwaiting = 350+440/250,0/250,350+440/250,0/3250\ndialrecall = 300/1500,0/500\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"),
2681  array ( "name" => "Venezuela / South America",  "iso" => "ve", "conf" => "; Tone definition source for ve found on\n; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf\nringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 400+450/300,0/6000\ndialrecall = 425\nrecord =  1400/500,0/15000\ninfo = !950/330,!1440/330,!1800/330,0/1000\n"),);
2682 }
2683
2684 function general_display_zones($curzone) {
2685         $zonelist = general_get_zonelist();
2686         echo "<select name='TONEZONE'>\n";
2687         foreach ($zonelist as $zone) {
2688                 if ($zone['iso'] == $curzone)
2689                         echo "<option selected value='{$zone['iso']}'>{$zone['name']}</option>\n";
2690                 else   
2691                         echo "<option value='{$zone['iso']}'>{$zone['name']}</option>\n";
2692         }
2693         echo "</select>";
2694        
2695 }
2696
2697 function general_generate_indications() {
2698         global $db;
2699         global $asterisk_conf;
2700
2701         $sql = "SELECT value FROM globals WHERE variable='TONEZONE'";
2702         $result = $db->getRow($sql,DB_FETCHMODE_ASSOC);
2703
2704         $filename = isset($asterisk_conf["astetcdir"]) && $asterisk_conf["astetcdir"] != '' ? rtrim($asterisk_conf["astetcdir"],DIRECTORY_SEPARATOR) : "/etc/asterisk";
2705         $filename .= "/indications.conf";
2706         $fd = fopen($filename, "w");
2707         fwrite($fd, "[general]\ncountry=".$result['value']."\n\n");
2708
2709         $zonelist = general_get_zonelist();
2710         foreach ($zonelist as $zone) {
2711                 fwrite($fd, "[{$zone['iso']}]\n{$zone['conf']}\n\n");
2712         }
2713         fclose($fd);
2714 }
2715 /* end page.routing.php functions */
2716
2717
2718
2719 // init registered 'your' config load and config process functions
2720 function core_users_configpageinit($dispnum) {
2721         global $currentcomponent;
2722         global $amp_conf;
2723
2724         if ( $dispnum == 'users' || $dispnum == 'extensions' ) {
2725                 // Setup option list we need
2726                 $currentcomponent->addoptlistitem('recordoptions', 'Adhoc', _("On Demand"));
2727                 $currentcomponent->addoptlistitem('recordoptions', 'Always', _("Always"));
2728                 $currentcomponent->addoptlistitem('recordoptions', 'Never', _("Never"));
2729                 $currentcomponent->setoptlistopts('recordoptions', 'sort', false);
2730
2731                 $currentcomponent->addoptlistitem('faxdetecttype', '0', _("None"));
2732                 $currentcomponent->addoptlistitem('faxdetecttype', '1', 'Zaptel');
2733                 $currentcomponent->addoptlistitem('faxdetecttype', '2', 'NVFax');
2734                 $currentcomponent->setoptlistopts('faxdetecttype', 'sort', false);
2735
2736                 $currentcomponent->addoptlistitem('privyn', '0', _("No"));
2737                 $currentcomponent->addoptlistitem('privyn', '1', _("Yes"));
2738                 $currentcomponent->setoptlistopts('privyn', 'sort', false);
2739
2740                 $currentcomponent->addoptlistitem('callwaiting', 'enabled', _("Enable"));
2741                 $currentcomponent->addoptlistitem('callwaiting', 'disabled', _("Disable"));
2742                 $currentcomponent->setoptlistopts('callwaiting', 'sort', false);
2743
2744                 $currentcomponent->addoptlistitem('ringtime', '0', 'Default');
2745                 for ($i=1; $i <= 120; $i++) {
2746                         $currentcomponent->addoptlistitem('ringtime', "$i", "$i");
2747                 }
2748                 $currentcomponent->setoptlistopts('ringtime', 'sort', false);
2749
2750                 $currentcomponent->addoptlistitem('faxdestoptions', 'default', _("FreePBX default"));
2751                 $currentcomponent->addoptlistitem('faxdestoptions', 'disabled', _("disabled"));
2752                 $currentcomponent->addoptlistitem('faxdestoptions', 'system', _("system"));
2753                 $currentcomponent->setoptlistopts('faxdestoptions', 'sort', false);
2754
2755                 if (function_exists('music_list')) {
2756                                 $tresults = music_list($amp_conf['ASTVARLIBDIR']."/mohmp3");
2757                     if (isset($tresults[0])) {
2758                         foreach ($tresults as $tresult) {
2759                             $currentcomponent->addoptlistitem('mohclass', $tresult, $tresult);
2760                         }
2761                     $currentcomponent->setoptlistopts('mohclass', 'sort', false);
2762                     }
2763                 }
2764
2765                 //get unique devices to finishoff faxdestoptions list
2766                 $devices = core_devices_list();
2767                 if (isset($devices)) {
2768                         foreach ($devices as $device) {
2769                                 $currentcomponent->addoptlistitem('faxdestoptions', $device[0], "$device[1] <$device[0]>");
2770                         }
2771                 }
2772
2773                 // Add the 'proces' functions
2774                 $currentcomponent->addguifunc('core_users_configpageload');
2775                 // Ensure users is called in middle order ($sortorder = 5), this is to allow
2776                 // other modules to call stuff before / after the processing of users if needed
2777                 // e.g. Voicemail module needs to create mailbox BEFORE the users as the mailbox
2778                 // context is needed by the add users function
2779                 $currentcomponent->addprocessfunc('core_users_configprocess', 5);                       
2780         }
2781 }
2782
2783 function core_users_configpageload() {
2784         global $currentcomponent;
2785         global $amp_conf;
2786
2787         // Ensure variables possibly extracted later exist
2788         $name = $directdid = $didalert = $outboundcid = $answer = null;
2789         $record_in = $record_out = $faxexten = $faxemail = $mohclass = $sipname = $cid_masquerade = null;
2790
2791         // Init vars from $_REQUEST[]
2792         $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
2793         $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
2794         $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
2795         $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
2796
2797         if ( $action == 'del' ) { // Deleted
2798
2799                 $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
2800
2801         } elseif ( $display == 'extensions' && ($extdisplay == '' && $tech_hardware == '') ) { // Adding
2802
2803                 // do nothing as you want the Devices to handle this bit
2804
2805         } else {
2806
2807                 $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
2808        
2809                 if ( is_string($extdisplay) ) {
2810                         $extenInfo=core_users_get($extdisplay);
2811                         extract($extenInfo);
2812                         if (isset($deviceInfo) && is_array($deviceInfo))
2813                                 extract($deviceInfo);
2814        
2815                         if ( $display == 'extensions' ) {
2816                                 $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Extension").": $extdisplay", false), 0);
2817                                 $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Extension")." $extdisplay", $delURL, true, false), 0);
2818                         } else {
2819                                 $currentcomponent->addguielem('_top', new gui_pageheading('title', _("User").": $extdisplay", false), 0);
2820                                 $currentcomponent->addguielem('_top', new gui_link('del', _("Delete User")." $extdisplay", $delURL, true, false), 0);
2821                         }
2822
2823                 } elseif ( $display != 'extensions' ) {
2824                         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add User/Extension")), 0);
2825                 }
2826                
2827                 // Setup vars for use in the gui later on                                                       
2828                 $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
2829                 $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
2830                
2831                 $msgInvalidExtNum = _("Please enter a valid extension number.");
2832                 $msgInvalidCidNum = _("Please enter a valid CID Num Alias (must be a valid number).");
2833                 $msgInvalidExtPwd = _("Please enter valid User Password using numbers only");
2834                 $msgInvalidDispName = _("Please enter a valid Display Name");
2835                 $msgInvalidOutboundCID = _("Please enter a valid Outbound CID");
2836                 $msgInvalidPause = _("Please enter a valid pause time in seconds, using digits only");
2837
2838                 // This is the actual gui stuff
2839                 $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
2840                 $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
2841                
2842                 if ( $display == 'extensions' ) {
2843                         $section = ($extdisplay ? _("Edit Extension") : _("Add Extension"));                   
2844                 } else {
2845                         $section = ($extdisplay ? _("Edit User") : _("Add User"));
2846                 }
2847                 if ( $extdisplay ) {
2848                         $currentcomponent->addguielem($section, new gui_hidden('extension', $extdisplay), 2);
2849                 } else {
2850                         $currentcomponent->addguielem($section, new gui_textbox('extension', $extdisplay, 'User Extension', 'The extension number to dial to reach this user.', '!isInteger()', $msgInvalidExtNum, false), 3);
2851                 }
2852                 if ( $display != 'extensions' ) {
2853                         $currentcomponent->addguielem($section, new gui_password('password', $password, 'User Password', _("A user will enter this password when logging onto a device.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), '!isInteger() && !isWhitespace()', $msgInvalidExtPwd, true));
2854                         // extra JS function check required for blank password warning -- call last in the onsubmit() function
2855                         $currentcomponent->addjsfunc('onsubmit()', "\treturn checkBlankUserPwd();\n", 9);
2856                 }
2857                 $currentcomponent->addguielem($section, new gui_textbox('name', $name, 'Display Name', 'The caller id name for calls from this user will be set to this name. Only enter the name, NOT the number.', '!isCallerID()', $msgInvalidDispName, false));
2858                 $cid_masquerade = (trim($cid_masquerade) == $extdisplay)?"":$cid_masquerade;
2859                 $currentcomponent->addguielem($section, new gui_textbox('cid_masquerade', $cid_masquerade, 'CID Num Alias', 'The CID Number to use for internal calls, if different from the extension number. This is used to masquerade as a different user. A common example is a team of support people who would like their internal callerid to display the general support number (a ringgroup or queue). There will be no effect on external calls.', '!isWhitespace() && !isInteger()', $msgInvalidCidNum, false));
2860                 $currentcomponent->addguielem($section, new gui_textbox('sipname', $sipname, 'SIP Alias', "If you want to support direct sip dialing of users internally or through anonymous sip calls, you can supply a friendly name that can be used in addition to the users extension to call them."));
2861                
2862                 $section = 'Extension Options';
2863                 $currentcomponent->addguielem($section, new gui_textbox('directdid', $directdid, 'Direct DID', "The direct DID that is associated with this extension. The DID should be in the same format as provided by the provider (e.g. full number, 4 digits for 10x4, etc).<br><br>Format should be: <b>XXXXXXXXXX</b><br><br>Leave this field blank to disable the direct DID feature for this extension. All non-numeric characters will be stripped."), 3);
2864                 $currentcomponent->addguielem($section, new gui_textbox('didalert', $didalert, 'DID Alert Info', "Alert Info can be used for distinctive ring on SIP phones. Set this value to the desired Alert Info to be sent to the phone when this DID is called. Leave blank to use default values. Will have no effect if no Direct DID is set"));
2865                 if (function_exists('music_list')) {
2866                     $currentcomponent->addguielem($section, new gui_selectbox('mohclass', $currentcomponent->getoptlist('mohclass'), $mohclass, 'Music on Hold', "Set the MoH class that will be used for calls that come in on this Direct DID. For example, choose a type appropriate for a originating country which may have announcements in their language. Only effects MoH class when the call came in from the Direct DID.", false));
2867                 }
2868                 $currentcomponent->addguielem($section, new gui_textbox('outboundcid', $outboundcid, 'Outbound CID', "Overrides the caller id when dialing out a trunk. Any setting here will override the common outbound caller id set in the Trunks admin.<br><br>Format: <b>\"caller name\" &lt;#######&gt;</b><br><br>Leave this field blank to disable the outbound callerid feature for this user.", '!isCallerID()', $msgInvalidOutboundCID, true));
2869                 $ringtimer = (isset($ringtimer) ? $ringtimer : '0');
2870                 $currentcomponent->addguielem($section, new gui_selectbox('ringtimer', $currentcomponent->getoptlist('ringtime'), $ringtimer, 'Ring Time', "Number of seconds to ring prior to going to voicemail. Default will use the value set in the General Tab. If no voicemail is configured this will be ignored.", false));
2871                 if (!isset($callwaiting)) {
2872                         if ($amp_conf['ENABLECW']) {
2873                                 $callwaiting = 'enabled';
2874                         } else {
2875                                 $callwaiting = 'disabled';
2876                         }
2877                 }
2878                 $currentcomponent->addguielem($section, new gui_selectbox('callwaiting', $currentcomponent->getoptlist('callwaiting'), $callwaiting, 'Call Waiting', "Set the initial/current Call Waiting state for this user's extension", false));
2879
2880                 $section = 'Recording Options';
2881                 $currentcomponent->addguielem($section, new gui_selectbox('record_in', $currentcomponent->getoptlist('recordoptions'), $record_in, 'Record Incoming', "Record all inbound calls received at this extension.", false));
2882                 $currentcomponent->addguielem($section, new gui_selectbox('record_out', $currentcomponent->getoptlist('recordoptions'), $record_out, 'Record Outgoing', "Record all outbound calls received at this extension.", false));
2883
2884                 $section = 'Fax Handling';
2885                 $wait = (isset($wait) ? $wait : '0');
2886                 $currentcomponent->addguielem($section, new gui_selectbox('faxexten', $currentcomponent->getoptlist('faxdestoptions'), $faxexten, 'Fax Extension', "Select 'system' to have the system receive and email faxes.<br><br>The FreePBX default is defined in General Settings.", false), 4);
2887                 $currentcomponent->addguielem($section, new gui_textbox('faxemail', $faxemail, 'Fax Email', "Email address is used if 'system' has been chosen for the fax extension above.<br><br>Leave this blank to use the FreePBX default in General Settings"));
2888                 $currentcomponent->addguielem($section, new gui_selectbox('answer', $currentcomponent->getoptlist('faxdetecttype'), $answer, 'Fax Detection Type', "Selecting Zaptel or NVFax will immediately answer the call and play ringing tones to the caller for the number of seconds in Pause below. Use NVFax on SIP or IAX trunks.", false));
2889                 $currentcomponent->addguielem($section, new gui_textbox('wait', $wait, 'Pause after answer', 'The number of seconds we should wait after performing an Immediate Answer. The primary purpose of this is to pause and listen for a fax tone before allowing the call to proceed.', '!isInteger()', $msgInvalidPause, false));
2890
2891                 $section = 'Privacy';
2892                 $privacyman = (isset($privacyman) ? $privacyman : '0');
2893                 $currentcomponent->addguielem($section, new gui_selectbox('privacyman', $currentcomponent->getoptlist('privyn'), $privacyman, 'Privacy Manager', "If no Caller ID is sent, Privacy Manager will asks the caller to enter their 10 digit phone number. The caller is given 3 attempts.", false), 4);
2894
2895         }
2896 }
2897
2898 function core_users_configprocess() {
2899         if ( !class_exists('agi_asteriskmanager') )
2900                 include 'common/php-asmanager.php';
2901        
2902         //create vars from the request
2903         extract($_REQUEST);
2904        
2905         //make sure we can connect to Asterisk Manager
2906         if (!checkAstMan()) {
2907                 return false;
2908         }
2909
2910         //check if the extension is within range for this user
2911         if (isset($extension) && !checkRange($extension)){
2912                 echo "<script>javascript:alert('". _("Warning! Extension")." ".$extension." "._("is not allowed for your account").".');</script>";
2913                 $GLOBALS['abort'] = true;
2914         } else {
2915                 //if submitting form, update database
2916                 if (!isset($action)) $action = null;
2917                 switch ($action) {
2918                         case "add":
2919                                 if (core_users_add($_REQUEST)) {
2920                                         needreload();
2921                                         redirect_standard_continue();
2922                                 } else {
2923                                         // really bad hack - but if core_users_add fails, want to stop core_devices_add
2924                                         $GLOBALS['abort'] = true;
2925                                 }
2926                         break;
2927                         case "del":
2928                                 core_users_del($extdisplay);
2929                                 core_users_cleanastdb($extdisplay);
2930                                 if (function_exists('findmefollow_del')) {
2931                                     findmefollow_del($extdisplay);
2932                                 }
2933                                 needreload();
2934                                 redirect_standard_continue();
2935                         break;
2936                         case "edit":
2937                                 if (core_users_edit($extdisplay,$_REQUEST)) {
2938                                         needreload();
2939                                         redirect_standard_continue('extdisplay');
2940                                 } else {
2941                                         // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
2942                                         $GLOBALS['abort'] = true;
2943                                 }
2944                         break;
2945                 }
2946         }
2947         return true;
2948 }
2949
2950
2951 function core_devices_configpageinit($dispnum) {
2952         global $currentcomponent;
2953
2954         if ( $dispnum == 'devices' || $dispnum == 'extensions' ) {
2955                 // Setup arrays for device types
2956                 $currentcomponent->addgeneralarray('devtechs');
2957                
2958                 // Some errors for the validation bits
2959                 $msgInvalidDTMFMODE = _("Please enter the dtmfmode for this device");
2960                 $msgInvalidChannel = _("Please enter the channel for this device");
2961                 $msgConfirmSecret = _("You have not entered a Secret for this device, although this is possible it is generally bad practice to not assign a Secret to a device. Are you sure you want to leave the Secret empty?");
2962                 $msgInvalidSecret = _("Please enter a Secret for this device");
2963                
2964                 // zap
2965                 $tmparr = array();
2966                 $tmparr['channel'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidChannel);
2967                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2968                 $tmparr['immediate'] = array('value' => 'no', 'level' => 1);
2969                 $tmparr['signalling'] = array('value' => 'fxo_ks', 'level' => 1);
2970                 $tmparr['echocancel'] = array('value' => 'yes', 'level' => 1);
2971                 $tmparr['echocancelwhenbridged'] = array('value' => 'no', 'level' => 1);
2972                 $tmparr['echotraining'] = array('value' => '800', 'level' => 1);
2973                 $tmparr['busydetect'] = array('value' => 'no', 'level' => 1);
2974                 $tmparr['busycount'] = array('value' => '7', 'level' => 1);
2975                 $tmparr['callprogress'] = array('value' => 'no', 'level' => 1);
2976                 $tmparr['dial'] = array('value' => '', 'level' => 1);
2977                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2978                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2979                 $currentcomponent->addgeneralarrayitem('devtechs', 'zap', $tmparr);
2980                 unset($tmparr);
2981                
2982                 // iax2
2983                 $tmparr = array();
2984                 $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
2985                 $tmparr['notransfer'] = array('value' => 'yes', 'level' => 1);
2986                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
2987                 $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
2988                 $tmparr['type'] = array('value' => 'friend', 'level' => 1);
2989                 $tmparr['port'] = array('value' => '4569', 'level' => 1);
2990                 $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
2991                 $tmparr['disallow'] = array('value' => '', 'level' => 1);
2992                 $tmparr['allow'] = array('value' => '', 'level' => 1);
2993                 $tmparr['dial'] = array('value' => '', 'level' => 1);
2994                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
2995                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
2996                 $currentcomponent->addgeneralarrayitem('devtechs', 'iax2', $tmparr);
2997                 unset($tmparr);
2998
2999                 // sip
3000                 $tmparr = array();
3001                 $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret);
3002                 $tmparr['dtmfmode'] = array('value' => 'rfc2833', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidDTMFMODE );
3003                 $tmparr['canreinvite'] = array('value' => 'no', 'level' => 1);
3004                 $tmparr['context'] = array('value' => 'from-internal', 'level' => 1);
3005                 $tmparr['host'] = array('value' => 'dynamic', 'level' => 1);
3006                 $tmparr['type'] = array('value' => 'friend', 'level' => 1);
3007                 $tmparr['nat'] = array('value' => 'yes', 'level' => 1);
3008                 $tmparr['port'] = array('value' => '5060', 'level' => 1);
3009                 $tmparr['qualify'] = array('value' => 'yes', 'level' => 1);
3010                 $tmparr['callgroup'] = array('value' => '', 'level' => 1);
3011                 $tmparr['pickupgroup'] = array('value' => '', 'level' => 1);
3012                 $tmparr['disallow'] = array('value' => '', 'level' => 1);
3013                 $tmparr['allow'] = array('value' => '', 'level' => 1);
3014                 $tmparr['dial'] = array('value' => '', 'level' => 1);
3015                 $tmparr['accountcode'] = array('value' => '', 'level' => 1);
3016                 $tmparr['mailbox'] = array('value' => '', 'level' => 1);
3017                 $currentcomponent->addgeneralarrayitem('devtechs', 'sip', $tmparr);
3018                 unset($tmparr);
3019
3020                 // custom
3021                 $tmparr = array();
3022                 $tmparr['dial'] = array('value' => '', 'level' => 0);
3023                 $currentcomponent->addgeneralarrayitem('devtechs', 'custom', $tmparr);
3024                 unset($tmparr);
3025                
3026                 // Devices list
3027                 $currentcomponent->addoptlistitem('devicelist', 'sip_generic', _("Generic SIP Device"));
3028                 $currentcomponent->addoptlistitem('devicelist', 'iax2_generic', _("Generic IAX2 Device"));
3029                 $currentcomponent->addoptlistitem('devicelist', 'zap_generic', _("Generic ZAP Device"));
3030                 $currentcomponent->addoptlistitem('devicelist', 'custom_custom', _("Other (Custom) Device"));
3031                 $currentcomponent->setoptlistopts('devicelist', 'sort', false);
3032
3033
3034                 // Option lists used by the gui
3035