" . _("Call Monitor") . "
";
return $ret;
}
/*
* Acts on the selected call monitor recordings in the method indicated by the action and updates page
*
* @param $args
* Common arguments
*/
function recAction($args) {
// args
$m = getArgument($args,'m');
$a = getArgument($args,'a');
$q = getArgument($args,'q');
$start = getArgument($args,'start');
$span = getArgument($args,'span');
$order = getArgument($args,'order');
$sort = getArgument($args,'sort');
$duration_filter = getArgument($args,'duration_filter');
// get files
$files = array();
foreach($_REQUEST as $key => $value) {
if (preg_match('/selected/',$key)) {
array_push($files, $value);
}
}
if ($a=='delete') {
$this->deleteRecData($files);
}
if ($a=='ignore') {
$start = 0;
setcookie("ari_duration_filter", $duration_filter, time()+365*24*60*60);
}
// redirect to see updated page
$ret .= "
";
return $ret;
}
/*
* Displays stats page
*
* @param $args
* Common arguments
*/
function display($args) {
global $ASTERISK_CALLMONITOR_PATH;
global $CALLMONITOR_ALLOW_DELETE;
global $AJAX_PAGE_REFRESH_ENABLE;
$display = new DisplaySearch();
// get the search string
$m = getArgument($args,'m');
$f = getArgument($args,'f');
$q = getArgument($args,'q');
$start = getArgument($args,'start');
$span = getArgument($args,'span');
$order = getArgument($args,'order');
$sort = getArgument($args,'sort');
$duration_filter = getArgument($args,'duration_filter');
$start = $start=='' ? 0 : $start;
$span = $span=='' ? 15 : $span;
$order = $order=='' ? 'calldate' : $order;
$sort = $sort=='' ? 'desc' : $sort;
$displayname = $_SESSION['ari_user']['displayname'];
$extension = $_SESSION['ari_user']['extension'];
// get data
$record_count = $this->getCdrCount($q,$duration_filter);
$data = $this->getCdrData($q,$duration_filter,$start,$span,$order,$sort);
// get the call monitor recording files
$paths = split(';',$ASTERISK_CALLMONITOR_PATH);
foreach($paths as $key => $path) {
if (!is_dir($path)) {
$_SESSION['ari_error'] .= sprintf(_("Path is not a directory: %s"),$path) . "
";
}
}
$recordings = $this->getRecordings($ASTERISK_CALLMONITOR_PATH,$data);
// build controls
if ($CALLMONITOR_ALLOW_DELETE) {
$controls .= "
";
}
$controls .= "
" . _("duration") . "
";
// table header
if ($CALLMONITOR_ALLOW_DELETE) {
$recording_delete_header = " | ";
}
$fields[0]['field'] = "calldate";
$fields[0]['text'] = _("Date");
$fields[1]['field'] = "calldate";
$fields[1]['text'] = _("Time");
$fields[2]['field'] = "clid";
$fields[2]['text'] = _("Caller ID");
$fields[3]['field'] = "src";
$fields[3]['text'] = _("Source");
$fields[4]['field'] = "dst";
$fields[4]['text'] = _("Destination");
$fields[5]['field'] = "dcontext";
$fields[5]['text'] = _("Context");
$fields[6]['field'] = "duration";
$fields[6]['text'] = _("Duration");
$i = 0;
while ($fields[$i]) {
$field = $fields[$i]['field'];
$text = $fields[$i]['text'];
if ($order==$field) {
if ($sort=='asc') {
$currentSort = 'desc';
$arrowImg = "";
}
else {
$currentSort = 'asc';
$arrowImg = "";
}
if ($i==1) {
$arrowImg = '';
}
}
else {
$arrowImg = '';
$currentSort = 'desc';
}
$unicode_q = urlencode($q);
$recording_header .= "" . $text . $arrowImg . " | ";
$i++;
}
$recording_header .= "" . _("Monitor") . " | ";
// table body
foreach($data as $key=>$value) {
// recording file
$recording = $recordings[$value['uniqueid'] . $value['calldate']];
// date and time
$buf = split(' ', $value[calldate]);
$date = $buf[0];
$time = $buf[1];
// recording delete checkbox
if ($CALLMONITOR_ALLOW_DELETE) {
$recording_delete_checkbox = " | ";
}
$recordingLink = '';
if (is_file($recordings[$value['uniqueid'] . $value['calldate']])) {
$recordingLink = "" . _("play") . "";
}
$recording_body .= "
" . $recording_delete_checkbox . "
" . $date . " |
" . $time . " |
" . $value[clid] . " |
" . $value[src] . " |
" . $value[dst] . " |
" . $value[dcontext] . " |
" . $value[duration] . " sec |
" . $recordingLink . " |
";
}
if (!count($data)) {
$recording_body .= "
";
}
// options
$url_opts = array();
$url_opts['sort'] = $sort;
$url_opts['order'] = $order;
$url_opts['duration_filter'] = $duration_filter;
// build page content
$ret .= checkErrorMessage();
// ajax page refresh script
if ($AJAX_PAGE_REFRESH_ENABLE) {
// $ret .= ajaxRefreshScript($args);
}
// header
if ($_SESSION['ari_user']['admin_callmonitor']) {
$header_text = _("Call Monitor");
} else {
$header_text = sprintf(_("Call Monitor for %s (%s)"),$displayname,$extension);
}
$ret .= $display->displayHeaderText($header_text);
$ret .= $display->displaySearchBlock('left',$m,$q,$url_opts,true);
// start form
if ($CALLMONITOR_ALLOW_DELETE) {
$ret .= "
";
}
$ret .= $display->displaySearchBlock('center',$m,$q,$url_opts,false);
$ret .= $display->displayNavigationBlock($m,$q,$url_opts,$start,$span,$record_count);
return $ret;
}
/*
* Checks for a recording file
*
* @param $asterisk_callmonitor_path
* path call monitor recording directory on the asterisk server
* @param $data
* current call monitor recordings on the asterisk server
* @return $recording
* returns an array of $recording file names if found
*/
function getRecordings($asterisk_callmonitor_path,$data) {
global $CALLMONITOR_ONLY_EXACT_MATCHING;
global $CALLMONITOR_AGGRESSIVE_MATCHING;
$recordings = array();
$extension = $_SESSION['ari_user']['extension'];
$paths = split(';',$asterisk_callmonitor_path);
foreach($paths as $key => $path) {
$paths[$key] = fixPathSlash($paths[$key]);
}
$files = array();
if (!$CALLMONITOR_ONLY_EXACT_MATCHING) {
$filter = '';
$recursiveMax = 6;
$recursiveCount = 0;
foreach($paths as $key => $path) {
$path_files = getFiles($path,$filter,$recursiveMax,$recursiveCount);
if ($path_files) {
$files = array_merge($files,$path_files);
}
}
rsort($files);
}
foreach($data as $data_key => $data_value) {
$recording='';
$calldate = $data_value['calldate'];
$duration = $data_value['duration'];
$lastdata = $data_value['lastdata'];
$uniqueid = $data_value['uniqueid'];
$userfield = $data_value['userfield'];
// timestamps
$st = trim(strtotime($calldate));
$et = trim(strtotime($calldate) + $duration); // for on-demand call recordings
// unique file key
if ($uniqueid) {
$buf = preg_replace('/\-|\:/', '', $calldate);
$calldate_key = preg_replace('/\s+/', '-', $buf);
$unique_file_key = $calldate_key . "-" . $uniqueid;
}
if ($unique_file_key=='') {
$buf = preg_split("/\|/", $lastdata);
$unique_file_key = $buf[1];
}
$recordingLink = '';
foreach($paths as $callmonitor_key => $path) {
// try to find an exact match using the uniqueid
if (isset($uniqueid)) {
$check_files = array();
array_push($check_files,$path . $uniqueid . ".WAV");
array_push($check_files,$path . $uniqueid . ".wav");
array_push($check_files,$path . $uniqueid . ".gsm");
array_push($check_files,$path . $unique_file_key . ".WAV");
array_push($check_files,$path . $unique_file_key . ".wav");
array_push($check_files,$path . $unique_file_key . ".gsm");
array_push($check_files,$path . "g" . $extension . "-" . $unique_file_key . ".WAV");
array_push($check_files,$path . "g" . $extension . "-" . $unique_file_key . ".wav");
array_push($check_files,$path . "g" . $extension . "-" . $unique_file_key . ".gsm");
array_push($check_files,$path . "q" . $extension . "-" . $unique_file_key . ".WAV");
array_push($check_files,$path . "q" . $extension . "-" . $unique_file_key . ".wav");
array_push($check_files,$path . "q" . $extension . "-" . $unique_file_key . ".gsm");
array_push($check_files,$path . "OUT" . $extension . "-" . $unique_file_key . ".WAV");
array_push($check_files,$path . "OUT" . $extension . "-" . $unique_file_key . ".wav");
array_push($check_files,$path . "OUT" . $extension . "-" . $unique_file_key . ".gsm");
array_push($check_files,$path . $userfield);
// try to match
foreach($check_files as $check_file) {
if (is_file($check_file)) {
$recording = $check_file;
break;
}
}
}
// if found do not need to check the rest of the paths
if ($recording!='') {
break;
}
}
// get all the callmonitor recordings on server and try to find a non-exact match for this log entry
if (!$CALLMONITOR_ONLY_EXACT_MATCHING) {
// try to find a file using the uniqueid
if (!$recording) {
// try and match the unique id
if (!$recording) {
foreach($files as $key => $path) {
if (strlen($uniqueid)>1 && strpos($path,$uniqueid)!==FALSE) {
$recording = $path;
$files[$key] = ''; // remove it from the recording files so it will not be matched twice
break;
}
}
}
}
// try and match a file using the calldate (if no unique number from database)
if (!$recording) {
foreach($files as $key => $path) {
$parts = split("-", $path);
if (strlen($st)>1 &&
(strpos($path,$st)!==FALSE) ||
(strpos($path,"auto")!==FALSE && $parts[1] >= $st && $parts[1] <= $et)) {
$recording = $path;
$files[$key] = ''; // remove it from the recording files so it will not be matched twice
break;
}
}
}
if ($CALLMONITOR_AGGRESSIVE_MATCHING) {
// one last stab at finding a recording by adding one or two seconds to the call time
if (!$recording) {
$st_1 = trim($st+1);
$st_2 = trim($st+2);
$et_1 = trim($et+1);
$et_2 = trim($et+2);
foreach($files as $key => $path) {
$split = explode("-", $path);
if (strlen($st)>1
&& ((strpos($path,$st_1)!==FALSE) ||
(strpos($path,$st_2)!==FALSE) ||
(strpos($path,"auto")!==FALSE && $parts[1] >= $st_1 && $parts[1] <= $et_1) ||
(strpos($path,"auto")!==FALSE && $parts[1] >= $st_2 && $parts[1] <= $et_2))) {
$recording = $path;
$files[$key] = ''; // remove it from the recording files so it will not be matched twice
break;
}
}
}
}
}
// add to array to be returned
if ($recording) {
$recordings[$uniqueid . $calldate] = $recording;
}
}
return $recordings;
}
/*
* Deletes selected call monitor recordings
*
* @param $files
* Array of files to delete
*/
function deleteRecData($files) {
foreach($files as $key => $file) {
if (is_writable($file)) {
unlink($file);
} else {
$_SESSION['ari_error'] = _("Only deletes recording files, not cdr log");
}
}
}
/*
* Gets cdr record count
*
* @param $q
* query text
*/
function getSearchText($q,$duration_filter) {
// search text
if ($q!='*' && $q!=NULL) {
$searchText .= "WHERE ";
$tok = strtok($q," \n\t");
while ($tok) {
$searchText .= " (calldate regexp '" . $tok . "'
OR clid regexp '" . $tok . "'
OR src regexp '" . $tok . "'
OR dst regexp '" . $tok . "'
OR dstchannel regexp '" . $tok . "'
OR dcontext regexp '" . $tok . "'
OR duration regexp '" . $tok . "'
OR disposition regexp '" . $tok . "'
OR uniqueid regexp '" . $tok . "'
OR userfield regexp '" . $tok . "'
)";
$tok = strtok(" \n\t");
if ($tok) {
$searchText .= " AND";
}
}
}
// duration_filter
if ($duration_filter) {
if (!$searchText) {
$searchText .= "WHERE ";
} else {
$searchText .= "AND ";
}
$searchText .= "duration>" . $duration_filter . " ";
}
// admin
if (!$_SESSION['ari_user']['admin_callmonitor']) {
if (!$searchText) {
$searchText .= "WHERE ";
} else {
$searchText .= "AND ";
}
// allow entries to be viewed with users extension
$searchText .= "(src = '" . $_SESSION['ari_user']['extension'] . "'
OR dst = '" . $_SESSION['ari_user']['extension'] . "'
OR channel LIKE 'IAX2/" . $_SESSION['ari_user']['extension'] ."-%'
OR dstchannel LIKE 'IAX2/" . $_SESSION['ari_user']['extension'] ."-%'
OR channel LIKE 'SIP/" . $_SESSION['ari_user']['extension'] ."-%'
OR dstchannel LIKE 'SIP/" . $_SESSION['ari_user']['extension'] ."-%')";
// allow entries to be viewed with users outbound CID
if (isset($_SESSION['ari_user']['outboundCID']) && trim($_SESSION['ari_user']['outboundCID']) != '') {
$searchText .= "OR (src = '" . $_SESSION['ari_user']['outboundCID'] . "'
OR dst = '" . $_SESSION['ari_user']['outboundCID'] . "')";
}
}
return $searchText;
}
/*
* Gets cdr record count
*
* @param $q
* query text
* @return $count
* Number of cdr records counted
*/
function getCdrCount($q,$duration_filter) {
global $ASTERISKCDR_DBTABLE;
$searchText = $this->getSearchText($q,$duration_filter);
$dbh = $_SESSION['dbh_cdr'];
$sql = "SELECT count(*)
FROM " . $ASTERISKCDR_DBTABLE . "
" . $searchText;
$result = $dbh->getAll($sql);
if (DB::isError($result)) {
$_SESSION['ari_error'] = $result->getMessage();
return;
}
$count = $result[0][0];
return $count;
}
/*
* Gets cdr data
*
* @param $q
* query text
* @param $start
* start record
* @param $span
* number of records to return
* @return $data
* cdr data to be returned
*/
function getCdrData($q,$duration_filter,$start,$span,$order,$sort) {
global $ASTERISKCDR_DBTABLE;
$data = array();
$searchText = $this->getSearchText($q,$duration_filter);
$dbh = $_SESSION['dbh_cdr'];
$sql = "SELECT *
FROM " . $ASTERISKCDR_DBTABLE . "
" . $searchText . "
ORDER BY " . $order . " " . $sort . "
LIMIT " . $start . "," . $span;
$result = $dbh->getAll($sql,DB_FETCHMODE_ASSOC);
if (DB::isError($result)) {
$_SESSION['ari_error'] = $result->getMessage();
return;
}
$data = $result;
return $data;
}
}
?>