diff --git a/app/operator_panel/app_config.php b/app/operator_panel/app_config.php new file mode 100644 index 0000000000..5059f43620 --- /dev/null +++ b/app/operator_panel/app_config.php @@ -0,0 +1,84 @@ + \ No newline at end of file diff --git a/app/operator_panel/app_languages.php b/app/operator_panel/app_languages.php new file mode 100644 index 0000000000..03f2570a72 --- /dev/null +++ b/app/operator_panel/app_languages.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/app/operator_panel/exec.php b/app/operator_panel/exec.php new file mode 100644 index 0000000000..e77a90a57d --- /dev/null +++ b/app/operator_panel/exec.php @@ -0,0 +1,185 @@ +0) { + $switch_cmd = trim(check_str($_GET["cmd"])); + $action = trim(check_str($_GET["action"])); + $data = trim(check_str($_GET["data"])); + $direction = trim(check_str($_GET["direction"])); + $username = $_SESSION['username']; + } + +//authorized commands +// if (stristr($switch_cmd, '&uuid=') == true) { +// //authorized; +// } elseif (stristr($switch_cmd, 'uuid_kill') == true) { +// //authorized; +// } elseif (stristr($switch_cmd, 'uuid_transfer') == true) { +// //authorized; +// } elseif (stristr($switch_cmd, 'uuid_record') == true) { +// //authorized; +// } elseif (stristr($action, 'user_status') == true) { +// //authorized; +// } elseif (stristr($action, 'callcenter_config') == true) { +// //authorized; +// } elseif (stristr($action, 'originate') == true) { +// //authorized; +// } else { +// //not found. this command is not authorized +// echo "access denied"; +// exit; +// } + +if (count($_GET)>0) { + + //setup the event socket connection + $fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']); + + if (stristr($action, 'user_status') == true) { + $user_status = $data; + switch ($user_status) { + case "Available": + $user_status = "Available"; + //update the user state + $cmd = "api callcenter_config agent set state ".$username."@".$_SESSION['domain_name']." Waiting"; + $response = event_socket_request($fp, $cmd); + break; + case "Available_On_Demand": + $user_status = "Available (On Demand)"; + //update the user state + $cmd = "api callcenter_config agent set state ".$username."@".$_SESSION['domain_name']." Waiting"; + $response = event_socket_request($fp, $cmd); + break; + case "Logged_Out": + $user_status = "Logged Out"; + //update the user state + $cmd = "api callcenter_config agent set state ".$username."@".$_SESSION['domain_name']." Waiting"; + $response = event_socket_request($fp, $cmd); + break; + case "On_Break": + $user_status = "On Break"; + //update the user state + $cmd = "api callcenter_config agent set state ".$username."@".$_SESSION['domain_name']." Waiting"; + $response = event_socket_request($fp, $cmd); + break; + case "Do_Not_Disturb": + $user_status = "Do Not Disturb"; + //update the user state + $cmd = "api callcenter_config agent set state ".$username."@".$_SESSION['domain_name']." Waiting"; + $response = event_socket_request($fp, $cmd); + break; + default: + $user_status = ""; + } + } + + //fs cmd + if (strlen($switch_cmd) > 0) { + + //set the status so they are compatible with mod_callcenter + $switch_cmd = str_replace("Available_On_Demand", "'Available (On Demand)'", $switch_cmd); + $switch_cmd = str_replace("Logged_Out", "'Logged Out'", $switch_cmd); + $switch_cmd = str_replace("On_Break", "'On Break'", $switch_cmd); + $switch_cmd = str_replace("Do_Not_Disturb", "'Logged Out'", $switch_cmd); + + /* + //if ($action == "energy") { + //conference 3001-example.org energy 103 + $switch_result = event_socket_request($fp, 'api '.$switch_cmd); + $result_array = explode("=",$switch_result); + $tmp_value = $result_array[1]; + //if ($direction == "up") { $tmp_value = $tmp_value + 100; } + //if ($direction == "down") { $tmp_value = $tmp_value - 100; } + //echo "energy $tmp_value
\n"; + $switch_result = event_socket_request($fp, 'api '.$switch_cmd.' '.$tmp_value); + //} + if ($action == "volume_in") { + $switch_result = event_socket_request($fp, 'api '.$switch_cmd); + $result_array = explode("=",$switch_result); + $tmp_value = $result_array[1]; + if ($direction == "up") { $tmp_value = $tmp_value + 1; } + if ($direction == "down") { $tmp_value = $tmp_value - 1; } + //echo "volume $tmp_value
\n"; + $switch_result = event_socket_request($fp, 'api '.$switch_cmd.' '.$tmp_value); + } + if ($action == "volume_out") { + $switch_result = event_socket_request($fp, 'api '.$switch_cmd); + $result_array = explode("=",$switch_result); + $tmp_value = $result_array[1]; + if ($direction == "up") { $tmp_value = $tmp_value + 1; } + if ($direction == "down") { $tmp_value = $tmp_value - 1; } + //echo "volume $tmp_value
\n"; + $switch_result = event_socket_request($fp, 'api '.$switch_cmd.' '.$tmp_value); + } + */ + + $switch_result = event_socket_request($fp, 'api '.$switch_cmd); + if ($action == "record") { + if (trim($_GET["action2"]) == "stop") { + $x=0; + while (true) { + if ($x > 0) { + $dest_file = $_SESSION['switch']['recordings']['dir']."/archive/".date("Y")."/".date("M")."/".date("d")."/".$_GET["uuid"]."_".$x.".wav"; + } + else { + $dest_file = $_SESSION['switch']['recordings']['dir']."/archive/".date("Y")."/".date("M")."/".date("d")."/".$_GET["uuid"].".wav"; + } + if (!file_exists($dest_file)) { + rename($_SESSION['switch']['recordings']['dir']."/archive/".date("Y")."/".date("M")."/".date("d")."/".$_GET["uuid"].".wav", $dest_file); + break; + } + $x++; + } + } + } + } +} + +?> \ No newline at end of file diff --git a/app/operator_panel/index.php b/app/operator_panel/index.php new file mode 100644 index 0000000000..5b9fbb22f0 --- /dev/null +++ b/app/operator_panel/index.php @@ -0,0 +1,340 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ +include "root.php"; +require_once "resources/require.php"; +require_once "resources/check_auth.php"; + +if (permission_exists('extensions_active_view')) { + //access granted +} +else { + echo "access denied"; + exit; +} + +//add multi-lingual support + include "app_languages.php"; + foreach($text as $key => $value) { + $text[$key] = $value[$_SESSION['domain']['language']['code']]; + } + +require_once "resources/header.php"; +?> + + + + + +"; + echo ""; +} +echo "
"; +// include("index_inc.php"); +echo "
\n"; +echo "

