CDR мой вариант

Обсуждаем, спрашиваем, помогаем в настройке VoIP

CDR мой вариант

Сообщение dimondack » 23 июн 2019, 12:49

Вот мой вариант CDR viewer

вот такая у меня таблица в базе
Код: Выделить всё
CREATE TABLE `cdr` (
  `accountcode` varchar(80) DEFAULT NULL,
  `src` varchar(80) DEFAULT NULL,
  `dst` varchar(80) DEFAULT NULL,
  `dcontext` varchar(80) DEFAULT NULL,
  `clid` varchar(80) DEFAULT NULL,
  `channel` varchar(80) DEFAULT NULL,
  `dstchannel` varchar(80) DEFAULT NULL,
  `lastapp` varchar(80) DEFAULT NULL,
  `lastdata` varchar(80) DEFAULT NULL,
  `start` datetime DEFAULT NULL,
  `answer` datetime DEFAULT NULL,
  `end` datetime DEFAULT NULL,
  `duration` int(11) DEFAULT NULL,
  `billsec` int(11) DEFAULT NULL,
  `disposition` varchar(45) DEFAULT NULL,
  `amaflags` varchar(45) DEFAULT NULL,
  `userfield` varchar(256) DEFAULT NULL,
  `uniqueid` varchar(150) DEFAULT NULL,
  `linkedid` varchar(150) DEFAULT NULL,
  `peeraccount` varchar(80) DEFAULT NULL,
  `sequence` int(11) DEFAULT NULL,
  `recordingfile` varchar(256) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


файл cdr_mysql.conf
Код: Выделить всё
[global]
hostname=localhost
dbname=asterisk
table=cdr
password=asterisk
user=asterisk
port=3306
sock=/tmp/mysql.sock

[columns]
.......
.......
;добавил вот такую запись
alias recfile => recordingfile
........
........



в контексты пишу такие строчки
Код: Выделить всё
[context]
exten => _X.,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M%S)}-${CALLERID(number)}-${EXTEN})
exten => _X.,n,MixMonitor(/var/spool/asterisk/monitor/${fname}.wav)
exten => _X.,n,Set(CDR(recfile)=/var/spool/asterisk/monitor/${fname}.wav)
.......
.......



подключаемся к базе и печатаем
Код: Выделить всё
<?php

function con_base()
{

$d= date("Y-m-d");
$nd= "'".$d." "."00:00:00"."'";
$link = mysqli_connect(
            'localhost',  /* Хост, к которому мы подключаемся */
            'asterisk',       /* Имя пользователя */
            'asterisk',   /* Используемый пароль */
            'asterisk');     /* База данных для запросов по умолчанию */
 
if (!$link) {
   printf("Невозможно подключиться к базе данных. Код ошибки: %s\n", mysqli_connect_error());
   //   print("Невозможно подключиться к базе данных. Код ошибки: %s\n", mysqli_connect_error());

   exit;
}

return $link;

}


