root/modules/branches/2.9/core/agi-bin/user_login_out.agi

Revision 11342, 18.2 kB (checked in by p_lindheimer, 2 years ago)

adds a toggle feature code and hints to go in conjunction with Asterisk patch submission 18788 on review board as 1105 re #778

  • Property svn:executable set to *
Line 
1 #!/usr/bin/php -q
2 <?php
3 //This file is part of FreePBX.
4 //
5 //    FreePBX is free software: you can redistribute it and/or modify
6 //    it under the terms of the GNU General Public License as published by
7 //    the Free Software Foundation, either version 2 of the License, or
8 //    (at your option) any later version.
9 //
10 //    FreePBX is distributed in the hope that it will be useful,
11 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //    GNU General Public License for more details.
14 //
15 //    You should have received a copy of the GNU General Public License
16 //    along with FreePBX.  If not, see <http://www.gnu.org/licenses/>.
17 //   
18 //    Copyright 2008 Philippe Lindheimer
19
20     require_once "phpagi.php";
21     require_once "phpagi-asmanager.php";
22
23     /* Usage:
24      *
25      * AGI(user_login_out.agi,login|logout,[user])
26      *
27      * ARG1: action
28      * ARG2: device
29      * ARG3: user
30      *
31      * login:
32      * Login the requested user and set hints appropriately as well as adjust
33      * hints on any previous user that was logged in.
34      *
35      * logout:
36      * Logout the current user and set hints appropriately for that user
37      * as well as logging in the default user (if applicable) and set hints
38      * accordingly
39      */
40     
41     $agi = new AGI();
42
43     // get manager credentials out of the channel
44     //
45     $ampmgruser   = get_var( "AMPMGRUSER" );
46     $ampmgrpass   = get_var( "AMPMGRPASS" );
47     $astspooldir  = get_var( "ASTSPOOLDIR" );
48     $ast_version  = get_var("ASTVERSION");
49     $dnd_devstate = get_var( "DNDDEVSTATE" ) == "TRUE" ? true : false;
50     $cf_devstate = get_var( "CFDEVSTATE" ) == "TRUE" ? true : false;
51     $fm_devstate  = get_var( "FMDEVSTATE" ) == "TRUE" ? true : false;
52     $que_devstate = get_var( "QUEDEVSTATE" ) == "TRUE" ? true : false;
53     $intercom_code = get_var( "INTERCOMCODE" );
54     $campon_toggle = get_var( "CAMPONTOGGLE" );
55
56     $ast_version14 = version_compare($ast_version, "1.4", "ge");
57
58     $DEVSTATE = version_compare($ast_version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE";
59
60     /*
61     $ampmgruser  = 'admin';
62     $ampmgrpass  = 'amp111';
63     */
64     $astman = new AGI_AsteriskManager( );   
65     if (!$astman->connect("127.0.0.1", $ampmgruser , $ampmgrpass)) {
66         exit (1);
67     }
68
69     $action      = get_action();
70     $this_device = get_this_device();
71
72     switch ($action) {
73         case 'login':
74         case 'logon':
75             $new_user = get_login_user();
76             debug("Logging in user $new_user to device $this_device");
77             user_login($this_device, $new_user);
78             break;
79         case 'logout':
80             debug("Logging out current user from device $this_device");
81             user_logout($this_device);
82             break;
83         default:
84             debug("Got unknown action: $action, exiting");
85     }
86     exit;
87
88     /*
89 exten => s,n,System(rm -f ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)})
90 exten => s,n,System(/bin/ln -s ${ASTSPOOLDIR}/voicemail/${DB(AMPUSER/${AMPUSER}/voicemail)}/${AMPUSER}/ ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)})
91 */
92
93
94     // Get the requested action (login or logout)
95     //
96     function get_action() {
97         global $argv;
98         return strtolower(trim($argv['1']));
99         //return get_var('ARG1');
100     }
101
102     // Get the device passed in (basically CID)
103     //
104     function get_this_device() {
105         global $argv;
106         return trim($argv['2']);
107         //return get_var('ARG2');
108     }
109
110     // Get the user to login to a device
111     //
112     function get_login_user() {
113         global $argv;
114         return trim($argv['3']);
115         //return get_var('ARG3');
116     }
117
118     // Login a new user to a device. If there is a current user
119     // log them out first.
120     //
121     function user_login($this_device, $new_user) {
122         debug("user_login: this_device: $this_device, new_user: $new_user",8);
123
124         $current_user = get_logged_in_user($this_device);
125         if ($current_user != $new_user) {
126             if ($current_user != '') {
127                 debug("Logging out current user $current_user from device $this_device so $new_user can login",5);
128                 remove_user($this_device);
129             }
130             insert_user($new_user, $this_device);
131         } else {
132             debug("User $new_user is already logged into device $this_device",5);
133         }
134     }
135
136     // Logout the current user. If device has a default user, log
137     // them in.
138     //
139     function user_logout($this_device) {
140         debug("user_logout: this_device: $this_device",8);
141
142         $current_user = get_logged_in_user($this_device);
143         $default_user = get_default_user($this_device);
144
145         debug("current_user: $current_user, default_user: $default_user",8);
146
147         if ($current_user != $default_user) {
148             remove_user($this_device);
149             if ($default_user != '') {
150                 debug("Logging in default user $default_user to device $this_device",5);
151                 insert_user($default_user, $this_device);
152             }
153         }
154     }
155
156     // Insert a specificed user into a specified device and then
157     // update the hint for that user to reflect the new device(s)
158     // and update the voicemial link
159     //
160     function insert_user($user, $device) {
161         debug("insert_user: user: $user, device: $device",8);
162         global $agi;
163         global $astspooldir;
164         global $fm_devstate;
165         global $dnd_devstate;
166         global $cf_devstate;
167         global $que_devstate;
168         global $DEVSTATE;
169
170         set_device_user($device, $user);
171         $previous_devices = get_devices($user);
172         $new_devices = insert_device($previous_devices,$device);
173         debug("insert_user: Setting user $user to devices $new_devices",5);
174         set_user_devices($user, $new_devices);
175         set_hint($user, $new_devices);
176         if(version_compare(get_var("ASTVERSION"), "1.6.1", "ge")) {
177              $user_event_body = "\"UserDeviceAdded|Data: {$user}\\,{$device}\"";
178          } else if(version_compare(get_var("ASTVERSION"), "1.6.0", "ge")) {
179              $user_event_body = "UserDeviceAdded,\"Data: {$user}\\\\,{$device}\"";
180          } else {
181              $user_event_body = "\"UserDeviceAdded|Data: {$user},{$device}\"";
182          }
183  
184     $agi->exec("UserEvent", $user_event_body);
185
186         if ($fm_devstate) {
187             debug("insert_user: Setting FollowMe DEVSTATES for device $device",5);
188             $agi->set_variable($DEVSTATE.'(Custom:FOLLOWME'.$device.')',get_followme_state($user));
189         }
190         if ($que_devstate) {
191             debug("insert_user: Setting queue DEVSTATES for device $device and user $user",5);
192             set_queue_states($user,$device,'on');
193         }
194         if ($dnd_devstate) {
195             debug("insert_user: Setting DND DEVSTATES for device $device",5);
196             $agi->set_variable($DEVSTATE.'(Custom:DEVDND'.$device.')',get_dnd_state($user));
197         }
198         if ($cf_devstate) {
199             debug("insert_user: Setting CF DEVSTATES for device $device",5);
200             $agi->set_variable($DEVSTATE.'(Custom:DEVCF'.$device.')',get_cf_state($user));
201         }
202
203         $vmcontext = get_voicemail_context($user);
204         if ($vmcontext != 'novm') {
205             exec("/bin/ln -s {$astspooldir}/voicemail/{$vmcontext}/{$user}/ {$astspooldir}/voicemail/device/$device", $output, $ret);
206             if ($ret) {
207                 debug("Got Return code: $ret trying to: /bin/ln -s {$astspooldir}/voicemail/{$vmcontext}/{$user}/ {$astspooldir}/voicemail/device/$device",5);
208             }
209         }
210     }
211
212     // Remove the current user from a device and then update
213     // the hint of that current user to reflect their current devices
214     //
215     function remove_user($device) {
216         debug("remove_user: device: $device",8);
217         global $agi;
218         global $astspooldir;
219         global $fm_devstate;
220         global $dnd_devstate;
221         global $cf_devstate;
222         global $que_devstate;
223         global $DEVSTATE;
224
225         $current_user = get_user($device);
226         if ($current_user != '') {
227             $current_devices = get_devices($current_user);
228             $new_devices = remove_device($current_devices,$device);
229             debug("remove_user: Setting user $current_user to devices $new_devices",5);
230             set_user_devices($current_user, $new_devices);
231             set_hint($current_user, $new_devices);
232             
233             if(version_compare(get_var("ASTVERSION"), "1.6.1", "ge")) {
234                 $user_event_body = "\"UserDeviceRemoved|Data: {$current_user}\\,{$device}\"";
235              } else if(version_compare(get_var("ASTVERSION"), "1.6.0", "ge")) {
236                  $user_event_body = "UserDeviceRemoved,\"Data: {$current_user}\\\\,{$device}\"";
237              } else {
238                  $user_event_body = "\"UserDeviceRemoved|Data: {$current_user},{$device}\"";
239              }
240  
241          $agi->exec("UserEvent", $user_event_body);
242         
243             exec("/bin/rm -f {$astspooldir}/voicemail/device/$device",$output, $ret);
244
245             debug("Setting device $device states to INVALID before deleting them",5);
246             if ($fm_devstate) {
247                 debug("Setting device $device FollowMe state to INVALID before deleting",5);
248                 $agi->set_variable($DEVSTATE.'(Custom:FOLLOWME'.$device.')','INVALID');
249             }
250             if ($que_devstate) {
251                             debug("remove_user: Setting queue DEVSTATES for device $device and user $user",5);
252                 set_queue_states($user,$device,'off');
253                     }
254             if ($dnd_devstate) {
255                 debug("Setting device $device DND state to INVALID before deleting",5);
256                 $agi->set_variable($DEVSTATE.'(Custom:DEVDND'.$device.')','NOT_INUSE');
257             }
258             if ($cf_devstate) {
259                 debug("Setting device $device CF state to INVALID before deleting",5);
260                 $agi->set_variable($DEVSTATE.'(Custom:DEVCF'.$device.')','NOT_INUSE');
261             }
262             // I thought they should then be deleted, but they still end up there probably because setting them to invalid re-creates them
263             //
264             //$agi->database_deltree('CustomDevstate','FOLLOWME'.$device);
265             //$agi->database_deltree('CustomDevstate','DEVDND'.$device);
266             if ($ret) {
267                 debug("Got Return code: $ret trying to remove: {$astspooldir}/voicemail/device/$device",5);
268             }
269             set_device_user($device, 'none');
270         }
271     }
272
273     // Set the hint for a user based on the devices in their AMPUSER object
274     //
275     function set_hint($user, $devices) {
276         debug("set_hint: user: $user, devices: $devices",8);
277         global $astman;
278         global $agi;
279         global $dnd_devstate;
280         global $intercom_code;
281         global $campon_toggle;
282         global $ast_version14;
283
284         // If Asterisk version >= 1.4, syntax change is 'dialplan add extension ...' vs. 'add extension ...'
285         $dp_pre = ($ast_version14) ? 'dialplan ' : '';
286
287         if ($devices) {
288             $dial_string = get_dial_string($devices);
289
290             if ($campon_toggle != 'nocampon' && $campon_toggle != '') {
291         $dev_arr = explode('&',$dial_string);
292         $hint_val = 'ccss:'.implode('&ccss:',$dev_arr);
293                 $response = $astman->send_request('Command',array('Command'=>$dp_pre."add extension {$campon_toggle}{$user},hint,{$hint_val} into ext-local replace"));
294             }
295             if ($dnd_devstate) {
296                 $dial_string .= "&Custom:DND$user";
297             }
298             debug("Setting user $user hint to $dial_string",5);
299             $response = $astman->send_request('Command',array('Command'=>$dp_pre."add extension {$user},hint,{$dial_string} into ext-local replace"));
300             if ($intercom_code != 'nointercom' && $intercom_code != '') {
301                 $response = $astman->send_request('Command',array('Command'=>$dp_pre."add extension {$intercom_code}{$user},hint,{$dial_string} into ext-local replace"));
302             }
303         } else {
304             debug("Removing hint for user $user",5);
305             $response = $astman->send_request('Command',array('Command'=>$dp_pre."remove extension {$user}@ext-local hint"));
306             if ($intercom_code != 'nointercom' && $intercom_code != '') {
307                 $response = $astman->send_request('Command',array('Command'=>$dp_pre."remove extension {$intercom_code}{$user}@ext-local hint"));
308             }
309             if ($campon_toggle != 'nocampon' && $campon_toggle != '') {
310                 $response = $astman->send_request('Command',array('Command'=>$dp_pre."remove extension {$campon_toggle}{$user}@ext-local hint"));
311             }
312         }
313     }
314
315     // Get the actual technology dialstrings from the DEVICE objects (used
316     // to create proper hints)
317     //
318     function get_dial_string($devices) {
319         $dialstring = "";
320
321         debug("get_dial_string: devices: $devices",8);
322         global $agi;
323
324         $device_array = explode( '&', $devices );
325         foreach ($device_array as $adevice) {
326             $dds = $agi->database_get('DEVICE',$adevice.'/dial');
327             $dialstring .= $dds['data'].'&';
328         }
329         return trim($dialstring," &");
330     }
331
332     // Insert a new device into a devices string and return the new string
333     //
334     function insert_device($devices, $new_device) {
335         debug("insert_device: devices: $devices, new_device: $new_device",8);
336
337         // We could just append it but this assures no bugs duplicate the device
338         //
339         if (trim($new_device) != '') {
340             $device_arr = explode('&',$devices);
341             $device_arr[] = $new_device;
342             $device_arr = array_unique($device_arr);
343             return trim(implode('&',$device_arr),'&');
344         } else {
345             return $devices;
346         }
347     }
348
349     // Remove a new device from a devices string and return the new string
350     //
351     function remove_device($devices, $remove_device) {
352         debug("remove_device: devices: $devices, remove_device: $remove_device",8);
353
354         $device_arr = explode('&',$devices);
355         $device_arr_hash = array_flip($device_arr);
356         unset($device_arr_hash[$remove_device]);
357         $new_device_arr = array_flip($device_arr_hash);
358         $new_devices  = implode('&', $new_device_arr);
359         return $new_devices;
360     }
361
362     // Get the currently logged in user of a device returning blank
363     // in no logins
364     //
365     function get_logged_in_user($device) {
366         debug("get_logged_in_user: device: $device",8);
367         global $agi;
368
369         $user = $agi->database_get('DEVICE',$device.'/user');
370         if ($user['result'] == 1 && trim($user['data']) != 'none') {
371             debug("get_logged_in_user: got user: ".$user['data'],8);
372             return trim($user['data']);
373         }
374         return '';
375     }
376
377     // Get the designated default user for the device or blank if none
378     //
379     function get_default_user($device) {
380         debug("get_default_user: device: $device",8);
381         global $agi;
382
383         $default_user = $agi->database_get('DEVICE',$device.'/default_user');
384         if ($default_user['result'] == 1 && trim($default_user['data']) != 'none') {
385             return trim($default_user['data']);
386         }
387         return '';
388     }
389
390     // Get the list of current devices for this user
391     //
392     function get_devices($user) {
393         debug("get_devices: user: $user", 8);
394         global $agi;
395
396         $devices = $agi->database_get('AMPUSER',$user.'/device');
397         if ($devices['result'] == 1) {
398             debug("get_devices: got: ".$devices['data'], 8);
399             return trim($devices['data']);
400         }
401         return '';
402     }
403
404     // Get the voicemail context for this user
405     //
406     function get_voicemail_context($user) {
407         debug("get_voicemail_context: user: $user", 8);
408         global $agi;
409
410         $devices = $agi->database_get('AMPUSER',$user.'/voicemail');
411         if ($devices['result'] == 1) {
412             return trim($devices['data']);
413         }
414         return 'novm';
415     }
416
417     // Get the user currently associated with this device or blank if none
418     //
419     function get_user($device) {
420         debug("get_user: device: $device", 8);
421         global $agi;
422
423         $user = $agi->database_get('DEVICE',$device.'/user');
424         if ($user['result'] == 1 && trim($user['data']) != 'none') {
425             debug("get_user: got: ".$user['data'], 8);
426             return trim($user['data']);
427         }
428         debug("get_user: no user found", 8);
429         return '';
430     }
431
432     function get_followme_state($user) {
433         global $agi;
434
435         $fm_state = $agi->database_get('AMPUSER',$user.'/followme/ddial');
436         if ($fm_state['result'] != 1) {
437             $ret = 'INVALID';
438         } else {
439             switch (trim($fm_state['data'])) {
440                 case 'EXTENSION':
441                     $ret = 'NOT_INUSE';
442                     break;
443                 case 'DIRECT':
444                     $ret = 'INUSE';
445                     break;
446                 default:
447                     $ret = 'INVALID';
448             }
449         }
450         debug("get_followme_state: user $user got state ".$fm_state['data']." returning $ret",8);
451         return $ret;
452     }
453
454     function get_dnd_state($user) {
455         global $agi;
456
457         $dnd_state = $agi->database_get('DND',$user);
458         if ($dnd_state['result'] != 1) {
459             $ret = 'NOT_INUSE';
460         } else {
461             if (strtoupper(trim($dnd_state['data'])) == 'YES') {
462                 $ret = 'INUSE';
463             } else {
464                 $ret = 'NOT_INUSE';
465             }
466         }
467         debug("get_dnd_state: user $user got state ".$dnd_state['data']." returning $ret",8);
468         return $ret;
469     }
470
471     function get_cf_state($user) {
472         global $agi;
473
474         $cf_state = $agi->database_get('CF',$user);
475         if ($cf_state['result'] != 1) {
476             $ret = 'NOT_INUSE';
477         } else {
478             if (trim($cf_state['data']) == '') {
479                 $ret = 'NOT_INUSE';
480             } else {
481                 $ret = 'INUSE';
482             }
483         }
484         debug("get_cf_state: user $user got state ".$cf_state['data']." returning $ret",8);
485         return $ret;
486     }
487
488     // Inserts device info into AMPUSER object for specificed user
489     //
490     function set_user_devices($user, $devices) {
491         debug("set_user_devices: user: $user,  devices: $devices", 8);
492         global $agi;
493         if (empty($devices)) {
494             debug("No more devices associated with $user, deletting /device key", 8);
495             $agi->database_del('AMPUSER',$user.'/device');
496         } else {
497             debug("set_user_devices: assigning $devices to $user /device key", 8);
498             $agi->database_put('AMPUSER',$user.'/device',$devices);
499         }
500     }
501
502     // Inserts user into DEVICE object for specified device
503     //
504     function set_device_user($device, $user) {
505         debug("set_device_user: device: $device,  user: $user", 8);
506         global $agi;
507         $agi->database_put('DEVICE',$device.'/user',$user);
508     }
509
510     // Get a channel variable
511     //
512     function get_var($value) {
513         global $agi;
514
515         $r = $agi->get_variable( $value );
516         if ($r['result'] == 1) {
517             $result = $r['data'];
518             return trim($result);
519         }
520         return '';
521     }
522
523     function debug($string, $level=3) {
524         global $agi;
525         $agi->verbose($string, $level);
526     }
527     
528     // Set States for queues
529     function set_queue_states($user,$device,$onoroff='on') {
530         global $agi;
531         global $astman;
532         global $DEVSTATE;
533         $response = $astman->send_request('Command',array('Command'=>"queue show"));
534         $response1=explode("\n",trim($response['data']));
535         // Lets try and process our results here.
536         $inqueue='false';
537         debug("User is $user");
538         foreach ($response1 as $item) {
539             $item1=trim($item);
540             if ($inqueue == 'false') {
541                 if (ereg('(\\d+)',$item1)) {
542                     preg_match_all ("/(\\d+)/is", $item1,$matches);
543                     if ($matches[1][0] != '') {
544                         $queues[]=$matches[1][0];
545                         $inqueue=$matches[1][0];
546                         $logged_agents_array[$inqueue][]='';
547                     }
548                 }
549             } else {
550                 // We should test to see if the item is an Agent description
551                 if (ereg('Local',$item1)) {
552                     preg_match_all ("/(Local).*?(\\d+)/is", $item1, $matches);
553                     $loggedagent=$matches[2][0];
554                     $item1='ADD';
555                 }
556
557                 switch ($item1) {
558                     case '':
559                         break;
560                     case '\n':
561                         break;
562
563                     case 'No Members':
564                         debug("Queue $inqueue has no one logged in");
565                         $inqueue='false';
566                         break;
567
568                     case 'No Callers':
569                     case 'Callers':
570                         debug("Finished processing members for $inqueue");
571                         $inqueue='false';
572                         break;
573                     case 'ADD':
574                         $logged_agents_array[$inqueue][]=$loggedagent;
575                         debug("Agent $loggedagent in queue $inqueue");
576                     break;
577                     default:
578                         debug("No Matches");
579
580                 }
581             }
582         }
583         debug("Finished sorting");
584         foreach ($queues as $queueno) {
585             debug("Agent is $user");
586             if ($onoroff=='on'){
587                 $queuestat=(array_search(trim($user),$logged_agents_array[$queueno]))?'INUSE':'NOT_INUSE';
588             } else {
589                 $queuestat=(array_search(trim($user),$logged_agents_array[$queueno]))?'INUSE':'NOT_INUSE';
590             }
591             $agi->set_variable($DEVSTATE.'(Custom:QUEUE'.$device.'*'.$queueno.')',$queuestat);
592         }
593     }
594         
595
Note: See TracBrowser for help on using the browser.