"; + + +require_once "resources/footer.php"; +?> \ No newline at end of file diff --git a/app/operator_panel/index_inc.php b/app/operator_panel/index_inc.php new file mode 100644 index 0000000000..8397474aa3 --- /dev/null +++ b/app/operator_panel/index_inc.php @@ -0,0 +1,267 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ +include "root.php"; +require_once "resources/require.php"; +require_once "resources/check_auth.php"; +require_once "resources/functions/get_call_activity.php"; + +if (permission_exists('extensions_active_view')) { + //access granted +} +else { + echo "access denied"; + exit; +} + +//add multi-lingual support + include "app_languages.php"; + foreach($text as $key => $value) { + $text[$key] = $value[$_SESSION['domain']['language']['code']]; + } + +$activity = get_call_activity(); + +foreach ($activity as $extension => $fields) { + if (substr_count($fields['call_group'], ',')) { + $tmp = explode(',', $fields['call_group']); + foreach ($tmp as $tmp_index => $tmp_value) { + if (trim($tmp_value) == '') { unset($tmp[$tmp_index]); } + else { $groups[] = $tmp_value; } + } + } + else if ($fields['call_group'] != '') { + $groups[] = $fields['call_group']; + } +} +$groups = array_unique($groups); +sort($groups); + +echo ""; +echo " "; +echo " "; +echo " "; +echo "
"; +if (sizeof($groups) > 0) { + echo $text['label-call_group']." "; + echo " \n"; +} +echo "
"; + +echo "".$text['title-operator_panel'].""; +echo "


