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

Revision 7893, 137.4 kB (checked in by p_lindheimer, 3 years 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     $currentcomponent->addoptlistitem('devicetypelist', 'fixed', _("Fixed"));
3036     $currentcomponent->addoptlistitem('devicetypelist', 'adhoc', _("Adhoc"));
3037     $currentcomponent->setoptlistopts('devicetypelist', 'sort', false);
3038    
3039     $currentcomponent->addoptlistitem('deviceuserlist', 'none', _("none"));
3040     $currentcomponent->addoptlistitem('deviceuserlist', 'new', _("New User"));
3041     $users = core_users_list();
3042     if (isset($users)) {
3043       foreach ($users as $auser) {
3044         $currentcomponent->addoptlistitem('deviceuserlist', $auser[0], $auser[0]);
3045       }
3046     }
3047     $currentcomponent->setoptlistopts('deviceuserlist', 'sort', false);
3048
3049     // Add the 'proces' functions
3050     $currentcomponent->addguifunc('core_devices_configpageload');
3051     $currentcomponent->addprocessfunc('core_devices_configprocess');
3052   }
3053 }
3054
3055 function core_devices_configpageload() {
3056   global $currentcomponent;
3057
3058   // Init vars from $_REQUEST[]
3059   $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;;
3060   $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
3061   $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
3062   $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
3063  
3064   if ( $action == 'del' ) { // Deleted
3065
3066     if ( $display != 'extensions' )
3067       $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false));
3068
3069   } elseif ( $extdisplay == '' && $tech_hardware == '' ) { // Adding
3070
3071     if ( $display != 'extensions') {
3072       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add Device")), 0);
3073     } else {
3074       $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add an Extension")), 0);
3075     }
3076     $currentcomponent->addguielem('_top', new gui_label('instructions', _("Please select your Device below then click Submit")));
3077     $currentcomponent->addguielem('Device', new gui_selectbox('tech_hardware', $currentcomponent->getoptlist('devicelist'), '', 'Device', '', false));
3078
3079   } else {
3080
3081     $deviceInfo = array();
3082     if ( $extdisplay ) { // Editing
3083
3084       $deviceInfo = core_devices_get($extdisplay);
3085
3086       if ( $display != 'extensions' ) {
3087         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Device").": $extdisplay", false), 0);
3088
3089         $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del';
3090         $currentcomponent->addguielem('_top', new gui_link('del', _("Delete Device")." $extdisplay", $delURL, true, false), 0);
3091       }
3092  
3093     } else {
3094
3095       $tmparr = explode('_', $tech_hardware);
3096       $deviceInfo['tech'] = $tmparr[0];
3097       $deviceInfo['hardware'] = $tmparr[1];
3098       unset($tmparr);
3099      
3100       if ( $display != 'extensions' ) {
3101         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Device")), 0);
3102       } else {
3103         $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Extension")), 0);
3104       }
3105
3106     }
3107
3108     // Ensure they exist before the extract
3109     $devinfo_description = $devinfo_emergency_cid = null;
3110     $devinfo_devicetype = $devinfo_user = $devinfo_hardware = null;
3111     if ( is_array($deviceInfo) )
3112       extract($deviceInfo, EXTR_PREFIX_ALL, 'devinfo');
3113
3114     // Setup vars for use in the gui later on             
3115     $fc_logon = featurecodes_getFeatureCode('core', 'userlogon');
3116     $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff');
3117
3118     $msgInvalidDevID = _("Please enter a device id.");
3119     $msgInvalidDevDesc = _("Please enter a valid Description for this device");
3120     $msgInvalidEmergCID = _("Please enter a valid Emergency CID");
3121     $msgInvalidExtNum = _("Please enter a valid extension number.");
3122    
3123     // Actual gui
3124     $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add')));
3125     $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay));
3126
3127     if ( $display != 'extensions' ) {
3128       $section = 'Device Info';
3129       if ( $extdisplay ) { // Editing
3130         $currentcomponent->addguielem($section, new gui_hidden('deviceid', $extdisplay));
3131       } else { // Adding
3132         $currentcomponent->addguielem($section, new gui_textbox('deviceid', $extdisplay, 'Device ID', 'Give your device a unique integer ID.  The device will use this ID to authenicate to the system.', '!isInteger()', $msgInvalidDevID, false));
3133       }
3134       $currentcomponent->addguielem($section, new gui_textbox('description', $devinfo_description, 'Description', 'The caller id name for this device will be set to this description until it is logged into.', '!isAlphanumeric() || isWhitespace()', $msgInvalidDevDesc, false));
3135       $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, 'Emergency CID', 'This caller id will always be set when dialing out an Outbound Route flagged as Emergency.  The Emergency CID overrides all other caller id settings.', '!isCallerID()', $msgInvalidEmergCID));
3136       $currentcomponent->addguielem($section, new gui_selectbox('devicetype', $currentcomponent->getoptlist('devicetypelist'), $devinfo_devicetype, 'Device Type', _("Devices can be fixed or adhoc. Fixed devices are always associated to the same extension/user. Adhoc devices can be logged into and logged out of by users.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), false));
3137       $currentcomponent->addguielem($section, new gui_selectbox('deviceuser', $currentcomponent->getoptlist('deviceuserlist'), $devinfo_user, 'Default User', 'Fixed devices will always mapped to this user.  Adhoc devices will be mapped to this user by default.<br><br>If selecting "New User", a new User Extension of the same Device ID will be set as the Default User.', false));
3138     } else {
3139       $section = 'Extension Options';
3140       $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, 'Emergency CID', 'This caller id will always be set when dialing out an Outbound Route flagged as Emergency.  The Emergency CID overrides all other caller id settings.', '!isCallerID()', $msgInvalidEmergCID));
3141     }
3142     $currentcomponent->addguielem($section, new gui_hidden('tech', $devinfo_tech));
3143     $currentcomponent->addguielem($section, new gui_hidden('hardware', $devinfo_hardware));
3144
3145     $section = 'Device Options';
3146     $currentcomponent->addguielem($section, new gui_label('techlabel', sprintf(_("This device uses %s technology."),$devinfo_tech)),4);
3147     $devopts = $currentcomponent->getgeneralarrayitem('devtechs', $devinfo_tech);
3148     foreach ($devopts as $devopt=>$devoptarr) {
3149       $devopname = 'devinfo_'.$devopt;
3150       $devoptcurrent = isset($$devopname) ? $$devopname : $devoptarr['value'];
3151       $devoptjs = isset($devoptarr['jsvalidation']) ? $devoptarr['jsvalidation'] : '';
3152       $devoptfailmsg = isset($devoptarr['failvalidationmsg']) ? $devoptarr['failvalidationmsg'] : '';
3153      
3154       if ( $devoptarr['level'] == 0 || ($extdisplay && $devoptarr['level'] == 1) ) { // editing to show advanced as well
3155         $currentcomponent->addguielem($section, new gui_textbox($devopname, $devoptcurrent, $devopt, '', $devoptjs, $devoptfailmsg), 4);
3156       } else { // add so only basic
3157         $currentcomponent->addguielem($section, new gui_hidden($devopname, $devoptcurrent), 4);
3158       }
3159     }
3160   }
3161 }
3162
3163 function core_devices_configprocess() {
3164   if ( !class_exists('agi_asteriskmanager') )
3165     include 'common/php-asmanager.php';
3166
3167   //make sure we can connect to Asterisk Manager
3168   if (!checkAstMan()) {
3169     return false;
3170   }
3171  
3172   //create vars from the request
3173   extract($_REQUEST);
3174
3175   $extension = isset($extension)?$extension:null;
3176   $deviceid = isset($deviceid)?$deviceid:null;
3177   $name = isset($name)?$name:null;
3178   $action = isset($action)?$action:null;
3179
3180   // fixed users only in extensions mode
3181   if ( $display == 'extensions' ) {
3182     $devicetype = 'fixed';
3183     $deviceid = $deviceuser = $extension;
3184         $description = $name;
3185   }
3186  
3187   //if submitting form, update database
3188   switch ($action) {
3189     case "add":
3190     // really bad hack - but if core_users_add fails, want to stop core_devices_add
3191     if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3192       if (core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid)) {
3193         needreload();
3194         if ($deviceuser != 'new') {
3195           redirect_standard_continue();
3196         }
3197       }
3198     }
3199     break;
3200     case "del":
3201       core_devices_del($extdisplay);
3202       needreload();
3203       redirect_standard_continue();
3204     break;
3205     case "edit":  //just delete and re-add
3206       // really bad hack - but if core_users_edit fails, want to stop core_devices_edit
3207       if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
3208         core_devices_del($extdisplay,true);
3209         core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid,true);
3210         needreload();
3211         redirect_standard_continue('extdisplay');
3212       }
3213       break;
3214       case "resetall":  //form a url with this option to nuke the AMPUSER & DEVICE trees and start over.
3215         core_users2astdb();
3216         core_devices2astdb();
3217       break;
3218   }
3219   return true;
3220 }
3221
3222 ?>
Note: See TracBrowser for help on using the browser.