function uregsqli($tabl,$src,$dst,$d_from,$d_to,$lm,$ind)
{

$cnt_full =0;
$cnt_answer = 0;
$cnt_no_answer =0;
$cnt_busy =0;
$cnt_congest=0;
$cnt_fail =0;

$today = date("H:m:s  Y-m-d  D");


$link=con_base();

switch($ind){

case 0: $result = mysqli_query($link, "SELECT start, src, dst, billsec, disposition, recordingfile
FROM $tabl ORDER BY start  DESC LIMIT $lm"); break;

case 1: $result = mysqli_query($link, "SELECT start, src, dst, billsec, disposition, recordingfile
FROM $tabl WHERE start BETWEEN   '$d_from' AND '$d_to'"); break;

case 2: $result = mysqli_query($link, "SELECT start, src, dst, billsec, disposition, recordingfile
FROM $tabl WHERE start BETWEEN   '$d_from' AND '$d_to' AND src like '%$src%'"); break;


case 3: $result = mysqli_query($link, "SELECT start, src, dst, billsec, disposition, recordingfile
FROM $tabl WHERE start BETWEEN   '$d_from' AND '$d_to' AND dst like '%$dst%'"); break;


case 4: $result = mysqli_query($link, "SELECT start, src, dst, billsec, disposition, recordingfile
FROM $tabl WHERE start BETWEEN   '$d_from' AND '$d_to' AND src like '%$src%' AND dst like '%$dst%' ");

default: break;
}


 
 // На печать
       
 //        print "Rezult OK";echo '<br>';
   /* Выводим результаты в html */
    echo '<br>';
        echo '<br>';
       
print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">'.$today.'</td>';
print '</table>';

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td bgcolor="#F08080" width="5%" align="center">'."Дата Время".'</td>';
print '<td bgcolor="#F08080" width="10%" align="center">'."Кто звонил".'</td>'; 
print '<td bgcolor="#F08080" width="10%" align="center">'."Куда Звонил".'</td>';
print '<td bgcolor="#F08080" width="10%" align="center">'."Длительность, сек".'</td>';
print '<td bgcolor="#F08080" width="10%" align="center">'."Результат".'</td>';
print '<td bgcolor="#F08080" width="10%" align="center">'."Player".'</td>';
 
   while( $row = mysqli_fetch_assoc($result) ){
 
    print '<tr>';
   
      print '<td  width="5%" valign="top" align="left">'.$row['start'].'</td>';
      
   
      print '<td width="10%" align="center">'.$row['src'].'</td>'; 
      print '<td width="10%" align="center">'.$row['dst'].'</td>';
                print '<td width="10%" valign="center" align="center">'.$row['billsec'].'</td>';


           $cnt_full=$cnt_full + 1;
      switch($row['disposition'])
   
      {
  case 'ANSWERED':
        print '<td  bgcolor="#00FF00" width="10%" align="center">'.$row['disposition'].'</td>';

      $cnt_answer=$cnt_answer + 1;
   break;
 
  case 'NO ANSWER':
        print '<td  bgcolor="#FF00FF" width="10%" align="center">'.$row['disposition'].'</td>';

      $cnt_no_answer=$cnt_no_answer + 1;
   break;
 
  case 'BUSY':
        print '<td  bgcolor="#FFFF00" width="10%" align="center">'.$row['disposition'].'</td>';
//      print '</tr>';
      $cnt_busy=$cnt_busy + 1;
   break;
 
  case 'CONGESTION':
        print '<td  bgcolor="#FF0000" width="10%" align="center">'.$row['disposition'].'</td>';
//      print '</tr>';
      $cnt_congest=$cnt_congest + 1;
   break;
 
 case 'FAILED':
        print '<td  bgcolor="#FF0000" width="10%" align="center">'.$row['disposition'].'</td>';
//      print '</tr>';
      $cnt_fail=$cnt_fail + 1;
 break;
 
 default:
         print '<td  bgcolor="#FF00FF" width="10%" align="center">*******</td>';
//       print '</tr>';
    
         
      }
      
print '<td width="10%" valign="center" align="center">';
print '<audio src="download.php?audio='.$row['recordingfile'].'" preload="none" controls></audio>';
print '</td>';
print '</tr>';
    }
        
//  end печать   
  print '</table>';   

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">';
print  "Выведено записей: ".$cnt_full."\n";
print '</td>';
print '</table>';

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">';
print  "Завершенных ответом: ".$cnt_answer."\n";
print '</td>';
print '</table>';

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">';
print  "Оставшиеся без ответа : ".$cnt_no_answer."\n";
print '</td>';
print '</table>';

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">';
print  "Неотвеченных вследствие перегрузки  : ".$cnt_congest."\n";
print '</td>';
print '</table>';

print '<table border="1" cellpadding="7" cellspacing="0">';
print '<td width="1%" align="left">';
print  "Неотвеченных из-за отказа : ".$cnt_fail."\n";
print '</td>';
print '</table>';

 
//print '</table>';   
 
   /* Освобождаем используемую память */
    mysqli_free_result($result);
 
 
   
     
/* Закрываем соединение */
mysqli_close($link);
}

 
?>



скачиваем файл с записью
Код: Выделить всё
<?php
$file = ($_REQUEST['audio']);
$file = str_replace(" ","+",$file);
header ("Content-Type: application/octet-stream");
header ("Accept-Ranges: bytes");
header ("Content-Length: ".filesize($file));
header ("Content-Disposition: attachment; filename=".$file);
readfile($file);
?>



Полезные источники:
http://subnets.ru/blog/?p=4872
https://github.com/prog-it/Asterisk-CDR-Viewer-Mod
https://www.dmosk.ru/miniinstruktions.php?mini=asterisk-mysql
https://www.google.com
Вложения
deos.zip
файлы
(69.85 Кб) Скачиваний: 51
111.jpg
Мой cdr
Нас определяет то, что мы делаем.
Аватара пользователя
dimondack
новичок
 
Сообщения: 91
Зарегистрирован: 21 янв 2015, 13:00

Re: CDR мой вариант

Сообщение root » 26 июн 2019, 10:29

Ну если закрыть глаза на проблемы с безопасностью (есть возможность sql инъекции), отсутствие проверок используемых переменных и очень слабый обработчик ошибок, то вполне жизнеспособный способ, но только для собственного использования. Выставлять такое наружу = 100% взлом.

Еще одно:
dimondack писал(а):
Код: Выделить всё
readfile($file);

При чтении больших (по размеру) аудио записей могут возникнуть проблемы. Заменить на:
Код: Выделить всё
$fp = fopen($file, 'rb');
while ( $bt=fread( $fp, 8192 ) ){
      print $bt;
}

И тут тоже не помешал бы обработчик на проверку существования файла, удостовериться что это аудио файл, а не /etc/passwd и что fopen успешно открыл файл.
С уважением, root

Изображение
------------
www.mega-net.ru - IT аутсорсинг
Аватара пользователя
root
Site Admin
 
Сообщения: 1882
Зарегистрирован: 11 июн 2008, 13:05
Откуда: Moscow, Russia

Re: CDR мой вариант

Сообщение dimondack » 28 июн 2019, 22:06

Честно говоря, долго я мучился с плеером , точнее как его на страницу вывести... :)
а все было под рукой <audio>

делал для локального использования,

спасибо за оценку.
Нас определяет то, что мы делаем.
Аватара пользователя
dimondack
новичок
 
Сообщения: 91
Зарегистрирован: 21 янв 2015, 13:00

Re: CDR мой вариант

Сообщение root » 29 июн 2019, 09:11

Пожалуйста.
Все же лучше переписать и устранить уязвимости.
Ведь недоброжелатели могут быть и внутри, а не только снаружи или небольшая ошибка в конфиге службы http и этот интерфейс может стать доступным из-вне.
Хотя бы чтение любого файла в твоей системе исправь. Это мега дЫриЩа. Самый простой способ передавать не полный путь к файлу, а относительный. При чтении папку /var/spool/asterisk/monitor хардкоднуть.
С уважением, root

Изображение
------------
www.mega-net.ru - IT аутсорсинг
Аватара пользователя
root
Site Admin
 
Сообщения: 1882
Зарегистрирован: 11 июн 2008, 13:05
Откуда: Moscow, Russia

Re: CDR мой вариант

Сообщение dimondack » 29 июн 2019, 20:35

и вот что у меня получилось

обработка input -ов
Код: Выделить всё
if(preg_match('/^[0-9]$/',$cnt_rec ) === false){ exit; } // здесь знак + не используется
if(preg_match('/^[0-9]+$/',$src ) === false){ exit; }  // да, и тут можно было бы обойтись без него
if(preg_match('/^[0-9]+$/',$dst ) === false){ exit; }  // ......



по чтению файлов
Код: Выделить всё
$rec = substr($row['recordingfile'],28); // отрезал /var/spool/asterisk/monitor
print '<audio src="d2.php?audio='.$rec.'" preload="none" controls></audio>';



теперь сам d2.php
Код: Выделить всё
<?php
$file = ($_REQUEST['audio']);
//$param = ($_REQUEST['param']);

$file = str_replace(" ","+",$file);
//Test any file
//$file = 'e112';
// тут у меня ссылка рядышком
// lrwxr-xr-x  1 root  vv        28 29 июня  14:31 rec -> /var/spool/asterisk/monitor/
$file = 'rec/'.$file;

header ("Content-Type: application/octet-stream");
header ("Accept-Ranges: bytes");
header ("Content-Length: ".filesize($file));
header ("Content-Disposition: attachment; filename=".$file);

$fp = fopen($file, 'rb');

$tmp_f = fopen('tmp.log','a+'); // буду логи записывать
$d = date('Ymd__H_i_s');
$wf = $d."\t"."Wrong format file\n";
$hh = $d."\t"."Mess with the best -- dead like the rest\n";
$pd = getmypid();
$cu = get_current_user();
$usr = "uid=".getmyuid().",gid=".getmygid().",user=".$cu.",pid=".$pd;
$err =$d."\t"."File - ".substr($file,4)." - not opened  ".$usr."  \n";
$ok = $d."\t"."File - ".substr($file,4)." - opened ".$usr."  \n";
if(!$fp){ fwrite($tmp_f,$err); exit ('File not opened'); }
else{ fwrite($tmp_f, $ok);}

//////////////Test wav////////
$d=$data=$format=$bit=$chn="0";
fseek($fp, 20); $d = fread($fp, 18);
$data = unpack('vfmt/vch/Vsr/Vdr/vbs/vbis/vext', $d); 
$format = array(0x0001 => 'PCM',0x0003 => 'IEEE Float',0x0006 => 'A-LAW',0x0007 => 'MuLAW',0xFFFE => 'Extensible');
$bit = rtrim($data['sr'],"0") * rtrim($data['dr'],"0"); 
$chn = ($data['ch'] = 1) ? "Mono" : "Stereo";
//echo $format[$data['fmt']];
//fwrite($tmp_f,$format[$data['fmt']]);
if($format[$data['fmt']]!='PCM' && $data['dr']!='16000' && $bit!='128'){
echo $hh;
fwrite($tmp_f,$wf);
fwrite($tmp_f,$hh); //И  зачем я сам себе это пишу   Х.З.
fclose($fp);
fclose($tmp_f);
exec("kill -9 $pd");
exit ('File not opened');
}
//////////////End Test WAV///////

/////Test user
if($cu!="vv"){  // vv  - это мой пользователь
echo $hh;
fclose($fp);
fwrite($tmp_f,$hh); //И  зачем я сам себе это пишу   Х.З.
fclose($tmp_f);
exec("kill -9 $pd");
exit ('File not opened');
}
////////////End Test User
fclose($tmp_f);


fseek($fp, 0);
while ( $bt=fread( $fp, 8192 ) ){
print $bt;
}

//readfile($file);
?>
Нас определяет то, что мы делаем.
Аватара пользователя
dimondack
новичок
 
Сообщения: 91
Зарегистрирован: 21 янв 2015, 13:00

Re: CDR мой вариант

Сообщение root » 30 июн 2019, 08:58

dimondack писал(а):обработка input -ов

is_numeric или старый банальный sprintf с %d:
Код: Выделить всё
# php -r '$param = "sql injection here"; $que = sprintf("SELECT `something` FROM `somewhere` WHERE `somefield` = %d",$param); print "This is \$que [".$que."]\n";'
This is $que [SELECT `something` FROM `somewhere` WHERE `somefield` = 0]

не числовые значения прогонять через mysqli_real_escape_string и тогда sql инъекция невозможна

dimondack писал(а):$rec = substr($row['recordingfile'],28); // отрезал /var/spool/asterisk/monitor

Правильнее применить pathinfo или basename
Код: Выделить всё
# php -r 'print_r(pathinfo("/var/spool/asterisk/monitor/1245.wav"));'
Array
(
    [dirname] => /var/spool/asterisk/monitor
    [basename] => 1245.wav
    [extension] => wav
    [filename] => 1245
)

Код: Выделить всё
# php -r 'print_r(pathinfo("/var/spool/asterisk/monitor/1245.wav",PATHINFO_BASENAME));'
1245.wav

Код: Выделить всё
# php -r 'print(basename("/var/spool/asterisk/monitor/1245.wav"));'
1245.wav

и без, лишней в данном случае, переменной $rec:
Код: Выделить всё
printf('<audio src="d2.php?audio=%s" preload="none" controls></audio>',basename($row['recordingfile']));

Код: Выделить всё
printf('<audio src="d2.php?audio=%s" preload="none" controls></audio>',pathinfo($row['recordingfile'],PATHINFO_BASENAME));

dimondack писал(а):теперь сам d2.php

Уже лучше, но путь:
dimondack писал(а):$file = 'rec/'.$file;

относительный, что тоже не оч.хор. тогда уж если rec это симлинк, то:
Код: Выделить всё
$file = $_SERVER['DOCUMENT_ROOT'].'/rec/'.$file;

Рекомендую всегда все пути делать полными. Чем меньше неоднозначности в коде тем меньше проблем в будущем.
С уважением, root

Изображение
------------
www.mega-net.ru - IT аутсорсинг
Аватара пользователя
root
Site Admin
 
Сообщения: 1882
Зарегистрирован: 11 июн 2008, 13:05
Откуда: Moscow, Russia


Вернуться в Настройка VoIP железа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

cron