"; + +foreach ($activity as $extension => $ext) { + unset($block); + + //filter by group, if defined + if ($_REQUEST['group'] != '' && substr_count($ext['call_group'], $_REQUEST['group']) == 0 && !in_array($extension, $_SESSION['user']['extensions'])) { continue; } + + //check if feature code being called + $format_number = (substr($ext['dest'], 0, 1) == '*') ? false : true; + + //determine extension state, direction icon, and displayed name/number for caller/callee + if ($ext['state'] == 'CS_EXECUTE') { + if (($ext['callstate'] == 'RINGING' || $ext['callstate'] == 'EARLY' || $ext['callstate'] == 'RING_WAIT') && $ext['direction'] == 'inbound') { + $ext_state = 'ringing'; + } + else if ($ext['callstate'] == 'ACTIVE' && $ext['direction'] == 'outbound') { + $ext_state = 'active'; + } + else if ($ext['callstate'] == 'RING_WAIT' && $ext['direction'] == 'outbound') { + $ext_state = 'ringing'; + } + else if ($ext['callstate'] == 'ACTIVE' && $ext['direction'] == 'inbound') { + $ext_state = 'active'; + } + if (!$format_number) { + $call_name = 'System'; + $call_number = $ext['dest']; + } + else { + $call_name = $activity[(int) $ext['dest']]['effective_caller_id_name']; + $call_number = format_phone((int) $ext['dest']); + } + $dir_icon = 'outbound'; + } + else if ($ext['state'] == 'CS_CONSUME_MEDIA' || $ext['state'] == 'CS_EXCHANGE_MEDIA') { + if ($ext['state'] == 'CS_CONSUME_MEDIA' && $ext['callstate'] == 'RINGING' && $ext['direction'] == 'outbound') { + $ext_state = 'ringing'; + } + else if ($ext['state'] == 'CS_EXCHANGE_MEDIA' && $ext['callstate'] == 'ACTIVE' && $ext['direction'] == 'outbound') { + $ext_state = 'active'; + } + $dir_icon = 'inbound'; + $call_name = $activity[(int) $ext['cid_num']]['effective_caller_id_name']; + $call_number = format_phone((int) $ext['cid_num']); + } + else { + unset($ext_state, $dir_icon, $call_name, $call_number); + } + + //determine block style by state (if any) + $style = ($ext_state != '') ? "state_".$ext_state : null; + + //determine the call identifier passed on drop + if ($ext['uuid'] == $ext['call_uuid'] && $ext['variable_bridge_uuid'] == '') { // transfer an outbound internal call + $call_identifier = $activity[$call_number]['uuid']; + } + else if (($ext['variable_call_direction'] == 'outbound' || $ext['variable_call_direction'] == 'local') && $ext['variable_bridge_uuid'] != '') { // transfer an outbound external call + $call_identifier = $ext['variable_bridge_uuid']; + } + else { + $call_identifier = $ext['call_uuid']; // transfer all other call types + } + + //determine extension draggable state + if (!in_array($extension, $_SESSION['user']['extensions']) && $ext_state != "ringing") { + $draggable = false; + } + else if ($ext['uuid'] != '' && $ext['call_uuid'] == $ext['uuid'] && $ext['variable_bridge_uuid'] == '') { + $draggable = false; + } + else if ($ext_state == 'ringing' && $ext['variable_call_direction'] == 'local') { + $draggable = false; + } + else if ($ext_state != '' && !$format_number) { + $draggable = false; + } + else { + $draggable = true; + } + + $block .= "
"; // TO + $block .= ""; + $block .= " "; + $block .= " "; + $block .= " "; + $block .= " "; + $block .= "
"; + $block .= " "; // FROM + $block .= ""; + $block .= ""; + $block .= " "; + if ($dir_icon != '') { + $block .= " "; + } + $block .= "
"; + if ($ext_state != '') { + $block .= " "; + $block .= "
".$ext['call_length']."
"; + $block .= " ".$call_name."
".$call_number; + $block .= "
"; + } + else { + if (in_array($extension, $_SESSION['user']['extensions'])) { + $block .= " "; + $block .= "
"; + $block .= " "; + $block .= "
"; + } + } + $block .= "
"; + + if (isset($_GET['debug'])) { + $block .= ""; + $block .= "From ID
    ".$extension."
