" . _("Call History") . "
";
    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 = "
";
        }
        else {
          $currentSort = 'asc';
          $arrowImg = " ";
        }   
        if ($i==1) {
          $arrowImg = '';
        }    
      }
      else {
        $arrowImg = '';
        $currentSort = 'desc';
      }
      $unicode_q = urlencode($q);
      $recording_header .= "
";
        }   
        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 History");
    } else {
      $header_text = sprintf(_("Call History 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;
  }
}
?>