"; + $block .= "uuid
    ".$ext['uuid']."
"; + $block .= "call_uuid
    ".$ext['call_uuid']."
"; + $block .= "variable_bridge_uuid
    ".$ext['variable_bridge_uuid']."
"; + $block .= "direction
    ".$ext['direction']."
"; + $block .= "variable_call_direction
    ".$ext['variable_call_direction']."
"; + $block .= "state
    ".$ext['state']."
"; + $block .= "cid_num
    ".$ext['cid_num']."
"; + $block .= "dest
    ".$ext['dest']."
"; + $block .= "context
    ".$ext['context']."
"; + $block .= "presence_id
    ".$ext['presence_id']."
"; + $block .= "callstate
    ".$ext['callstate']."
"; + $block .= "
"; + } + $block .= "
"; + + if (in_array($extension, $_SESSION['user']['extensions'])) { + $user_extensions[] = $block; + } + else { + $other_extensions[] = $block; + } +} + + +if (sizeof($user_extensions) > 0) { + echo "
"; + foreach ($user_extensions as $ext_block) { + echo $ext_block; + } + echo "
"; +} + +if ($_REQUEST['group'] != '') { + echo "
"; + echo "".ucwords($_REQUEST['group']).""; + echo "

"; +} +else if (sizeof($user_extensions) > 0) { + echo "
"; + echo "".$text['label-other_extensions'].""; + echo "

"; +} + +if (sizeof($other_extensions) > 0) { + echo "
"; + foreach ($other_extensions as $ext_block) { + echo $ext_block; + } + echo "
"; +} +else { + echo $text['label-no_extensions_found']; +} +echo "

"; + +if (isset($_GET['debug'])) { + echo ""; + echo "

"; + + echo '$_SESSION...'; + echo ""; +} +?> \ No newline at end of file diff --git a/app/operator_panel/resources/functions/get_call_activity.php b/app/operator_panel/resources/functions/get_call_activity.php new file mode 100644 index 0000000000..a55f655aed --- /dev/null +++ b/app/operator_panel/resources/functions/get_call_activity.php @@ -0,0 +1,150 @@ +prepare($sql); + $prep_statement->execute(); + $extensions = $prep_statement->fetchAll(PDO::FETCH_NAMED); + unset ($prep_statement, $sql); + + //send the command + $fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']); + if ($fp) { + $switch_cmd = 'show channels as json'; + $switch_result = event_socket_request($fp, 'api '.$switch_cmd); + $json_array = json_decode($switch_result, true); + } + + //build the response + $x = 0; + foreach($extensions as &$row) { + //add the extension details + $array[$x] = $row; + + //set the call detail defaults + $array[$x]["uuid"] = null; + $array[$x]["direction"] = null; + $array[$x]["created"] = null; + $array[$x]["created_epoch"] = null; + $array[$x]["name"] = null; + $array[$x]["state"] = null; + $array[$x]["cid_name"] = null; + $array[$x]["cid_num"] = null; + $array[$x]["ip_addr"] = null; + $array[$x]["dest"] = null; + $array[$x]["application"] = null; + $array[$x]["application_data"] = null; + $array[$x]["dialplan"] = null; + $array[$x]["context"] = null; + $array[$x]["read_codec"] = null; + $array[$x]["read_rate"] = null; + $array[$x]["read_bit_rate"] = null; + $array[$x]["write_codec"] = null; + $array[$x]["write_rate"] = null; + $array[$x]["write_bit_rate"] = null; + $array[$x]["secure"] = null; + $array[$x]["hostname"] = null; + $array[$x]["presence_id"] = null; + $array[$x]["presence_data"] = null; + $array[$x]["callstate"] = null; + $array[$x]["callee_name"] = null; + $array[$x]["callee_num"] = null; + $array[$x]["callee_direction"] = null; + $array[$x]["call_uuid"] = null; + $array[$x]["sent_callee_name"] = null; + $array[$x]["sent_callee_num"] = null; + + //add the active call details + $found = false; + foreach($json_array['rows'] as &$field) { + $presence_id = $field['presence_id']; + $presence = explode("@", $presence_id); + $presence_id = $presence[0]; + $presence_domain = $presence[1]; + if ($row['extension'] == $presence_id) { + if ($presence_domain == $_SESSION['domain_name']) { + $found = true; + break; + } + } + } + + //normalize the array + if ($found) { + $array[$x]["uuid"] = $field['uuid']; + $array[$x]["direction"] = $field['direction']; + $array[$x]["created"] = $field['created']; + $array[$x]["created_epoch"] = $field['created_epoch']; + $array[$x]["name"] = $field['name']; + $array[$x]["state"] = $field['state']; + $array[$x]["cid_name"] = $field['cid_name']; + $array[$x]["cid_num"] = $field['cid_num']; + $array[$x]["ip_addr"] = $field['ip_addr']; + $array[$x]["dest"] = $field['dest']; + $array[$x]["application"] = $field['application']; + $array[$x]["application_data"] = $field['application_data']; + $array[$x]["dialplan"] = $field['dialplan']; + $array[$x]["context"] = $field['context']; + $array[$x]["read_codec"] = $field['read_codec']; + $array[$x]["read_rate"] = $field['read_rate']; + $array[$x]["read_bit_rate"] = $field['read_bit_rate']; + $array[$x]["write_codec"] = $field['write_codec']; + $array[$x]["write_rate"] = $field['write_rate']; + $array[$x]["write_bit_rate"] = $field['write_bit_rate']; + $array[$x]["secure"] = $field['secure']; + $array[$x]["hostname"] = $field['hostname']; + $array[$x]["presence_id"] = $field['presence_id']; + $array[$x]["presence_data"] = $field['presence_data']; + $array[$x]["callstate"] = $field['callstate']; + $array[$x]["callee_name"] = $field['callee_name']; + $array[$x]["callee_num"] = $field['callee_num']; + $array[$x]["callee_direction"] = $field['callee_direction']; + $array[$x]["call_uuid"] = $field['call_uuid']; + $array[$x]["sent_callee_name"] = $field['sent_callee_name']; + $array[$x]["sent_callee_num"] = $field['sent_callee_num']; + + //calculate and set the call length + $call_length_seconds = time() - $array[$x]["created_epoch"]; + $call_length_hour = floor($call_length_seconds/3600); + $call_length_min = floor($call_length_seconds/60 - ($call_length_hour * 60)); + $call_length_sec = $call_length_seconds - (($call_length_hour * 3600) + ($call_length_min * 60)); + $call_length_min = sprintf("%02d", $call_length_min); + $call_length_sec = sprintf("%02d", $call_length_sec); + $call_length = $call_length_hour.':'.$call_length_min.':'.$call_length_sec; + $array[$x]['call_length'] = $call_length; + + //send the command + if ($field['state'] != '') { + if ($fp) { + $switch_cmd = 'uuid_dump '.$field['uuid'].' json'; + $dump_result = event_socket_request($fp, 'api '.$switch_cmd); + $dump_array = json_decode($dump_result, true); + foreach ($dump_array as $dump_var_name => $dump_var_value) { + $array[$x][$dump_var_name] = trim($dump_var_value); + } + } + } + + } + + //increment the row + $x++; + } + + //reindex array using extension instead of auto-incremented value + foreach ($array as $index => $subarray) { + foreach ($subarray as $field => $value) { + $array[$subarray['extension']][$field] = $array[$index][$field]; + unset($array[$index][$field]); + } + unset($array[$subarray['extension']]['extension']); + unset($array[$index]); + } + + //return array + return $array; +} \ No newline at end of file diff --git a/app/operator_panel/resources/images/inbound.png b/app/operator_panel/resources/images/inbound.png new file mode 100644 index 0000000000..5d4bbf8dfc Binary files /dev/null and b/app/operator_panel/resources/images/inbound.png differ diff --git a/app/operator_panel/resources/images/keypad.png b/app/operator_panel/resources/images/keypad.png new file mode 100644 index 0000000000..b3050e33a4 Binary files /dev/null and b/app/operator_panel/resources/images/keypad.png differ diff --git a/app/operator_panel/resources/images/outbound.png b/app/operator_panel/resources/images/outbound.png new file mode 100644 index 0000000000..900d187503 Binary files /dev/null and b/app/operator_panel/resources/images/outbound.png differ diff --git a/app/operator_panel/resources/images/person.png b/app/operator_panel/resources/images/person.png new file mode 100644 index 0000000000..972bc500ee Binary files /dev/null and b/app/operator_panel/resources/images/person.png differ diff --git a/app/operator_panel/root.php b/app/operator_panel/root.php new file mode 100644 index 0000000000..7b882438ea --- /dev/null +++ b/app/operator_panel/root.php @@ -0,0 +1,50 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ + +// make sure the PATH_SEPARATOR is defined + if (!defined("PATH_SEPARATOR")) { + if ( strpos( $_ENV[ "OS" ], "Win" ) !== false ) { define("PATH_SEPARATOR", ";"); } else { define("PATH_SEPARATOR", ":"); } + } + +// make sure the document_root is set + $_SERVER["SCRIPT_FILENAME"] = str_replace("\\", "/", $_SERVER["SCRIPT_FILENAME"]); + $_SERVER["DOCUMENT_ROOT"] = str_replace($_SERVER["PHP_SELF"], "", $_SERVER["SCRIPT_FILENAME"]); + $_SERVER["DOCUMENT_ROOT"] = realpath($_SERVER["DOCUMENT_ROOT"]); + //echo "DOCUMENT_ROOT: ".$_SERVER["DOCUMENT_ROOT"]."
\n"; + //echo "PHP_SELF: ".$_SERVER["PHP_SELF"]."
\n"; + //echo "SCRIPT_FILENAME: ".$_SERVER["SCRIPT_FILENAME"]."
\n"; + +// if the project directory exists then add it to the include path otherwise add the document root to the include path + if (is_dir($_SERVER["DOCUMENT_ROOT"].'/fusionpbx')){ + if(!defined('PROJECT_PATH')) { define('PROJECT_PATH', '/fusionpbx'); } + set_include_path( get_include_path() . PATH_SEPARATOR . $_SERVER["DOCUMENT_ROOT"].'/fusionpbx' ); + } + else { + if(!defined('PROJECT_PATH')) { define('PROJECT_PATH', ''); } + set_include_path( get_include_path() . PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] ); + } + +?> \ No newline at end of file