Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/library/cdr_asterisk.php b/library/cdr_asterisk.php
index b20a7f8..9d51a27 100644
--- a/library/cdr_asterisk.php
+++ b/library/cdr_asterisk.php
@@ -1,1557 +1,1557 @@
<?php
class CDRS_asterisk extends CDRS {
var $table = "cdr";
var $CDR_class = "CDR_asterisk";
// mapping between CDRTool fields and database fields
var $CDRFields=array('id' => 'id',
'callId' => 'uniqueid',
'duration' => 'billsec',
'startTime' => 'calldate',
'aNumber' => 'clid',
'username' => 'src',
'UserName' => 'src',
'domain' => 'dcontext',
'cNumber' => 'dst',
'timestamp' => 'timestamp',
'applicationType' => 'lastapp',
'BillingPartyId' => 'src',
'billingCode' => 'accountcode',
'BillingPartyId' => 'src',
'appDuration' => 'duration',
'data' => 'lastdata',
'channelIn' => 'channel',
'channelOut' => 'dstchannel',
'normalized' => 'Normalized',
'rate' => 'Rate',
'price' => 'Price',
'BillingPartyId' => 'UserName',
'DestinationId' => 'DestinationId'
);
var $CDRNormalizationFields=array('id' => 'id',
'callId' => 'uniqueid',
'username' => 'src',
'domain' => 'dcontext',
'duration' => 'billsec',
'startTime' => 'calldate',
'aNumber' => 'clid',
'cNumber' => 'dst',
'timestamp' => 'timestamp',
'BillingPartyId' => 'src',
'price' => 'Price',
'DestinationId' => 'DestinationId'
);
var $GROUPBY = array(
"src" => "Username",
"clid" => "Source",
"dst" => "Destination",
"lastapp" => "Application Type",
"dcontext" => "Context",
"DestinationId" => "Destination Id",
" " => "-------------",
"hour" => "Hour of day",
"DAYOFWEEK" => "Day of Week",
"DAYOFMONTH" => "Day of Month",
"DAYOFYEAR" => "Day of Year"
);
var $FormElements=array(
"begin_hour","begin_min","begin_month","begin_day","begin_year","begin_datetime","end_date","begin_date",
"end_hour","end_min","end_month","end_day","end_year","end_datetime","end_date","begin_date",
"call_id","a_number","a_number_comp","c_number","c_number_comp","DestinationId","ExcludeDestinations",
"unnormalize",
"UserName","UserName_comp","BillingId",
"applicationType","context","channel_in","channel_out","data",
"duration","action","redirect","MONTHYEAR",
"order_by","order_type","group_by","cdr_table","maxrowsperpage");
function LoadDisconnectCodes() {
}
function showTableHeaderStatistics() {
$group_byPrint=$this->GROUPBY[$this->group_by];
if (!$this->export) {
print "
<table border=1 cellspacing=2 width=100% align=center>
<tr>
<td>
<table border=0 cellspacing=2 width=100%>
<tr bgcolor=lightgrey>
<td></td>
<td> <b>Calls</b></td>
<td align=right><b>Seconds</b></td>
<td align=right><b>Minutes</b></td>
<td align=right><b>Hours</b></td>";
if ($this->rating) {
print "<td align=right><b>Price</b></td>";
}
print "
<td align=center colspan=2><b>Success</b></td>
<td align=center colspan=2><b>Failure</b></td>
<td><b>$group_byPrint</b></td>
<td><b>Description</b></td>
<td><b>Action</b></td>
</tr>
";
} else {
print "id,Calls,Seconds,Minutes,Hours,Price,Success(%),Success(calls),Failure(%),Failure(calls),$group_byPrint,Description\n";
}
}
function showTableHeaderSubscriber() {
$this->showTableHeader();
}
function showTableHeader() {
print "
<table border=1 cellspacing=2 width=100% align=center>
<tr>
<td>
<table border=0 cellspacing=2 width=100%>
<tr bgcolor=lightgrey>
<td>
<td> <b>Date and time</td>
<td> <b>Username</b></td>
<td> <b>Source</b></td>
<td> <b>In</b></td>
<td colspan=2> <b>Destination</b></td>
<td> <b>Out</b></td>
<td> <b>Dur</b></td>
<td> <b>Price</b></td>
<td> <b>Context</b></td>
<td> <b>Channel in</b></td>
<td> <b>Channel out</b></td>
<td> <b>Account</b></td>
<td> <b>App (Duration)</b></td>
</tr>
";
}
function showExportHeader() {
print "id,StartTime,Username,Source,Destination,DestinationId,DestinationName,Duration,Price,Context,ChannelIn,ChannelOut,Account,Application,ApplicationDuration\n";
}
function showSubscriber() {
$this->show();
}
function show() {
global $perm;
foreach ($this->FormElements as $_el) {
${$_el} = $_REQUEST[$_el];
}
if ($begin_time) {
list($begin_hour,$begin_min)=explode(":",$begin_time);
}
if ($end_time) {
list($end_hour,$end_min)=explode(":",$end_time);
}
if ($begin_date) {
list($begin_year,$begin_month,$begin_day)=explode("-",$begin_date);
}
if ($end_date) {
list($end_year,$end_month,$end_day)=explode("-",$end_date);
}
if (!$this->export) {
if (!$begin_datetime) {
$begin_datetime="$begin_year-$begin_month-$begin_day $begin_hour:$begin_min";
$begin_datetime_timestamp=mktime($begin_hour, $begin_min, 0, $begin_month,$begin_day,$begin_year);
} else {
$begin_datetime_timestamp=$begin_datetime;
$begin_datetime=Date("Y-m-d H:i",$begin_datetime);
}
$begin_datetime_url=urlencode($begin_datetime_timestamp);
if (!$end_datetime) {
$end_datetime_timestamp=mktime($end_hour, $end_min, 0, $end_month,$end_day,$end_year);
$end_datetime="$end_year-$end_month-$end_day $end_hour:$end_min";
} else {
$end_datetime_timestamp=$end_datetime;
$end_datetime=Date("Y-m-d H:i",$end_datetime);
}
$end_datetime_url=urlencode($end_datetime_timestamp);
} else {
$begin_datetime=Date("Y-m-d H:i",$begin_datetime);
$end_datetime=Date("Y-m-d H:i",$end_datetime);
}
if (!$order_by || (!$group_by && $order_by == "group_by")) {
$order_by=$this->idField;
}
if (!$cdr_table) $cdr_table=$this->table;
// build an url to be able to log and refine the query
$this->url="?cdr_source=$this->cdr_source&cdr_table=$cdr_table";
$this->url=$this->url."&order_by=$order_by&order_type=$order_type";
$this->url=$this->url."&begin_datetime=$begin_datetime_url";
$this->url=$this->url."&end_datetime=$end_datetime_url";
if ($this->CDRTool['filter']['aNumber']) {
$this->url = $this->url."&aNumbers=".urlencode($this->CDRTool['filter']['aNumber']);
$aNumbers = explode(" ",$this->CDRTool['filter']['aNumber']);
} else if ($aNumbers) {
$this->url = $this->url."&aNumbers=".urlencode($aNumbers);
$aNumbers = explode(" ",$aNumbers);
}
if ($this->CDRTool['filter']['after_date']) {
$where .= sprintf(" and calldate >= '%s' ",$this->CDRTool['filter']['after_date']);
}
$where = " calldate > '$begin_datetime' and calldate <= '$end_datetime' ";
$a_number=trim($a_number);
if ($this->CDRTool['filter']['aNumber']) {
$where .= "
and $this->aNumberField in (" ;
$rr=0;
foreach ($aNumbers as $_aNumber) {
$_aNumber=trim($_aNumber);
if (strlen($_aNumber)) {
if ($rr) $where .= ", ";
$where .= " '$_aNumber'";
$rr++;
}
}
$where .= ") ";
} else if ($aNumbers) {
$where .= "
and $this->aNumberField in (" ;
$rr=0;
foreach ($aNumbers as $_aNumber) {
$_aNumber=trim($_aNumber);
if (strlen($_aNumber)) {
if ($rr) $where .= ", ";
$where .= " '$_aNumber'";
$rr++;
}
}
$where .= ") ";
} else if ($a_number_comp == "empty") {
$where .= " and $this->aNumberField = ''";
$this->url=$this->url."&a_number_comp=$a_number_comp";
} else if (strlen($a_number)) {
$a_number=urldecode($a_number);
if (!$a_number_comp) $a_number_comp="equal";
$a_number_encoded=urlencode($a_number);
$a_number_encoded=urlencode($a_number);
$this->url="$this->url"."&a_number=$a_number_encoded";
if ($a_number_comp=="begin") {
$where .= " and ($this->aNumberField like '".addslashes($a_number)."%'";
$s=1;
} elseif ($a_number_comp=="contain") {
$where .= " and ($this->aNumberField like '%".addslashes($a_number)."%'";
$s=1;
} elseif ($a_number_comp=="equal") {
$where .= " and ($this->aNumberField = '".addslashes($a_number)."'";
$s=1;
}
if ($s) {
$where .= ")";
}
$this->url=$this->url."&a_number_comp=$a_number_comp";
}
if ($channel_in) {
$channel_in_encoded=urlencode($channel_in);
$where = "$where"." and $this->channelInField = '".addslashes($channel_in)."'";
$this->url="$this->url"."&channel_in=$channel_in_encoded";
}
if ($applicationType) {
$where = "$where"." and $this->applicationTypeField like '".addslashes($applicationType)."%'";
$applicationType_encoded=urlencode($applicationType);
$this->url="$this->url"."&applicationType=$applicationType_encoded";
}
if ($UserName_comp != "empty") {
$UserName=trim($UserName);
if ($UserName) {
$UserName=urldecode($UserName);
if (!$UserName_comp) {
$UserName_comp="begin";
}
$UserName_encoded=urlencode($UserName);
if ($UserName_comp=="begin") {
$where .= " and $this->usernameField like '".addslashes($UserName)."%'";
} elseif ($UserName_comp=="contain") {
$where .= " and $this->usernameField like '%".addslashes($UserName)."%'";
} elseif ($UserName_comp=="equal") {
$where .= " and $this->usernameField = '".addslashes($UserName)."'";
}
$this->url="$this->url"."&UserName=$UserName_encoded&UserName_comp=$UserName_comp";
}
} else {
$where .= " and $this->usernameField = ''";
$this->url="$this->url"."&UserName_comp=$UserName_comp";
}
if ($context) {
$context_encoded=urlencode($context);
$where = "$where"." and $this->domainField = '".addslashes($context)."'";
$this->url="$this->url"."&context=$context_encoded";
}
if ($channel_out) {
$channel_out_encoded=urlencode($channel_out);
$where = "$where"." and $this->channelOutField = '".addslashes($channel_out)."'";
$this->url="$this->url"."&channel_out=$channel_out_encoded";
}
if (strlen($c_number)) {
# Trim content of dest_form - allow only digits
if ($c_number_comp=="begin") {
$where = "$where"." and $this->cNumberField like '".addslashes($c_number)."%'";
} elseif ($c_number_comp=="equal") {
$where = "$where"." and $this->cNumberField = '".addslashes($c_number)."'";
} elseif ($c_number_comp=="contain") {
$where .= " and $this->cNumberField like '%".addslashes($c_number)."%'";
} else {
$where = "$where"." and $this->cNumberField like '%".addslashes($c_number)."%'";
}
$c_number_encoded=urlencode($c_number);
$this->url=$this->url."&c_number=$c_number_encoded&c_number_comp=$c_number_comp";
}
if ($DestinationId) {
if ($DestinationId=="empty") {
$DestinationIdSQL="";
} else {
$DestinationIdSQL=$DestinationId;
}
$where = "$where"." and $this->DestinationIdField = '".addslashes($DestinationIdSQL)."'";
$DestinationId_encoded=urlencode($DestinationId);
$this->url="$this->url"."&DestinationId=$DestinationId_encoded";
}
if ($duration) {
if (preg_match("/\d+/",$duration) ) {
$where .= " and ($this->durationField > 0 and $this->durationField $duration) ";
} elseif ($duration == "zero") {
$where = "$where"." and $this->durationField = 0";
} elseif ($duration == "nonzero") {
$where = "$where"." and $this->durationField > 0";
}
$this->url="$this->url"."&duration=$duration";
}
$this->url="$this->url"."&maxrowsperpage=$this->maxrowsperpage";
$url_calls = $this->scriptFile.$this->url."&action=search";
if ($group_by) {
$this->url="$this->url"."&group_by=$group_by";
}
$this->url_edit = $this->scriptFile.$this->url."&action=edit";
$this->url_run = $this->scriptFile.$this->url."&action=search";
$this->url_export = $_SERVER["PHP_SELF"].$this->url."&action=search&export=1";
if ($group_by) {
$this->group_byOrig=$group_by;
if ($group_by=="hour") {
$group_by="HOUR($this->startTimeField)";
} else if (preg_match("/^DAY/",$group_by)) {
$group_by="$group_by($this->startTimeField)";
}
if (!$perm->have_perm("statistics")) {
print "<p><font color=red>You do not have the right for statistics.</font>";
return 0 ;
}
$this->group_by=$group_by;
$query= "
select sum($this->durationField) as duration, SEC_TO_TIME(sum($this->durationField)) as duration_print,
count($group_by) as calls, $group_by
from $cdr_table
where $where
group by $group_by
";
} else {
$query = "select count(*) as records from $cdr_table where ".$where;
}
dprint("$query");
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
if ($group_by) {
$rows=$this->CDRdb->num_rows();
} else {
$rows = $this->CDRdb->f('records');
}
} else {
$rows = 0;
}
$this->rows=$rows;
if ($this->CDRTool['filter']['aNumber']) {
$this->showResultsMenuSubscriber('0',$begin_datetime,$end_datetime);
} else {
$this->showResultsMenu('0',$begin_datetime,$end_datetime);
}
if (!$this->next) {
$i=0;
$this->next=0;
} else {
$i=$this->next;
}
$j=0;
$z=0;
if ($rows>0) {
if ($UnNormalizedCalls=$this->getUnNormalized($where,$cdr_table)) {
dprint("Normalize calls");
$this->NormalizeCDRS($where,$cdr_table);
if (!$this->export && $this->status['normalized'] ) {
printf ("<p> Found %d CDRs for normalization. ",$this->status['normalized']);
}
}
$this->$rows=$rows;
if ($rows > $this->maxrowsperpage) {
$maxrows=$this->maxrowsperpage+$this->next;
if ($maxrows > $rows) {
$maxrows=$rows;
$prev_rows=$maxrows;
}
} else {
$maxrows=$rows;
}
if ($group_by) {
if ($order_by=="group_by") {
$order_by1=$group_by;
} else {
if ($order_by == $this->priceField ||
$order_by == "zeroP" ||
$order_by == "nonzeroP" ||
$order_by == $this->durationField ) {
$order_by1 = $order_by;
} else {
$order_by1 = "calls";
}
}
$query= "
select
sum($this->durationField) as $this->durationField,
SEC_TO_TIME(sum($this->durationField)) as hours,
count($group_by) as calls, ";
if ($this->priceField) {
$query.=" sum($this->priceField) as price, ";
}
$query.="
SUM($this->durationField = '0') as zero,
SUM($this->durationField > '0') as nonzero,
";
if ($order_by=="zeroP" || $order_by=="nonzeroP") {
$query.="
SUM($this->durationField = '0')/count($group_by)*100 as zeroP,
SUM($this->durationField > '0')/count($group_by)*100 as nonzeroP,
";
}
$query.="
$group_by as mygroup
from $cdr_table
where $where
group by $group_by
order by $order_by1 $order_type
limit $i, $this->maxrowsperpage
";
dprint($query);
$this->CDRdb->query($query);
$this->showTableHeaderStatistics();
while ($i<$maxrows) {
$found=$i+1;
$this->CDRdb->next_record();
$seconds =$this->CDRdb->Record[$this->durationField];
$seconds_print =number_format($this->CDRdb->Record[$this->durationField],0);
$minutes =number_format($this->CDRdb->Record[$this->durationField]/60,0,"","");
$minutes_print =number_format($this->CDRdb->Record[$this->durationField]/60,0);
$hours =$this->CDRdb->Record['hours'];
$calls =$this->CDRdb->Record['calls'];
$mygroup =$this->CDRdb->Record['mygroup'];
if ($this->rating && $this->priceField) {
$price =$this->CDRdb->Record['price'];
}
$zero =$this->CDRdb->Record['zero'];
$nonzero =$this->CDRdb->Record['nonzero'];
$success =number_format($nonzero/$calls*100,2,".","");
$failure =number_format($zero/$calls*100,2,".","");
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
$mygroup_enc=urlencode($mygroup);
$traceValue="";
if ($group_by==$this->DestinationIdField) {
if ($this->CDRTool['filter']['aNumber']) {
$description=$this->destinations[$this->CDRTool['filter']['aNumber']][$mygroup];
} else if ($this->CDRTool['filter']['domain']) {
$description=$this->destinations[$this->CDRTool['filter']['domain']][$mygroup];
} else {
$description=$this->destinations["default"][$mygroup];
}
} else if ($group_by==$this->aNumberField) {
$traceField="a_number";
} else if ($group_by==$this->usernameField) {
$traceField="username";
} else if ($group_by==$this->cNumberField) {
$traceField="c_number";
}
if ($mygroup) {
$traceValue=$mygroup;
} else {
$traceValue="empty";
}
if (!$traceField) {
$traceField = $group_by;
}
if (!$traceValue) {
$traceValue = $mygroup;
}
$mygroup_print = $mygroup;
$traceValue_enc=urlencode($traceValue);
if (!$this->export) {
$pricePrint=number_format($price,4);
print "
<tr bgcolor=$inout_color>
<td><b>$found</b></td>
<td align=right>$calls</td>
<td align=right>$seconds_print</td>
<td align=right>$minutes_print</td>
<td align=right>$hours</td>
<td align=right>$pricePrint</td>
<td align=right>$success%</td>
<td align=right>($nonzero calls)</td>
<td align=right>$failure%</td>
<td align=right>($zero calls)</td>
<td>$mygroup_print</td>
<td>$description</td>
<td><a href=$url_calls&$traceField=$traceValue_enc target=_new>Display calls</a></td>
</tr>
";
} else {
print "$found,";
print "$calls,";
print "$seconds,";
print "$minutes,";
print "$hours,";
print "$price,";
print "$success,";
print "$nonzero,";
print "$failure,";
print "$zero,";
print "$mygroup,";
print "$description";
print "\n";
}
$i++;
}
if (!$this->export) {
print "
</table>
</td>
</tr>
</table>
";
}
} else {
if (!$order_by) {
$order_by=calldate;
}
$query = "select *,unix_timestamp(calldate) as timestamp
from $cdr_table
where $where
order by $order_by $order_type
limit $i,$this->maxrowsperpage";
dprint("$query");
$this->CDRdb->query($query);
if (!$this->export) {
$this->showTableHeader();
} else {
$this->showExportHeader();
}
while ($i<$maxrows) {
global $found;
$found=$i+1;
$this->CDRdb->next_record();
$Structure=$this->_readCDRFieldsFromDB();
$CDR = new $this->CDR_class($this, $Structure);
if (!$this->export) {
$CDR->show();
} else {
$CDR->export();
}
$i++;
}
if (!$this->export) {
print "
</table>
</td>
</tr>
</table>
";
}
}
}
$this->showPagination($this->next,$maxrows,$rows);
}
function initForm() {
// form els added below must have global vars
foreach ($this->FormElements as $_el) {
global ${$_el};
${$_el} = $_REQUEST[$_el];
}
$action = "search";
if ($this->CDRTool['filter']['aNumber']) {
$a_number=$this->CDRTool['filter']['aNumber'];
$UserName=$this->CDRTool['filter']['aNumber'];
}
if (!$maxrowsperpage) $maxrowsperpage=15;
$this->f = new form;
if (isset($this->CDRTool['dataSourcesAllowed'])) {
- while (list($k,$v)=each($this->CDRTool['dataSourcesAllowed'])) {
+ foreach ($this->CDRTool['dataSourcesAllowed'] as $k => $v) {
if ($this->DATASOURCES[$v]['invisible']) continue;
$cdr_source_els[]=array("label"=>$this->DATASOURCES[$v]['name'],"value"=>$v);
}
}
if (!$cdr_source) $cdr_source=$cdr_source_els[0]['value'];
$this->f->add_element(array("name"=>"cdr_source",
"type"=>"select",
"options"=>$cdr_source_els,
"size"=>"1",
"extrahtml"=>"onChange=\"document.datasource.submit.disabled = true; location.href = 'callsearch.phtml?cdr_source=' + this.options[this.selectedIndex].value\"",
"value"=>"$cdr_source"
)
);
$cdr_table_els=array();
foreach ($this->tables as $_table) {
if (preg_match("/^.*(\d{6})$/",$_table,$m)) {
$cdr_table_els[]=array("label"=>$m[1],"value"=>$_table);
} else {
$cdr_table_els[]=array("label"=>$_table,"value"=>$_table);
}
}
$this->f->add_element(array( "name"=>"cdr_table",
"type"=>"select",
"options"=>$cdr_table_els,
"size"=>"1",
"value"=>$cdr_table
));
if ($begin_datetime) {
dprint("begin_datetime=$begin_datetime");
preg_match("/^(\d\d\d\d)-(\d+)-(\d+)\s+(\d\d):(\d\d)/", "$begin_datetime", $parts);
$begin_year =date(Y,$begin_datetime);
$begin_month=date(m,$begin_datetime);
$begin_day =date(d,$begin_datetime);
$begin_hour =date(H,$begin_datetime);
$begin_min =date(i,$begin_datetime);
} else {
$begin_day = $_REQUEST["begin_day"];
$begin_month = $_REQUEST["begin_month"];
$begin_year = $_REQUEST["begin_year"];
$begin_hour = $_REQUEST["begin_hour"];
$begin_min = $_REQUEST["begin_min"];
}
if ($end_datetime) {
dprint("end_datetime=$end_datetime");
preg_match("/^(\d\d\d\d)-(\d+)-(\d+)\s+(\d\d):(\d\d)/", "$end_datetime", $parts);
$end_year =date(Y,$end_datetime);
$end_month =date(m,$end_datetime);
$end_day =date(d,$end_datetime);
$end_hour =date(H,$end_datetime);
$end_min =date(i,$end_datetime);
} else {
$end_day = $_REQUEST["end_day"];
$end_month = $_REQUEST["end_month"];
$end_year = $_REQUEST["end_year"];
$end_hour = $_REQUEST["end_hour"];
$end_min = $_REQUEST["end_min"];
}
$default_year =Date("Y");
$default_month =Date("m");
$default_day =Date("d");
$default_hour =Date(H,time());
if ($default_hour > 1) {
$default_hour=$default_hour-1;
}
$default_hour=preg_replace("/^(\d)$/","0$1",$default_hour);
$default_min =Date("i");
if ($default_min > 10) {
$default_min=$default_min-10;
$default_min=preg_replace("/^(\d)$/","0$1",$default_min);
}
if (!$begin_hour) $begin_hour = $default_hour;
if (!$begin_min) $begin_min = $default_min;
if (!$begin_day) $begin_day = $default_day;
if (!$begin_month) $begin_month = $default_month;
if (!$begin_year) $begin_year = $default_year;
if (!$end_hour) $end_hour = 23;
if (!$end_min) $end_min = 55;
if (!$end_day) $end_day = $default_day;
if (!$end_month) $end_month = $default_month;
if (!$end_year) $end_year = $default_year;
$this->f->add_element(array(
"name"=>"begin_time",
"size"=>"1",
"type"=>"text",
"extrahtml"=>"id='timepicker1' class=\"input-small\" data-show-meridian='false' data-minute-step='1' data-default-time='$begin_hour:$begin_min'"
));
$this->f->add_element(array(
"name"=>"end_time",
"size"=>"1",
"type"=>"text",
"extrahtml"=>"id='timepicker2' class=\"input-small\" data-show-meridian='false' data-minute-step='1' data-default-time='$end_hour:$end_min'"
));
$this->f->add_element(array(
"name"=>"begin_date",
"size"=>"10",
"maxlength"=>"10",
"type"=>"text",
"value"=>"$begin_year-$begin_month-$begin_day",
"extrahtml"=>"id='begin_date' data-date-format=\"yyyy-mm-dd\" class=\"span2\""
));
$this->f->add_element(array(
"name"=>"end_date",
"size"=>"1",
"type"=>"text",
"value"=>"$end_year-$end_month-$end_day",
"extrahtml"=>"id='end_date' data-date-format=\"yyyy-mm-dd\" class=\"span2\""
));
$this->f->add_element(array( "name"=>"call_id",
"type"=>"text",
"size"=>"50",
"maxlength"=>"100"
));
$this->f->add_element(array( "name"=>"a_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array( "name"=>"UserName",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array( "name"=>"c_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
if (!$this->CDRTool['filter']['aNumber']) {
$durations_els = array(
array("label"=>"All calls","value"=>""),
array("label"=>"0 seconds call","value"=>"zero"),
array("label"=>"non 0 seconds","value"=>"nonzero"),
array("label"=>"non 0 seconds with 0 price","value"=>"zeroprice"),
array("label"=>"less than 5 seconds","value"=>"< 5"),
array("label"=>"more than 5 seconds","value"=>"> 5"),
array("label"=>"less than 60 seconds","value"=>"< 60"),
array("label"=>"greater than 1 hour","value"=>"> 3600"),
array("label"=>"greater than 5 hours","value"=>"> 18000")
);
} else {
$durations_els = array(
array("label"=>"Succesfull calls","value"=>"nonzero")
);
}
$this->f->add_element(array( "name"=>"duration",
"type"=>"select",
"options"=>$durations_els,
"value"=>"All",
"size"=>"1"
));
$comp_ops_els = array(
array("label"=>"Begins with","value"=>"begin"),
array("label"=>"Contains","value"=>"contain"),
array("label"=>"Is empty","value"=>"empty"),
array("label"=>"Equal","value"=>"equal")
);
$this->f->add_element(array( "name"=>"a_number_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"c_number_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"UserName_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"Realm",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array("type"=>"submit",
"name"=>"submit",
"value"=>"Search"
));
$max_els=array(
array("label"=>"5","value"=>"5"),
array("label"=>"10","value"=>"10"),
array("label"=>"15","value"=>"15"),
array("label"=>"25","value"=>"25"),
array("label"=>"50","value"=>"50"),
array("label"=>"100","value"=>"100"),
array("label"=>"500","value"=>"500")
);
$this->f->add_element(array( "name"=>"maxrowsperpage",
"type"=>"select",
"options"=>$max_els,
"size"=>"1",
"value"=>"25"
));
$order_type_els=array(
array("label"=>"Descending","value"=>"DESC"),
array("label"=>"Ascending","value"=>"ASC")
);
$this->f->add_element(array( "name"=>"order_type",
"type"=>"select",
"options"=>$order_type_els,
"size"=>"1"
));
$this->f->add_element(array("type"=>"hidden",
"name"=>"action",
"value"=>$action,
));
$order_by_els=array(array("label"=>"Date","value"=>"calldate"),
array("label"=>"CLID","value"=>"clid"),
array("label"=>"Source","value"=>"src"),
array("label"=>"Destination","value"=>"dst"),
array("label"=>"Call duration","value"=>"duration"),
array("label"=>"Application","value"=>"lastapp"),
array("label"=>"Data","value"=>"lastdata"),
array("label"=>"Price","value"=>"Price"),
array("label"=>"Failures(%)","value"=>"zeroP"),
array("label"=>"Success(%)","value"=>"nonzeroP"),
array("label"=>"Group by","value"=>"group_by")
);
$group_by_els[]=array("label"=>"","value"=>"");
- while (list($k,$v)=each($this->GROUPBY)) {
+ foreach($this->GROUPBY as $k => $v) {
$group_by_els[]=array("label"=>$v,"value"=>$k);
}
$this->f->add_element(array( "name"=>"order_by",
"type"=>"select",
"options"=>$order_by_els,
"value"=>$order_by,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"group_by",
"type"=>"select",
"options"=>$group_by_els,
"value"=>$group_by,
"size"=>"1"
));
$applicationType_els=array(array("label"=>"Any", "value"=>""),
array("label"=>"Dial", "value"=>"Dial"),
array("label"=>"Voicemail", "value"=>"Voicemail"),
array("label"=>"Playback", "value"=>"Playback"),
array("label"=>"Conference", "value"=>"MeetMe"),
array("label"=>"Enum Lookup", "value"=>"ENUMLookup"),
array("label"=>"Record", "value"=>"Record"),
array("label"=>"AGI scripting", "value"=>"AGI"),
array("label"=>"Music On Hold", "value"=>"MusicOnHold"),
array("label"=>"Back Ground Music", "value"=>"BackGround"),
array("label"=>"MP3 Player", "value"=>"MP3Player")
);
$this->f->add_element(array( "name"=>"applicationType",
"type"=>"select",
"options"=>$applicationType_els,
"value"=>$applicationType,
"size"=>"1"
));
if ($this->DATASOURCES[$this->cdr_source][contexts]) {
$contexts_els[]=array("label"=>"All contexts","value"=>"");
- while (list($k,$v)=each($this->DATASOURCES[$this->cdr_source][contexts])) {
- $contexts_els[]=array("label"=>$v[WEBName]." (".$k.")","value"=>$k);
+ foreach ($this->DATASOURCES[$this->cdr_source]['contexts'] as $k => $v) {
+ $contexts_els[]=array("label"=>$v['WEBName']." (".$k.")","value"=>$k);
}
$this->f->add_element(array(
"name"=>"context",
"type"=>"select",
"options"=>$contexts_els,
"size"=>"1",
"value"=>$context
));
} else {
$this->f->add_element(array( "name"=>"context",
"type"=>"text",
"size"=>"10",
"maxlength"=>"45"
));
}
$this->f->add_element(array( "name"=>"channel_in",
"type"=>"text",
"size"=>"20",
"maxlength"=>"25"
));
$this->f->add_element(array( "name"=>"channel_out",
"type"=>"text",
"size"=>"20",
"maxlength"=>"25"
));
$this->f->load_defaults();
}
function searchForm() {
global $perm;
// Start displaying form
$this->initForm();
$this->f->start("","POST","","","datasource");
print "
<table cellpadding=5 CELLSPACING=0 border=6 width=100% align=center>
";
$this->showDataSources ($this->f);
$this->showDateTimeElements ($this->f);
if ($this->CDRTool['filter']['aNumber']) {
$ff[]="a_number";
$ff[]="a_number_comp";
$ff[]="UserName";
$ff[]="UserName_comp";
}
if ($this->CDRTool['filter']['domain']) {
$ff[]="context";
}
if (count($ff)) {
$this->f->freeze($ff);
}
print "
<tr>
<td align=left>
<b>Context</b>
</td>
<td valign=top>
";
$this->f->show_element("context","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Channels</b>
</td>
<td valign=top>
Incomming
";
$this->f->show_element("channel_in","");
print "Outgoing";
$this->f->show_element("channel_out","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Username
</b>
</td>
<td valign=top>
";
$this->f->show_element("UserName_comp","");
$this->f->show_element("UserName","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Source
</b>
</td>
<td valign=top>
";
$this->f->show_element("a_number_comp","");
$this->f->show_element("a_number","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Destination
</b>
</td>
<td valign=top> ";
$this->f->show_element("c_number_comp","");
$this->f->show_element("c_number","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Duration</b>
</td>
<td valign=top> ";
$this->f->show_element("duration","");
print " Application ";
$this->f->show_element("applicationType","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Order by</b>
</td>
<td valign=top>
";
$this->f->show_element("order_by","");
$this->f->show_element("order_type","");
if ($perm->have_perm("statistics")) {
print " Group by ";
$this->f->show_element("group_by","");
}
print " Max results per page ";
$this->f->show_element("maxrowsperpage","");
print "</nobr>&nbsp;&nbsp;&nbsp; <nobr>ReNormalize";
print "<input type=checkbox name=ReNormalize value=1>
</nobr>";
print "
</td>
</tr>
</table>
<p>
<center>
";
$this->f->show_element("submit","");
$this->f->finish();
print "</center>";
}
function searchFormSubscriber() {
global $perm;
// Start displaying form
$this->initForm();
$this->f->start("","POST","","","datasource");
print "
<table cellpadding=5 CELLSPACING=0 border=6 width=100% align=center>
";
$this->showDataSources ($this->f);
$this->showDateTimeElements ($this->f);
if ($this->CDRTool['filter']['aNumber']) {
$ff[]="a_number";
$ff[]="a_number_comp";
$ff[]="UserName";
$ff[]="UserName_comp";
}
if ($this->CDRTool['filter']['domain']) {
$ff[]="context";
}
if (count($ff)) {
$this->f->freeze($ff);
}
print "
<tr>
<td align=left>
<b>Context</b>
</td>
<td valign=top>
";
$this->f->show_element("context","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Channels</b>
</td>
<td valign=top>
Incomming
";
$this->f->show_element("channel_in","");
print "Outgoing";
$this->f->show_element("channel_out","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Source
</b>
</td>
<td valign=top>
";
$this->f->show_element("a_number_comp","");
$this->f->show_element("a_number","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Destination
</b>
</td>
<td valign=top> ";
$this->f->show_element("c_number_comp","");
$this->f->show_element("c_number","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Duration</b>
</td>
<td valign=top> ";
$this->f->show_element("duration","");
print " Application ";
$this->f->show_element("applicationType","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Order by</b>
</td>
<td valign=top>
";
$this->f->show_element("order_by","");
$this->f->show_element("order_type","");
if ($perm->have_perm("statistics")) {
print " Group by ";
$this->f->show_element("group_by","");
}
print " Max results per page ";
$this->f->show_element("maxrowsperpage","");
print "</nobr>&nbsp;&nbsp;&nbsp; <nobr>ReNormalize";
print "<input type=checkbox name=ReNormalize value=1>
</nobr>";
print "
</td>
</tr>
</table>
<p>
<center>
";
$this->f->show_element("submit","");
$this->f->finish();
print "</center>";
}
}
class CDR_asterisk extends CDR {
function CDR_asterisk($parent,$CDRfields) {
dprint("<hr>Init CDR");
dprint_r($CDRfields);
$this->CDRS= $parent;
foreach (array_keys($this->CDRS->CDRFields) as $field) {
$key=$this->CDRS->CDRFields[$field];
$this->$field = $CDRfields[$key];
$mysqlField=$this->CDRS->CDRFields[$field];
$_field=$field."Field";
$this->$_field=$mysqlField;
}
$this->dayofweek = date("w",$this->timestamp);
$this->hourofday = date("G",$this->timestamp);
$this->dayofyear = date("Y-m-d",$this->timestamp);
$this->aNumberPrint = $this->aNumber;
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->cNumber,"destination",$this->aNumberPrint,$this->domain,"");
$this->cNumberNormalized= $NormalizedNumber[Normalized];
$this->cNumberPrint = $NormalizedNumber[NumberPrint];
$this->DestinationId = $NormalizedNumber[DestinationId];
$this->destinationName = $NormalizedNumber[destinationName];
$this->durationPrint = sec2hms($this->duration);
$this->appDurationPrint = sec2hms($this->appDuration);
if ($this->CDRS->rating) {
$this->showRate = $this->CDRS->showRate;
}
$chanIn_els = explode("/",$this->channelIn);
$chanOut_els = explode("/",$this->channelOut);
$this->remoteGatewayIn = $chanIn_els[0];
$this->remoteGatewayOut = $chanOut_els[0];
$this->traceIn();
$this->traceOut();
if ($this->price == "0.0000") {
$this->pricePrint="";
} else {
$this->pricePrint=$this->price;
}
if (!strlen($this->username)) {
$this->username="unknown";
}
if ($this->domain) {
$_from=$this->username."@".$this->domain;
} else {
$_from=$this->username;
}
$this->NetworkRateDictionary=array(
'callId' => $this->id,
'Timestamp' => $this->timestamp,
'Duration' => $this->duration,
'Application' => 'audio',
'From' => $_from,
'To' => $this->cNumberNormalized
);
}
function traceIn () {
$datasource=$this->CDRS->traceInURL[$this->remoteGatewayIn];
global $DATASOURCES;
if (!$datasource || !$DATASOURCES[$datasource]) {
return;
}
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$cdr_table = $DATASOURCES[$datasource][table];
$c_number = preg_replace("/^(0+)/","",$this->cNumber);
$this->traceIn=
"<a href=callsearch.phtml".
"?cdr_source=$datasource".
"&cdr_table=$cdr_table".
"&trace=1".
"&action=search".
"&c_number=$c_number".
"&c_number_comp=contain".
"&begin_datetime=$tmin".
"&end_datetime=$tplus".
" target=bottom>".
"In".
"</a>";
}
function traceOut () {
$datasource=$this->CDRS->traceOutURL[$this->remoteGatewayOut];
global $DATASOURCES;
if (!$datasource || !$DATASOURCES[$datasource]) {
return;
}
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$cdr_table = $DATASOURCES[$datasource][table];
$c_number = preg_replace("/^(0+)/","",$this->cNumber);
$this->traceOut=
"<a href=callsearch.phtml".
"?cdr_source=$datasource".
"&cdr_table=$cdr_table".
"&trace=1".
"&action=search".
"&c_number=$c_number".
"&c_number_comp=contain".
"&begin_datetime=$tmin".
"&end_datetime=$tplus".
" target=bottom>".
"Out".
"</a>";
}
function showSubscriber() {
$this->show();
}
function show() {
global $found;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
if ($this->normalized) {
$found_print=$found."N";
} else {
$found_print=$found;
}
$this->ratePrint=nl2br($this->rate);
$CallInfoVerbose="
<table border=0 bgcolor=#CCDDFF class=extrainfo id=row$found cellpadding=0 cellspacing=0>
<tr>
<td valign=top>";
if ($this->price > 0) {
$CallInfoVerbose.= "
<table border=0 cellpadding=0 cellspacing=0>
<tr>
<td colspan=3><b>Rating information</b></td>
</tr>
<tr>
<td></td>
<td colspan=2>$this->ratePrint</td>
</tr>
</table>
";
}
$CallInfoVerbose.= "
</td>
</tr>
</table>";
print "
<tr bgcolor=$inout_color>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><a href=#>$found_print</a></td>
<td>$this->startTime</td>
<td>$this->username</td>
<td>$this->aNumberPrint</td>
<td>$this->traceIn</td>
<td>$this->cNumberPrint
<td>$this->destinationName $this->DestinationId</td>
<td>$this->traceOut</td>
<td align=right>$this->durationPrint</td>
<td valign=top align=right>$this->pricePrint</td>
<td>$this->domain</td>
<td>$this->channelIn</td>
<td>$this->channelOut</td>
<td align=right>$this->billingAccount</td>
<td align=right>$this->applicationType ($this->appDurationPrint)</td>
</tr>
<tr>
<td></td>
<td colspan=11>$CallInfoVerbose</td>
</tr>
";
}
function export() {
global $found;
print "$found";
print ",$this->startTime";
print ",$this->username";
print ",$this->aNumberPrint";
print ",$this->cNumberPrint";
print ",$this->DestinationId";
print ",$this->destinationName";
print ",$this->duration";
print ",$this->pricePrint";
print ",$this->domain";
print ",$this->channelIn";
print ",$this->channelOut";
print ",$this->billingAccount";
print ",$this->applicationType";
print ",$this->appDuration";
print "\n";
}
}
?>
diff --git a/library/cdr_cisco.php b/library/cdr_cisco.php
index 8c3485b..95f0463 100644
--- a/library/cdr_cisco.php
+++ b/library/cdr_cisco.php
@@ -1,1632 +1,1632 @@
<?php
class CDRS_cisco extends CDRS {
var $table = "radacct";
var $CDR_class = "CDR_cisco";
var $CDRFields=array('id' => 'RadAcctId',
'callId' => 'H323ConfID',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'username' => 'UserName',
'domain' => 'Realm',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'serviceType' => 'ServiceType',
'disconnect' => 'H323DisconnectCause',
'applicationType' => 'SipApplicationType',
'BillingPartyId' => 'UserName',
'localGateway' => 'NASIPAddress',
'gateway' => 'H323RemoteAddress',
'BillingPartyId' => 'UserName',
'NASPortId' => 'NASPortId',
'NASPortType' => 'NASPortType',
'H323GWID' => 'H323GWID',
'H323CallOrigin' => 'H323CallOrigin',
'H323CallType' => 'H323CallType',
'H323SetupTime' => 'H323SetupTime',
'H323ConnectTime' => 'H323ConnectTime',
'H323DisconnectTime' => 'H323DisconnectTime',
'H323DisconnectCause' => 'H323DisconnectCause',
'RemoteAddress' => 'H323RemoteAddress',
'H323VoiceQuality' => 'H323VoiceQuality',
'H323ConfID' => 'H323ConfID',
'normalized' => 'Normalized',
'rate' => 'Rate',
'price' => 'Price',
'BillingPartyId' => 'UserName',
'DestinationId' => 'DestinationId'
);
var $CDRNormalizationFields=array('id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'username' => 'UserName',
'domain' => 'Realm',
'gateway' => 'H323RemoteAddress',
'NASIPAddress' => 'NASIPAddress',
'NASPortId' => 'NASPortId',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'BillingPartyId' => 'UserName',
'price' => 'Price',
'DestinationId' => 'DestinationId'
);
var $GROUPBY=array("CallingStationId" => "Caller Party",
"DestinationId" => "Destination Id",
"NASPortId" => "Port Id",
"H323RemoteAddress" => "Gateway",
"H323RemoteAddress" => "Remote address",
"H323DisconnectCause" => "Disconnection cause"
);
var $FormElements=array(
"begin_hour","begin_min","begin_month","begin_day","begin_year","begin_datetime",
"end_hour","end_min","end_month","end_day","end_year","end_datetime",
"call_id","a_number","a_number_comp","c_number","c_number_comp","DestinationId","ExcludeDestinations",
"unnormalize",
"UserName","UserName_comp","BillingId",
"NASIPAddress","NASPortId","RemoteAddress","H323CallType","H323CallOrigin","release_cause",
"duration","action","MONTHYEAR","showRate",
"order_by","order_type","group_by",
"cdr_source","trace","cdr_table","maxrowsperpage");
function LoadDisconnectCodes() {
$query="select * from isdncause order by cause";
dprint("$query");
$this->cdrtool->query($query);
$this->disconnectCodesElements[]=array("label"=>"Any disconnection cause","value"=>"");
while($this->cdrtool->next_record()) {
$key = $this->cdrtool->f('cause');
$value = $this->cdrtool->f('description');
$value_print = $value." (".$key.")";
$this->disconnectCodesElements[]=array("label"=>$value_print,"value"=>$key);
$this->disconnectCodesDescription[$key]=$value;
$found++;
}
dprint("Loaded $found release codes");
return 1;
}
function showTableHeaderStatistics() {
$group_byPrint=$this->GROUPBY[$this->group_by];
if (!$this->export) {
print "
<table border=1 cellspacing=2 width=100% align=center>
<tr>
<td>
<table border=0 cellspacing=2 width=100%>
<tr bgcolor=lightgrey>
<td></td>
<td> <b>Calls</b></td>
<td align=right><b>Seconds</b></td>
<td align=right><b>Minutes</b></td>
<td align=right><b>Hours</b></td>";
if ($this->rating) {
print "<td align=right><b>Price</b></td>
";
}
print "
<td align=right><b>MB In</b></td>
<td align=right><b>MB Out</b></td>
<td align=center colspan=2><b>Success</b></td>
<td align=center colspan=2><b>Failure</b></td>
<td> <b>$group_byPrint</b></td>
<td> <b>Description</b></td>
<td> <b>Type</b>
<td> <b>Action</b></td>
</tr>
";
print "</tr>";
} else {
print "id,Calls,Seconds,Minutes,Hours,Price,TrafficIn(MB),TrafficOut(MB),Success(%),Success(calls),Failure(%),Failure(calls),$group_byPrint,Description\n";
}
}
function showTableHeaderSubscriber() {
$this->showTableHeader();
}
function showTableHeader() {
print "
<table border=1 cellspacing=2 width=100% align=center>
<tr>
<td>
<table border=0 cellspacing=2 width=100%>
<tr bgcolor=lightgrey>
<td>
<td> <b>Date and time
<td> <b>Caller Party</b>
<td> <b>In</b>
<td colspan=2> <b>Destination</b>
<td> <b>Out</b>
<td> <b>Dur</b>";
if ($this->rating) {
if ($this->showRate) {
print "<td><b>Rate</b></td>";
}
print "
<td> <b>Price</b>
";
}
print "
<td> <b>Gateway</b>
<td> <b>KBIn</b>
<td> <b>KBOut</b>
<td> <b>Disconnect</b>
<td> <b>Channel</b>
<td> <b>Direction</b>
<td> <b>CallType</b>
</tr>
";
}
function showExportHeader() {
print "id,StartTime,Username,CallerParty,Destination,DestinationId,DestinationName,Duration,Price,Gateway,KBIn,KBOut,Disconnect,Channel,Direction,CallType\n";
}
function searchFormSubscriber() {
$this->searchForm();
}
function initForm() {
// form els added below must have global vars
foreach ($this->FormElements as $_el) {
global ${$_el};
${$_el} = $_REQUEST[$_el];
}
$action = "search";
if (!$maxrowsperpage) $maxrowsperpage=15;
$this->f = new form;
if (isset($this->CDRTool['dataSourcesAllowed'])) {
- while (list($k,$v)=each($this->CDRTool['dataSourcesAllowed'])) {
+ foreach ($this->CDRTool['dataSourcesAllowed'] as $k => $v) {
if ($this->DATASOURCES[$v]['invisible']) continue;
$cdr_source_els[]=array("label"=>$this->DATASOURCES[$v]['name'],"value"=>$v);
}
}
if (!$cdr_source) $cdr_source=$cdr_source_els[0]['value'];
$this->f->add_element(array("name"=>"cdr_source",
"type"=>"select",
"options"=>$cdr_source_els,
"size"=>"1",
"extrahtml"=>"onChange=\"document.datasource.submit.disabled = true; location.href = 'callsearch.phtml?cdr_source=' + this.options[this.selectedIndex].value\"",
"value"=>"$cdr_source"
)
);
$cdr_table_els=array();
foreach ($this->tables as $_table) {
if (preg_match("/^.*(\d{6})$/",$_table,$m)) {
$cdr_table_els[]=array("label"=>$m[1],"value"=>$_table);
} else {
$cdr_table_els[]=array("label"=>$_table,"value"=>$_table);
}
}
$this->f->add_element(array( "name"=>"cdr_table",
"type"=>"select",
"options"=>$cdr_table_els,
"size"=>"1",
"value"=>$cdr_table
));
if ($begin_datetime) {
dprint("begin_datetime=$begin_datetime");
preg_match("/^(\d\d\d\d)-(\d+)-(\d+)\s+(\d\d):(\d\d)/", "$begin_datetime", $parts);
$begin_year =date(Y,$begin_datetime);
$begin_month=date(m,$begin_datetime);
$begin_day =date(d,$begin_datetime);
$begin_hour =date(H,$begin_datetime);
$begin_min =date(i,$begin_datetime);
} else {
$begin_day = $_REQUEST["begin_day"];
$begin_month = $_REQUEST["begin_month"];
$begin_year = $_REQUEST["begin_year"];
$begin_hour = $_REQUEST["begin_hour"];
$begin_min = $_REQUEST["begin_min"];
}
if ($end_datetime) {
dprint("end_datetime=$end_datetime");
preg_match("/^(\d\d\d\d)-(\d+)-(\d+)\s+(\d\d):(\d\d)/", "$end_datetime", $parts);
$end_year =date(Y,$end_datetime);
$end_month =date(m,$end_datetime);
$end_day =date(d,$end_datetime);
$end_hour =date(H,$end_datetime);
$end_min =date(i,$end_datetime);
} else {
$end_day = $_REQUEST["end_day"];
$end_month = $_REQUEST["end_month"];
$end_year = $_REQUEST["end_year"];
$end_hour = $_REQUEST["end_hour"];
$end_min = $_REQUEST["end_min"];
}
$default_year =Date("Y");
$default_month =Date("m");
$default_day =Date("d");
$default_hour =Date(H,time());
if ($default_hour > 1) {
$default_hour=$default_hour-1;
}
$default_hour=preg_replace("/^(\d)$/","0$1",$default_hour);
$default_min =Date("i");
if ($default_min > 10) {
$default_min=$default_min-10;
$default_min=preg_replace("/^(\d)$/","0$1",$default_min);
}
if (!$begin_hour) $begin_hour = $default_hour;
if (!$begin_min) $begin_min = $default_min;
if (!$begin_day) $begin_day = $default_day;
if (!$begin_month) $begin_month = $default_month;
if (!$begin_year) $begin_year = $default_year;
if (!$end_hour) $end_hour = 23;
if (!$end_min) $end_min = 55;
if (!$end_day) $end_day = $default_day;
if (!$end_month) $end_month = $default_month;
if (!$end_year) $end_year = $default_year;
$m=0;
while ($m<24) {
if ($m<10) { $v="0".$m; } else { $v=$m; }
$hours_els[]=array("label"=>$v,"value"=>$v);
$m++;
}
$this->f->add_element(array(
"name"=>"begin_hour",
"type"=>"select",
"options"=>$hours_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"end_hour",
"type"=>"select",
"options"=>$hours_els,
"size"=>"1",
"value"=>"23"
));
$m=0;
while ($m<60) {
if ($m<10) { $v="0".$m; } else { $v=$m; }
$min_els[]=array("label"=>$v,"value"=>$v);
$m++;
}
$this->f->add_element(array( "name"=>"begin_min",
"type"=>"select",
"options"=>$min_els,
"size"=>"1"
));
$this->f->add_element(array(
"name"=>"end_min",
"type"=>"select",
"options"=>$min_els,
"size"=>"1"
));
$m=1;
while ($m<32) {
if ($m<10) { $v="0".$m; } else { $v=$m; }
$days_els[]=array("label"=>$v,"value"=>$v);
$m++;
}
$this->f->add_element(array( "name"=>"begin_day",
"type"=>"select",
"options"=>$days_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"end_day",
"type"=>"select",
"options"=>$days_els,
"size"=>"1"
));
$m=1;
while ($m<13) {
if ($m<10) { $v="0".$m; } else { $v=$m; }
$month_els[]=array("label"=>$v,"value"=>$v);
$m++;
}
$this->f->add_element(array( "name"=>"begin_month",
"type"=>"select",
"options"=>$month_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"end_month",
"type"=>"select",
"options"=>$month_els,
"size"=>"1"
));
$thisYear=date("Y",time());
$y=$thisYear;
while ($y>$thisYear-6) {
$year_els[]=array("label"=>$y,"value"=>$y);
$y--;
}
$this->f->add_element(array( "name"=>"begin_year",
"type"=>"select",
"options"=>$year_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"end_year",
"type"=>"select",
"options"=>$year_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"call_id",
"type"=>"text",
"size"=>"50",
"maxlength"=>"100"
));
$this->f->add_element(array( "name"=>"a_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array( "name"=>"UserName",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array( "name"=>"c_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
if (!$this->CDRTool['filter']['aNumber']) {
$durations_els = array(
array("label"=>"All calls","value"=>""),
array("label"=>"0 seconds call","value"=>"zero"),
array("label"=>"non 0 seconds","value"=>"nonzero"),
array("label"=>"non 0 seconds with 0 price","value"=>"zeroprice"),
array("label"=>"less than 5 seconds","value"=>"< 5"),
array("label"=>"more than 5 seconds","value"=>"> 5"),
array("label"=>"less than 60 seconds","value"=>"< 60"),
array("label"=>"greater than 1 hour","value"=>"> 3600"),
array("label"=>"greater than 5 hours","value"=>"> 18000")
);
} else {
$durations_els = array(
array("label"=>"Succesfull calls","value"=>"nonzero")
);
}
$this->f->add_element(array( "name"=>"duration",
"type"=>"select",
"options"=>$durations_els,
"value"=>"All",
"size"=>"1"
));
$comp_ops_els = array(
array("label"=>"Begins with","value"=>"begin"),
array("label"=>"Contains","value"=>"contain"),
array("label"=>"Is empty","value"=>"empty"),
array("label"=>"Equal","value"=>"equal")
);
$this->f->add_element(array( "name"=>"a_number_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"c_number_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"UserName_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1"
));
$this->f->add_element(array( "name"=>"Realm",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25"
));
$this->f->add_element(array("type"=>"submit",
"name"=>"submit",
"value"=>"Search"
));
$max_els=array(
array("label"=>"5","value"=>"5"),
array("label"=>"10","value"=>"10"),
array("label"=>"15","value"=>"15"),
array("label"=>"25","value"=>"25"),
array("label"=>"50","value"=>"50"),
array("label"=>"100","value"=>"100"),
array("label"=>"500","value"=>"500")
);
$this->f->add_element(array( "name"=>"maxrowsperpage",
"type"=>"select",
"options"=>$max_els,
"size"=>"1",
"value"=>"25"
));
$order_type_els=array(
array("label"=>"Descending","value"=>"DESC"),
array("label"=>"Ascending","value"=>"ASC")
);
$this->f->add_element(array( "name"=>"order_type",
"type"=>"select",
"options"=>$order_type_els,
"size"=>"1"
));
$this->f->add_element(array("type"=>"hidden",
"name"=>"action",
"value"=>$action,
));
$order_by_els=array(array("label"=>"Id","value"=>"RadAcctId"),
array("label"=>"Date","value"=>"AcctStopTime"),
array("label"=>"Disconnection cause","value"=>"H323DisconnectCause"),
array("label"=>"Caller Party","value"=>"CallingStationId"),
array("label"=>"Destination","value"=>"CalledStationId"),
array("label"=>"Call duration","value"=>"AcctSessionTime"),
array("label"=>"Price","value"=>"Price"),
array("label"=>"Failures(%)","value"=>"zeroP"),
array("label"=>"Success(%)","value"=>"nonzeroP")
);
$group_by_els[]=array("label"=>"","value"=>"");
- while (list($k,$v)=each($this->GROUPBY)) {
+ foreach ($this->GROUPBY as $k => $v) {
$group_by_els[]=array("label"=>$v,"value"=>$k);
}
$this->f->add_element(array( "name"=>"order_by",
"type"=>"select",
"options"=>$order_by_els,
"value"=>$order_by,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"group_by",
"type"=>"select",
"options"=>$group_by_els,
"value"=>$group_by,
"size"=>"1"
));
// Cisco stuff
$this->f->add_element(array( "name"=>"NASIPAddress",
"type"=>"text",
"size"=>"25",
"maxlength"=>"50"
));
$this->f->add_element(array( "name"=>"RemoteAddress",
"type"=>"text",
"size"=>"15",
"maxlength"=>"50"
));
$this->f->add_element(array( "name"=>"NASPortId",
"type"=>"text",
"size"=>"15",
"maxlength"=>"25"
));
$H323CallType_els=array(
array("label"=>"Any technology","value"=>""),
array("label"=>"Telephony","value"=>"Telephony"),
array("label"=>"Voice over IP","value"=>"VoIP")
);
$this->f->add_element(array( "name"=>"H323CallType",
"type"=>"select",
"options"=>$H323CallType_els,
"size"=>"1"
));
$H323CallOrigin_els=array(
array("label"=>"Any origin","value"=>""),
array("label"=>"Incoming","value"=>"answer"),
array("label"=>"Outgoing","value"=>"originate")
);
$this->f->add_element(array( "name"=>"H323CallOrigin",
"type"=>"select",
"options"=>$H323CallOrigin_els,
"size"=>"1"
));
$this->f->add_element(array( "name"=>"release_cause",
"type"=>"select",
"options"=>$this->disconnectCodesElements,
"size"=>"1"
));
$this->f->load_defaults();
// Start displaying form
}
function searchForm() {
global $perm;
$this->initForm();
$this->f->start("","POST","","","datasource");
print "
<table cellpadding=5 CELLSPACING=0 border=6 width=100% align=center>
";
$this->showDataSources ($this->f);
$this->showDateTimeElements ($this->f);
if ($this->CDRTool['filter']['aNumber']) {
$ff[]="a_number";
}
if ($this->CDRTool['filter']['domain']) {
$ff[]="comp_id";
}
if (count($ff)) {
$this->f->freeze($ff);
}
print "
<tr>
<td align=left>
<b>Gateway</b>
</td>
<td valign=top>
";
$this->f->show_element("RemoteAddress","");
print " Local gateway:";
$this->f->show_element("NASIPAddress","");
print " Port Id ";
$this->f->show_element("NASPortId","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Call Id</b>
</td>
<td valign=top>
";
$this->f->show_element("call_id","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Caller Party
</b>
</td>
<td valign=top>
";
$this->f->show_element("a_number_comp","");
$this->f->show_element("a_number","");
print " Direction ";
$this->f->show_element("H323CallOrigin","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
Destination
</b>
</td>
<td valign=top> ";
$this->f->show_element("c_number_comp","");
$this->f->show_element("c_number","");
print " Technology ";
$this->f->show_element("H323CallType","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Call duration</b>
</td>
<td valign=top> ";
$this->f->show_element("duration","");
print "
Disconnection cause
";
$this->f->show_element("release_cause","");
print " ReNormalize";
print "<input type=checkbox name=ReNormalize value=1>";
print "
</td>
</tr>
";
print "
<tr>
<td align=left>
<b>Order by</b>
</td>
<td valign=top>
";
$this->f->show_element("order_by","");
$this->f->show_element("order_type","");
if ($perm->have_perm("statistics")) {
print " Group by ";
$this->f->show_element("group_by","");
}
print " Max results per page ";
$this->f->show_element("maxrowsperpage","");
print "
</td>
</tr>
";
print "
</table>
<p>
<center>
";
$this->f->show_element("submit","");
$this->f->finish();
print "</center>";
}
function showSubscriber() {
$this->show();
}
function show() {
global $perm;
foreach ($this->FormElements as $_el) {
${$_el} = $_REQUEST[$_el];
}
if (!$this->export) {
if (!$begin_datetime) {
$begin_datetime="$begin_year-$begin_month-$begin_day $begin_hour:$begin_min";
$begin_datetime_timestamp=mktime($begin_hour, $begin_min, 0, $begin_month,$begin_day,$begin_year);
} else {
$begin_datetime_timestamp=$begin_datetime;
$begin_datetime=Date("Y-m-d H:i",$begin_datetime);
}
$begin_datetime_url=urlencode($begin_datetime_timestamp);
if (!$end_datetime) {
$end_datetime_timestamp=mktime($end_hour, $end_min, 0, $end_month,$end_day,$end_year);
$end_datetime="$end_year-$end_month-$end_day $end_hour:$end_min";
} else {
$end_datetime_timestamp=$end_datetime;
$end_datetime=Date("Y-m-d H:i",$end_datetime);
}
$end_datetime_url=urlencode($end_datetime_timestamp);
} else {
$begin_datetime=Date("Y-m-d H:i",$begin_datetime);
$end_datetime=Date("Y-m-d H:i",$end_datetime);
}
if (!$order_by) {
$order_by=$this->timestampField;
$order_type="DESC";
}
// build an url to be able to log and refine the query
if (!$cdr_table) $cdr_table=$this->table;
$this->url="?cdr_source=$this->cdr_source&cdr_table=$cdr_table";
$this->url=$this->url."&order_by=$order_by&order_type=$order_type";
$this->url=$this->url."&begin_datetime=$begin_datetime_url";
$this->url=$this->url."&end_datetime=$end_datetime_url";
$where = " ($this->startTimeField >= '$begin_datetime' and $this->startTimeField < '$end_datetime')";
if ($this->CDRTool[filter][aNumber]) {
// force user to see only this a_number
$a_number=$this->CDRTool[filter][aNumber];
}
$a_number=trim($a_number);
if ($a_number_comp == "empty") {
$where .= " and $this->aNumberField = ''";
} else {
if ($a_number) {
if (!$a_number_comp) {
$a_number_comp="equal";
}
$a_number_encoded=urlencode($a_number);
$this->url="$this->url"."&a_number=$a_number_encoded";
if ($a_number_comp=="begin") {
$where .= " and ($this->aNumberField like '".addslashes($a_number)."%'";
$s=1;
} elseif ($a_number_comp=="contain") {
$where .= " and ($this->aNumberField like '%".addslashes($a_number)."%'";
$s=1;
} elseif ($a_number_comp=="equal") {
$where .= " and ($this->aNumberField = '".addslashes($a_number)."'";
$s=1;
}
if ($this->CDRTool[filter][aNumber]) {
$where .= " or $this->cNumberField like '".addslashes($a_number)."%') ";
} else {
if ($s) {
$where .= ")";
}
}
$this->url=$this->url."&a_number_comp=$a_number_comp";
}
}
if ($UserName_comp != "empty") {
if ($UserName) {
if (!$UserName_comp) {
$UserName_comp="begin";
}
$UserName_encoded=trim($UserName);
$UserName_encoded=urlencode($UserName);
$this->url="$this->url"."&UserName=$UserName_encoded";
if ($UserName_comp=="begin") {
$where .= " and $this->usernameField like '".addslashes($UserName)."%'";
} elseif ($UserName_comp=="contain") {
$where .= " and $this->usernameField like '%".addslashes($UserName)."%'";
} elseif ($UserName_comp=="equal") {
$where .= " and $this->usernameField = '".addslashes($UserName)."'";
}
}
} else {
$where .= " and $this->usernameField = ''";
}
if ($NASPortId) {
$NASPortId_encoded=urlencode($NASPortId);
$where = "$where"." and $this->NASPortIdField = '".addslashes($NASPortId)."'";
$this->url="$this->url"."&$this->NASPortIdField=$NASPortId_encoded";
}
$call_id_encoded=trim($call_id);
if ($call_id) {
$where = "$where"." and $this->callIdField = '".addslashes($call_id)."'";
$call_id_encoded=urlencode($call_id);
$this->url="$this->url"."&call_id=$call_id_encoded";
}
if ($release_cause) {
$release_cause_hex=dechex($release_cause);
$where = "$where"." and $this->disconnectField = '".addslashes($release_cause_hex)."'";
$this->url="$this->url"."&release_cause=$release_cause";
}
if ($DestinationId) {
$where = "$where"." and $this->DestinationIdField = '".addslashes($DestinationId)."'";
$this->url="$this->url"."&$this->DestinationIdField=$DestinationId";
}
if ($H323CallType) {
$where = "$where"." and $this->H323CallTypeField = '".addslashes($H323CallType)."'";
$this->url="$this->url"."&$this->H323CallTypeField=$H323CallType";
} else {
if ($group_by) {
if ($group_by=="RemoteAddress") {
$where = "$where"." and $this->H323CallTypeField = 'VoIP'";
$this->url="$this->url"."&$this->H323CallTypeField=VoIP";
} else {
$where = "$where"." and $this->H323CallTypeField = 'Telephony'";
$this->url="$this->url"."&$this->H323CallTypeField=Telephony";
}
} else {
$where = "$where"." and ($this->H323CallTypeField = 'VoIP' or
$this->H323CallTypeField = 'Telephony')";
}
}
if ($NASIPAddress) {
$NASIPAddress_encoded=urlencode($NASIPAddress);
$where = "$where"." and $this->localGatewayField = '".addslashes($NASIPAddress)."'";
$this->url="$this->url"."&$this->localGatewayField=$NASIPAddress_encoded";
}
if ($RemoteAddress) {
$where = "$where"." and $this->RemoteAddressField = '".addslashes($RemoteAddress)."'";
$this->url="$this->url"."&RemoteAddress=$RemoteAddress";
}
if ($H323CallOrigin) {
$where = "$where"." and $this->H323CallOriginField = '".addslashes($H323CallOrigin)."'";
$this->url="$this->url"."&$this->H323CallOriginField=$H323CallOrigin";
}
$c_number=trim($c_number);
if (strlen($c_number)) {
# Trim content of dest_form - allow only digits
if ($c_number_comp=="begin") {
$where = "$where"." and $this->cNumberField like '".addslashes($c_number)."%'";
} elseif ($c_number_comp=="equal") {
$where = "$where"." and $this->cNumberField = '".addslashes($c_number)."'";
} elseif ($c_number_comp=="contain") {
$where .= " and $this->cNumberField like '%".addslashes($c_number)."%'";
} else {
$where = "$where"." and $this->cNumberField like '%".addslashes($c_number)."%'";
}
$c_number_encoded=urlencode($c_number);
$this->url=$this->url."&c_number=$c_number_encoded&c_number_comp=$c_number_comp";
}
if ($duration) {
if (preg_match("/\d+/",$duration) ) {
$where .= " and ($this->durationField > 0 and $this->durationField $duration) ";
} elseif ($duration == "zero") {
$where = "$where"." and $this->durationField = 0";
} elseif ($duration == "nonzero") {
$where = "$where"." and $this->durationField > 0";
}
$duration_enc=urlencode($duration);
$this->url="$this->url"."&duration=$duration_enc";
}
$this->url="$this->url"."&maxrowsperpage=$this->maxrowsperpage";
$url_calls = $this->scriptFile.$this->url."&action=search";
if ($group_by) {
$this->url="$this->url"."&group_by=$group_by";
}
$this->url_edit = $this->scriptFile.$this->url."&action=edit";
$this->url_run = $this->scriptFile.$this->url."&action=search";
$this->url_export = $_SERVER["PHP_SELF"].$this->url."&action=search&export=1";
if ($group_by) {
if (!$perm->have_perm("statistics")) {
print "<p><font color=red>You do not have the right for statistics.</font>";
return 0 ;
}
$this->group_by=$group_by;
$query= "
select sum($this->durationField) as duration,
count($group_by) as calls, $group_by
from $this->table
where $where
group by $group_by
";
} else {
$query = "select count(*) as records from $this->table where"."$where";
}
dprint("$query");
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
if ($group_by) {
$rows=$this->CDRdb->num_rows();
} else {
$rows = $this->CDRdb->f('records');
}
} else {
print "$this->CDRdb->Error";
$rows = 0;
}
$this->rows=$rows;
if ($this->CDRTool[filter][aNumber]) {
$this->showResultsMenuSubscriber('0',$begin_datetime,$end_datetime);
} else {
$this->showResultsMenu('0',$begin_datetime,$end_datetime);
}
if (!$this->next) {
$i=0;
$this->next=0;
} else {
$i=$this->next;
}
$j=0;
$z=0;
if ($rows>0) {
if ($UnNormalizedCalls=$this->getUnNormalized($where,$cdr_table)) {
dprint("Normalize calls");
$this->NormalizeCDRS($where,$cdr_table);
if (!$this->export && $this->status['normalized'] ) {
printf ("<p> Found %d CDRs for normalization. ",$this->status['normalized']);
}
}
$this->$rows=$rows;
if ($rows > $this->maxrowsperpage) {
$maxrows=$this->maxrowsperpage+$this->next;
if ($maxrows > $rows) {
$maxrows=$rows;
$prev_rows=$maxrows;
}
} else {
$maxrows=$rows;
}
if ($group_by) {
if ($order_by == $this->inputTrafficField ||
$order_by == $this->outputTrafficField ||
$order_by == $this->durationField ||
$order_by == $this->priceField ||
$order_by == "zeroP" ||
$order_by == "nonzeroP"
) {
$order_by1=$order_by;
} else {
$order_by1="calls";
}
$query= "
select sum($this->durationField) as $this->durationField,
SEC_TO_TIME(sum($this->durationField)) as hours,
count($group_by) as calls, ";
if ($this->priceField) {
$query.=" sum($this->priceField) as price, ";
}
$query.="
$this->H323CallTypeField,
sum($this->inputTrafficField) as $this->inputTrafficField,
sum($this->outputTrafficField) as $this->outputTrafficField,
SUM($this->durationField = '0') as zero,
SUM($this->durationField > '0') as nonzero,
";
if ($order_by=="zeroP" || $order_by=="nonzeroP") {
$query.="
SUM($this->durationField = '0')/count($group_by)*100 as zeroP,
SUM($this->durationField > '0')/count($group_by)*100 as nonzeroP,
";
}
$query.="
$group_by as group_by
from $this->table
where $where
group by $group_by
order by $order_by1 $order_type
limit $i,$this->maxrowsperpage
";
dprint($query);
$this->CDRdb->query($query);
$this->showTableHeaderStatistics();
while ($i<$maxrows) {
$found=$i+1;
$this->CDRdb->next_record();
$seconds =$this->CDRdb->f($this->durationField);
$seconds_print =number_format($this->CDRdb->f($this->durationField),0);
$minutes =number_format($this->CDRdb->f($this->durationField)/60,0,"","");
$minutes_print =number_format($this->CDRdb->f($this->durationField)/60,0);
$hours =$this->CDRdb->f('hours');
$calls =$this->CDRdb->f('calls');
if ($this->priceField) {
$price =$this->CDRdb->f('price');
}
$AcctInputOctets =number_format($this->CDRdb->f($this->inputTrafficField)/1024,2,".",".");
$AcctOutputOctets =number_format($this->CDRdb->f($this->outputTrafficField)/1024,2,".",".");
$H323CallType =$this->CDRdb->f($this->H323CallTypeField);
$AcctTerminateCause =$this->CDRdb->f($this->disconnectField);
$mygroup =$this->CDRdb->f('group_by');
$zero =$this->CDRdb->f('zero');
$nonzero =$this->CDRdb->f('nonzero');
$success =number_format($nonzero/$calls*100,2,".",".");
$failure =number_format($zero/$calls*100,2,".",".");
if ($group_by==$this->disconnectField) {
if ($mygroup=="AC") {
$mygroup="22";
}
$DisconnectCause=hexdec($mygroup);
$mygroup_print=hexdec($mygroup);
$mygroup_enc=urlencode($DisconnectCause);
} else {
$DisconnectCause ="";
$mygroup_print=$mygroup;
$mygroup_enc=urlencode($mygroup);
}
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
if ($group_by == $this->disconnectField) {
$description=$this->disconnectCodesDescription[$DisconnectCause];
} else if ($group_by==$this->DestinationIdField) {
if ($this->CDRTool['filter']['aNumber']) {
$description=$this->destinations[$this->CDRTool['filter']['aNumber']][$mygroup];
} else if ($this->CDRTool['filter']['domain']) {
$description=$this->destinations[$this->CDRTool['filter']['domain']][$mygroup];
} else {
$description=$this->destinations["default"][$mygroup];
}
} else {
$description="";
}
if ($group_by==$this->aNumberField) {
$traceField="a_number";
} else if ($group_by==$this->cNumberField) {
$traceField="c_number";
} else if ($group_by==$this->disconnectField) {
$traceField="release_cause";
} else {
$traceField=$group_by;
}
if (!$this->export) {
$pricePrint=number_format($price,4);
print "
<tr bgcolor=$inout_color>
<td><b>$found</b></td>
<td align=right>$calls</td>
<td align=right>$seconds_print</td>
<td align=right>$minutes_print</td>
<td align=right>$hours</td>";
if ($this->rating) {
print "<td align=right>$pricePrint</td>";
}
print "
<td align=right>$AcctInputOctets
<td align=right>$AcctOutputOctets
<td align=right>$success%</td>
<td align=right>($nonzero calls)</td>
<td align=right>$failure%</td>
<td align=right>($zero calls)</td>
<td>$mygroup_print
<td>$description
<td align=right>$H323CallType</td>
<td><a href=$url_calls&$traceField=$mygroup_enc target=_new>Display calls </a>
</tr>
";
} else {
print "$found,$calls,$seconds,$minutes,$hours,$AcctInputOctets,$AcctOutputOctets,$success,$nonzero,$failure,$zero,$mygroup_print,$description\n";
}
$i++;
}
if (!$this->export) {
print "
</table>
</td>
</tr>
</table>
";
}
} else {
if ($order_by=="zeroP" || $order_by=="nonzeroP") {
$order_by="timestamp";
}
$query = "select *, UNIX_TIMESTAMP($this->startTimeField) as timestamp
from $this->table where ".
"$where ".
"order by $order_by $order_type ".
"limit $i,$this->maxrowsperpage";
dprint($query);
$this->CDRdb->query($query);
if (!$this->export) {
$this->showTableHeader();
} else {
$this->showExportHeader();
}
while ($i<$maxrows) {
global $found;
$found=$i+1;
$this->CDRdb->next_record();
$Structure=$this->_readCDRFieldsFromDB();
$CDR = new $this->CDR_class($this, $Structure);
if (!$this->export) {
$CDR->show();
} else {
$CDR->export();
}
$i++;
}
if (!$this->export) {
print "
</table>
</td>
</tr>
</table>
";
}
}
dprint("$query");
$this->showPagination($this->next,$maxrows);
}
}
function import($file,$timezone) {
$b=time();
$this->radiusAttributes=array(
"Acct-Session-Id" => "AcctSessionId",
"Calling-Station-Id" => "CallingStationId",
"Called-Station-Id" => "CalledStationId",
"Acct-Status-Type" => "",
"Realm" => "",
"Acct-Authentic" => "AcctAuthentic",
"Acct-Terminate-Cause" => "AcctTerminateCause",
"User-Name" => "UserName",
"Service-Type" => "ServiceType",
"NAS-IP-Address" => "NASIPAddress",
"Acct-Delay-Time" => "AcctDelayTime",
"Client-IP-Address" => "ClientIPAddress",
"Acct-Unique-Session-Id" => "AcctUniqueId",
"Timestamp" => "Timestamp",
"NAS-Port-Id" => "NASPortId",
"Cisco-NAS-Port" => "CiscoNASPort",
"NAS-Port-Type" => "NASPortType",
"NAS-Port" => "NASPort",
"Framed-Protocol" => "FramedProtocol",
"Framed-IP-Address" => "FramedIPAddress",
"Connect-Info" => "ConnectInfo_stop",
"h323-setup-time" => "H323SetupTime",
"h323-connect-time" => "H323ConnectTime",
"h323-disconnect-time" => "H323DisconnectTime",
"h323-disconnect-cause" => "H323DisconnectCause",
"h323-remote-address" => "H323RemoteAddress",
"h323-voice-quality" => "H323VoiceQuality",
"h323-gw-id" => "H323GWID",
"h323-conf-id" => "H323ConfID",
"h323-call-origin" => "H323CallOrigin",
"h323-call-type" => "H323CallType",
"Acct-Input-Octets" => "AcctInputOctets",
"Acct-Output-Octets" => "AcctOutputOctets",
"Acct-Input-Packets" => "AcctInputPackets",
"Acct-Output-Packets" => "AcctOutputPackets",
"Acct-Session-Time" => "AcctSessionTime"
);
if (!$fp=fopen("$file","r")) {
print "Error: cannot open file $file\n";
return 0;
} else {
$filesize=filesize($file);
print "File $file (size=$filesize) succesfully opened.\n";
}
$success=0;
$failed =0;
if ($filesize > 100000) {
print "Import progress: ";
flush();
}
while (!feof($fp)) {
$record = $this->RadiusRecordRead($fp);
$radiusParsed = $this->RadiusRecordParse($record);
$currentFilePointer=ftell($fp);
if ($filesize > 100000) {
if ($currentFilePointer> $progress*$filesize/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
if ($progress==100) {
print "\n";
}
}
flush();
}
}
dprint_r($radiusParsed);
$packetType = $radiusParsed["Acct-Status-Type"];
$radiusTable = $this->table;
unset($query);
if ($packetType=="Start") {
$results[$file][$packetType]++;
$accounting_start_query= "INSERT into $this->table (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '0', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0')";
$query=$accounting_start_query;
$query=preg_replace("/%{/","",$query);
$query=preg_replace("/}'/","'",$query);
$query=preg_replace("/}\)/",")",$query);
$Timestamp=getLocalTime($timezone,$radiusParsed[Timestamp]);
$query=preg_replace("/'%S'/","'$Timestamp'",$query);
$query=preg_replace("/SQL-User-Name/","User-Name",$query);
foreach (array_keys($this->radiusAttributes) as $attribute) {
$value=$radiusParsed[$attribute];
$query=preg_replace("/'$attribute'/","'$value'",$query);
}
} else if ($packetType=="Stop") {
$accounting_stop_query = "INSERT into $this->table (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, CiscoNASPort, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay, H323GWId, H323CallOrigin, H323CallType, H323Setuptime,H323ConnectTime, H323DisconnectTime,H323DisconnectCause,H323RemoteAddress,H323VoiceQuality, H323ConfId, Timestamp ) values ('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{Cisco-NAS-Port}','%{NAS-Port-Id}', '%{NAS-Port-Type}', from_unixtime(unix_timestamp('%S')-%{Acct-Session-Time}), '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}', SUBSTRING('%{h323-remote-address}',21), SUBSTRING('%{h323-call-origin}',18), SUBSTRING('%{h323-call-type}',16), SUBSTRING('%{h323-setup-time}',18), SUBSTRING('%{h323-connect-time}',20), SUBSTRING('%{h323-disconnect-time}',23), SUBSTRING('%{h323-disconnect-cause}',23), SUBSTRING('%{h323-remote-address}',21),SUBSTRING('%{h323-voice-quality}',20), SUBSTRING('%{h323-conf-id}',14) , '%{Timestamp}')";
$query=$accounting_stop_query;
$query=preg_replace("/%{/","",$query);
$query=preg_replace("/}'/","'",$query);
$query=preg_replace("/}\)/",")",$query);
$Timestamp=getLocalTime($timezone,$radiusParsed[Timestamp]);
$query=preg_replace("/'%S'/","'$Timestamp'",$query);
$query=preg_replace("/SQL-User-Name/","User-Name",$query);
foreach (array_keys($this->radiusAttributes) as $attribute) {
$value=$radiusParsed[$attribute];
$query=preg_replace("/'$attribute'/","'$value'",$query);
$value=$radiusParsed['Acct-Session-Time'];
$query=preg_replace("/Acct-Session-Time/","$value",$query);
}
}
if ($query) {
$results[$file][packetTypes][$packetType]++;
$AcctSessionId=$radiusParsed["Acct-Session-Id"];
dprint ("$packetType Radius packet $AcctSessionId\n");
$this->CDRdb->Halt_On_Error="no";
dprint("$query\n");
if ($this->CDRdb->query($query)) {
if ($packetType=="Start" || $packetType=="Failed" ) {
if ($this->CDRdb->affected_rows()) {
$results[$file][database][insert]++;
} else {
$results[$file][database][insertExists]++;
}
} else if ($packetType=="Stop") {
if ($this->CDRdb->affected_rows()) {
$results[$file][database][update]++;
} else {
$results[$file][database][updateExists]++;
}
}
} else {
$results[$file][database][errorType][$packetType]++;
$results[$file][database][error]++;
$results[$file][database][errors][$this->CDRdb->Errno]++;
$results[$file][database][errorDict][$this->CDRdb->Errno]=$this->CDRdb->Error;
}
$results[$file][database][queries]++;
}
}
$e=time();
$d=$e-$b;
print "Import results (script runtime $d s)\n";
foreach (array_keys($results[$file][packetTypes]) as $ptype) {
$howmany=$results[$file][packetTypes][$ptype];
print "$ptype: $howmany packets ";
$totalPackets=$totalPackets+$howmany;
}
print "\nDatabase import statistics: ";
if ($results[$file][database][insert]) {
$howmany=$results[$file][database][insert];
print "$howmany records inserted ";
}
if ($results[$file][database][update]) {
$howmany=$results[$file][database][update];
print "$howmany records updated";
}
if ($results[$file][database][error]) {
$howmany=$results[$file][database][error];
$queries=$results[$file][database][queries];
print "\n$queries queries from which $howmany queries failed\n";
foreach (array_keys($results[$file][database][errors]) as $error) {
$howmany=$results[$file][database][errors][$error];
$errorDescription=$results[$file][database][errorDict][$error];
print "MySQL Error $error ($errorDescription): $howmany errors\n";
}
print "Error were generated by the folowing RADIUS packet types:\n";
foreach (array_keys($results[$file][database][errorType]) as $errorType) {
$howmany=$results[$file][database][errorType][$errorType];
print "$errorType packet: $howmany errors\n";
}
}
if ($d) {
$importSpeed=number_format($totalPackets/$d,0,"","");
print "Import speed: $importSpeed packets / second\n";
}
}
}
class CDR_cisco extends CDR {
function CDR_cisco(&$parent, $CDRfields) {
$this->CDRS = & $parent;
dprint("<hr>Init CDR");
dprint($this->timestampField);
dprint_r($CDRfields);
foreach (array_keys($this->CDRS->CDRFields) as $field) {
$key=$this->CDRS->CDRFields[$field];
$this->$field = quoted_printable_decode($CDRfields[$key]);
$mysqlField=$this->CDRS->CDRFields[$field];
$_field=$field."Field";
$this->$_field=$mysqlField;
}
if ($this->CDRS->rating) {
$this->showRate = $this->CDRS->showRate;
}
$this->dayofweek = date("w",$this->timestamp);
$this->hourofday = date("G",$this->timestamp);
$this->dayofyear = date("Y-m-d",$this->timestamp);
$this->traffic = 2*($this->inputTraffic+$this->outputTraffic);
if (!$this->NASPortId) {
$this->NASPortIdPrint=$this->RemoteAddress;
} else {
$this->NASPortIdPrint=$this->NASPortId;
}
if (preg_match("/^(ISDN) ([0-9]+)/",$this->NASPortIdPrint,$m)) {
$this->gateway=$this->localGateway."-".$m[1]."-".$m[2];
} else if ($this->RemoteAddress) {
$this->gateway=$this->RemoteAddress;
}
if ($this->H323GWID) {
$this->aNumberPrint=$this->aNumber."@".$this->H323GWID;
} else {
$this->aNumberPrint=$this->aNumber;
}
dprint("A number");
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->aNumber,"source");
$this->aNumberPrint = $NormalizedNumber[NumberPrint];
$this->aNumberNormalized = $NormalizedNumber[Normalized];
dprint("C number");
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->cNumber);
$this->cNumberPrint = $NormalizedNumber[NumberPrint];
$this->cNumberNormalized = $NormalizedNumber[Normalized];
$this->DestinationId = $NormalizedNumber[DestinationId];
$this->destinationName = $NormalizedNumber[destinationName];
$this->inputTrafficPrint = number_format(2*$this->inputTraffic/1024,2);
$this->outputTrafficPrint = number_format(2*$this->outputTraffic/1024,2);
$this->durationPrint=sec2hms($this->duration);
$this->disconnectPrint=$this->NormalizeDisconnect($this->disconnect);
if ($this->H323CallOrigin=="answer") {
$this->H323CallOrigin="incoming";
} elseif ($this->H323CallOrigin=="originate") {
$this->H323CallOrigin="outgoing";
}
$this->traceIn();
$this->traceOut();
if ($this->price == "0.0000") {
$this->pricePrint="";
} else {
$this->pricePrint=$this->price;
}
$this->NetworkRateDictionary=array(
'callId' => $this->callId,
'Timestamp' => $this->timestamp,
'Duration' => $this->duration,
'inputTraffic' => $this->inputTraffic,
'outputTraffic' => $this->outputTraffic,
'Application' => "audio",
'Gateway' => $this->gateway,
'From' => $this->aNumberNormalized,
'To' => $this->cNumberNormalized
);
}
function NormalizeDisconnect() {
$this->disconnect=hexdec($this->disconnect);
$causePrint=$this->CDRS->disconnectCodesDescription[$this->disconnect];
return $causePrint;
}
function traceIn() {
if ($this->H323CallOrigin=="incoming" && $this->CDRS->traceInURL[$this->gateway]) {
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$url_trace="&trace=1&action=search&c_number=$this->cNumber&c_number_comp=contain&begin_datetime=$tmin&end_datetime=$tplus";
$this->traceIn="<a href=".$this->CDRS->traceInURL[$this->gateway].$url_trace." target=bottom>In</a>";
}
}
function traceOut() {
if (!$this->H323CallOrigin=="outgoing" || !$this->CDRS->traceOutURL[$this->gateway]) {
return;
}
$datasource=$this->CDRS->traceOutURL[$this->gateway];
global $DATASOURCES;
if (!$datasource || !$DATASOURCES[$datasource]) {
return;
}
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$cdr_table = $DATASOURCES[$datasource][table];
$c_number = preg_replace("/^(0+)/","",$this->cNumber);
$this->traceOut=
"<a href=callsearch.phtml".
"?cdr_source=$datasource".
"&cdr_table=$cdr_table".
"&trace=1".
"&action=search".
"&c_number=$c_number".
"&c_number_comp=contain".
"&begin_datetime=$tmin".
"&end_datetime=$tplus".
" target=bottom>".
"Out".
"</a>";
}
function showSubscriber() {
$this->show();
}
function show() {
global $found;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
$check=date("Y-m-d H:i",$this->timestamp);
print "
<tr bgcolor=$inout_color>
<td><b>$found</b></td>
<td>$this->startTime</td>
<td>$this->aNumberPrint</td>
<td>$this->traceIn</td>
<td>$this->cNumberPrint</td>
<td>$this->destinationName $this->DestinationId</td>
<td>$this->traceOut</td>
";
if ($this->duration) {
print "<td align=right>$this->durationPrint</td>";
} else {
print "<td align=right><font color=red>$this->durationPrint</a></td>";
}
if ($this->CDRS->rating) {
$this->ratePrint=nl2br($this->rate);
if ($this->showRate) {
print "<td>$this->ratePrint</td>";
}
if ($this->price) {
$quotedRate = addcslashes(nl2br($this->rate), "\n\r");
$jscode="onMouseOver=\"stm('Rating info', '$quotedRate', Style['right'])\" onMouseOut=\"htm()\"";
} else {
$jscode = "";
}
print "<td valign=top align=right $jscode>$this->pricePrint</td>
";
}
print "
<td>$this->gateway</td>
<td>$this->inputTrafficPrint</td>
<td>$this->outputTrafficPrint</td>
<td>$this->disconnectPrint ($this->disconnect)</td>
<td>$this->NASPortIdPrint</td>
<td>$this->H323CallOrigin</td>
<td>$this->H323CallType</td>
</tr>
";
}
function export() {
global $found;
print "$found";
print ",$this->startTime";
print ",$this->username";
print ",$this->aNumberPrint";
print ",$this->cNumberPrint";
print ",$this->DestinationId";
print ",$this->destinationName";
print ",$this->duration";
print ",$this->pricePrint";
print ",$this->gateway";
print ",$this->inputTraffic";
print ",$this->outputTraffic";
print ",$this->disconnect";
print ",$this->disconnectPrint";
print ",$this->NASPortIdPrint";
print ",$this->H323CallOrigin";
print ",$this->H323CallType";
print "\n";
}
}
?>
diff --git a/library/cdr_generic.php b/library/cdr_generic.php
index f40c682..6e2d32c 100644
--- a/library/cdr_generic.php
+++ b/library/cdr_generic.php
@@ -1,3360 +1,3360 @@
<?php
$tz = $CDRTool['provider']['timezone'];
putenv("TZ=$tz");
class CDRS {
var $CDR_class = 'CDR';
var $intAccessCode = '00';
var $natAccessCode = '0';
var $maxrowsperpage = 15;
var $status = array();
var $normalizedField = 'Normalized';
var $DestinationIdField = 'DestinationId';
var $BillingIdField = 'UserName';
var $defaults = array();
var $whereUnnormalized = '';
var $skipNormalize = false;
var $reNormalize = false;
var $usageKeysForDeletionFromCache = array();
var $localDomains = array();
var $trustedPeers = array();
var $maxCDRsNormalizeWeb = 500;
var $E164_class = 'E164_Europe';
var $quotaEnabled = false;
var $csv_writter = false;
var $CallerIsLocal = false;
var $CalleeIsLocal = false;
var $CDRNormalizationFields = array(
'id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'username' => 'UserName',
'domain' => 'Realm',
'gateway' => 'NASIPAddress',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'BillingPartyId' => 'UserName',
'sipRPID' => 'SipRPID',
'ResellerId' => 'BillingId',
'price' => 'Price',
'DestinationId' => 'DestinationId'
);
function _readCDRNormalizationFieldsFromDB()
{
foreach (array_keys($this->CDRNormalizationFields) as $field) {
$mysqlField = $this->CDRNormalizationFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function _readCDRFieldsFromDB($fields)
{
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField = $this->CDRFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function initCDRFields()
{
// init names of CDR fields
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField = $this->CDRFields[$field];
$_field = $field."Field";
$this->$_field = $mysqlField;
}
}
function initDatabaseConnection()
{
// connect to the CDR database(s)
if(!$this->DATASOURCES[$this->cdr_source]['db_class']) {
$log = sprintf("Error: \$DATASOURCES['%s']['db_class'] is not defined (init)", $this->cdr_source);
syslog(LOG_NOTICE, $log);
return 0;
}
$_dbClass = $this->DATASOURCES[$this->cdr_source]['db_class'];
if (is_array($_dbClass)) {
if ($_dbClass[0]) $this->primary_database = $_dbClass[0];
if ($_dbClass[1]) $this->secondary_database = $_dbClass[1];
} else {
$this->primary_database = $_dbClass;
}
if(!class_exists($this->primary_database)) {
$log = sprintf("Error: database class '%s' is not defined", $this->primary_database);
syslog(LOG_NOTICE, $log);
return 0;
}
$this->CDRdb = new $this->primary_database;
// check db connectivity
if (!$this->CDRdb->query('SELECT 1')) {
$log = sprintf("Error: failed to connect to the primary CDR database %s\n", $this->primary_database);
syslog(LOG_NOTICE, $log);
if ($this->secondary_database) {
$this->CDRdb = new $this->secondary_database;
if (!$this->CDRdb->query('SELECT 1')) {
$log = sprintf("Error: failed to connect to the secondary CDR database %s\n", $this->secondary_database);
syslog(LOG_NOTICE, $log);
return 0;
} else {
$this->CDRdb1 = new $this->secondary_database;
$this->db_class = $this->secondary_database;
}
} else {
return 0;
}
} else {
$this->CDRdb1 = new $this->primary_database;
$this->db_class = $this->primary_database;
}
return 1;
}
function __construct($cdr_source)
{
global $CDRTool;
global $DATASOURCES;
global $RatingEngine;
if (!$cdr_source) {
$log = "Error: cdr_source not defined\n";
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$DATASOURCES[$cdr_source]) {
$log = sprintf("Error: no such datasource defined (%s)\n", $cdr_source);
syslog(LOG_NOTICE, $log);
return 0;
}
$this->initDefaults();
$this->cdrtool = new DB_CDRTool();
$this->cdr_source = $cdr_source;
$this->CDRTool = $CDRTool;
$this->rating_settings = $RatingEngine;
$this->DATASOURCES = $DATASOURCES;
$this->cdrtool->Halt_On_Error = "no";
$this->table = $this->DATASOURCES[$this->cdr_source]['table'];
$this->initCDRFields();
if ($this->DATASOURCES[$this->cdr_source]['rating']) {
$this->ratingEnabled = 1;
$this->rating = $this->DATASOURCES[$this->cdr_source]['rating'];
if ($this->DATASOURCES[$this->cdr_source]['showRate']) $this->showRate = $this->DATASOURCES[$this->cdr_source]['showRate'];
if ($this->DATASOURCES[$this->cdr_source]['rateField']) $this->rateField = $this->DATASOURCES[$this->cdr_source]['rateField'];
if ($this->DATASOURCES[$this->cdr_source]['priceField']) $this->priceField = $this->DATASOURCES[$this->cdr_source]['priceField'];
}
if ($this->DATASOURCES[$this->cdr_source]['UserQuotaClass']) {
$this->quotaEnabled = 1;
$this->quota_init_flag = $this->cdr_source.':quotaCheckInit';
$this->quota_reset_flag = $this->cdr_source.':reset_quota_for';
if ($this->DATASOURCES[$this->cdr_source]['daily_quota']) {
$this->daily_quota=$this->DATASOURCES[$this->cdr_source]['daily_quota'];
}
}
$this->initDatabaseConnection();
if ($this->DATASOURCES[$this->cdr_source]['DestinationIdField']) {
$this->DestinationIdField = $this->DATASOURCES[$this->cdr_source]['DestinationIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['normalizedField']) {
$this->normalizedField = $this->DATASOURCES[$this->cdr_source]['normalizedField'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['intAccessCode'])) {
$this->intAccessCode = $this->DATASOURCES[$this->cdr_source]['intAccessCode'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['natAccessCode'])) {
$this->natAccessCode = $this->DATASOURCES[$this->cdr_source]['natAccessCode'];
}
if ($this->DATASOURCES[$this->cdr_source]['db_subscribers']) {
if (class_exists($this->DATASOURCES[$this->cdr_source]['db_subscribers'])) {
$this->AccountsDB = new $this->DATASOURCES[$this->cdr_source]['db_subscribers'];
$this->db_subscribers = $this->DATASOURCES[$this->cdr_source]['db_subscribers'];
} else {
$log = sprintf(
"Error: subscribers database class %s is not defined",
$this->DATASOURCES[$this->cdr_source]['db_subscribers']
);
syslog(LOG_NOTICE, $log);
return 0;
}
} else if (class_exists('DB_opensips')) {
$this->AccountsDB = new DB_opensips();
$this->db_subscribers = 'DB_opensips';
} else {
$log = sprintf(
"Error: subscribers database is not defined, please define 'db_subscribers' in datasource '%s'",
$this->cdr_source
);
syslog(LOG_NOTICE, $log);
return 0;
}
if ($this->DATASOURCES[$this->cdr_source]['BillingIdField']) {
$this->BillingIdField = $this->DATASOURCES[$this->cdr_source]['BillingIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['E164_class']) {
if (class_exists($this->DATASOURCES[$this->cdr_source]['E164_class'])) {
$this->E164_class = $this->DATASOURCES[$this->cdr_source]['E164_class'];
} else {
printf(
"Error: E164 class '%s' defined in datasource %s does not exist, using default '%s'",
$this->DATASOURCES[$this->cdr_source]['E164_class'],
$this->cdr_source,
$this->E164_class
);
}
}
if ($this->DATASOURCES[$this->cdr_source]['sipTrace']) {
$this->sipTrace = $this->DATASOURCES[$this->cdr_source]['sipTrace'];
}
if ($this->DATASOURCES[$this->cdr_source]['mediaTrace']) {
$this->mediaTrace = $this->DATASOURCES[$this->cdr_source]['mediaTrace'];
}
if ($this->DATASOURCES[$this->cdr_source]['domain_table']) {
$this->domain_table = $this->DATASOURCES[$this->cdr_source]['domain_table'];
}
if ($this->DATASOURCES[$this->cdr_source]['skipNormalize']) {
$this->skipNormalize = $this->DATASOURCES[$this->cdr_source]['skipNormalize'];
}
if ($this->DATASOURCES[$this->cdr_source]['enableThor']) {
$this->enableThor = $this->DATASOURCES[$this->cdr_source]['enableThor'];
}
if (is_array($this->CDRTool['normalize']['CS_CODES'])) $this->CS_CODES=array_keys($this->CDRTool['normalize']['CS_CODES']);
$this->missed_calls = $this->DATASOURCES[$this->cdr_source]['missed_calls'];
$this->traceInURL = $this->DATASOURCES[$this->cdr_source]['traceInURL'];
$this->traceOutURL = $this->DATASOURCES[$this->cdr_source]['traceOutURL'];
$this->protocolTraceURL = $this->DATASOURCES[$this->cdr_source]['protocolTraceURL'];
$spath = explode("/",$_SERVER["PHP_SELF"]);
$last = count($spath)-1;
$this->scriptFile=$spath[$last];
$this->next = $_REQUEST["next"];
$this->export = $_REQUEST["export"];
$this->trace = $_REQUEST["trace"];
if ($this->export) {
$this->maxrowsperpage=10000000;
} else {
if ($_REQUEST["maxrowsperpage"]) {
$this->maxrowsperpage = $_REQUEST["maxrowsperpage"];
} else {
$this->maxrowsperpage = "25";
}
}
$this->LoadDisconnectCodes();
$this->LoadDestinations();
$this->LoadENUMtlds();
$this->LoadDomains();
$this->LoadTrustedPeers();
$this->getCDRtables();
if ($this->DATASOURCES[$this->cdr_source]['csv_writer_class']) {
$csv_writter_class=$this->DATASOURCES[$this->cdr_source]['csv_writer_class'];
if (class_exists($csv_writter_class)) {
$this->csv_writter = new $csv_writter_class(
$this->cdr_source,
$this->DATASOURCES[$this->cdr_source]['csv_directory'],
$this->db_subscribers
);
}
}
$this->initOK=1;
}
function initDefaults()
{
if (is_readable('/etc/default/cdrtool')) {
$defaultContentLines = explode("\n", file_get_contents('/etc/default/cdrtool'));
foreach ($defaultContentLines as $_line) {
list($defaults_key, $defaults_value) = explode("=", $_line);
if (strlen($defaults_value)) $this->defaults[trim($defaults_key)]=trim($defaults_value);
}
}
}
function LoadDomains()
{
}
function LoadTrustedPeers()
{
}
function LoadAccounts()
{
}
function LoadDestinations()
{
$_destinations = array();
$_destinations_sip = array();
$this->destinations_count = 0;
$this->destinations_sip_count = 0;
$query = sprintf("select `value` from memcache where `key` = 'destinations'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$b = time();
$this->cdrtool->next_record();
$_destinations = json_decode($this->cdrtool->f('value'),true);
foreach (array_keys($_destinations) as $_key1) {
foreach(array_keys($_destinations[$_key1]) as $_key2) {
$this->destinations_count = $this->destinations_count + count($_destinations[$_key1][$_key2]);
}
}
if (!$this->destinations_count) {
$log = "Error: cached destinations key contains no data";
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations_sip'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$this->cdrtool->next_record();
$_destinations_sip = json_decode($this->cdrtool->f('value'), true);
foreach (array_keys($_destinations_sip) as $_key1) {
foreach (array_keys($_destinations_sip[$_key1]) as $_key2) {
$this->destinations_sip_count = $this->destinations_count + count($_destinations_sip[$_key1][$_key2]);
}
}
}
/*
$e=time();
$log=sprintf("Read %d PSTN destinations from cache in %d seconds",$this->destinations_count,$e-$b);
syslog(LOG_NOTICE,$log);
if ($this->destinations_sip_count) {
$e=time();
$log=sprintf("Read %d SIP destinations from cache in %d seconds",$this->destinations_sip_count,$e-$b);
syslog(LOG_NOTICE,$log);
}
*/
$this->destinations = $_destinations;
$this->destinations_sip = $_destinations_sip;
unset($_destinations);
unset($_destinations_sip);
} else {
$this->CacheDestinations();
$this->destinations = $this->_destinations;
$this->destinations_sip = $this->_destinations_sip;
unset($this->_destinations);
unset($this->_destinations_sip);
}
if (is_array($this->destinations)) {
foreach (array_keys($this->destinations) as $_reseller) {
foreach ($this->destinations[$_reseller] as $key => $val) {
$this->destinations_length[$_reseller][$key] = max(array_map('strlen', array_keys($val)));
}
}
}
$c = $this->destinations_count + $this->destinations_sip_count;
return $c;
}
function CacheDestinations()
{
$this->_destinations = array();
$this->_destinations_sip = array();
$this->destinations_count = 0;
$this->destinations_sip_count = 0;
$b=time();
$query = "select * from destinations";
if ($this->CDRTool['filter']['aNumber']) {
$faNumber=$this->CDRTool['filter']['aNumber'];
$query .= sprintf(" where subscriber = '%s' or (subscriber = '' and domain = '' and gateway = '') ", addslashes($faNumber));
} else if ($this->CDRTool['filter']['domain']) {
$fdomain=$this->CDRTool['filter']['domain'];
$query .= sprintf(" where domain = '%s' or (subscriber = '' and domain = '' and gateway = '') ", addslashes($fdomain));
} else if ($this->CDRTool['filter']['gateway']) {
$fgateway=$this->CDRTool['filter']['gateway'];
$query .= sprintf(" where gateway = '%s' or (subscriber = '' and domain = '' and gateway = '') ",addslashes($fgateway));
}
$this->cdrtool->query($query);
if (!$this->cdrtool->num_rows()) {
$log = "Error: could not find any entries in the destinations table";
syslog(LOG_NOTICE, $log);
return 0;
}
$destinations_cache = "\n";
$destinations_sip_cache = "\n";
$this->destinations_count = 0;
$this->destinations_default_count = 0;
$this->destinations_gateway_count = 0;
$this->destinations_domain_count = 0;
$this->destinations_subscriber_count = 0;
$j=0;
while ($this->cdrtool->next_record()) {
$j++;
$reseller_id = $this->cdrtool->Record['reseller_id'];
$gateway = trim($this->cdrtool->Record['gateway']);
$domain = trim($this->cdrtool->Record['domain']);
$subscriber = trim($this->cdrtool->Record['subscriber']);
$dest_id = trim($this->cdrtool->Record['dest_id']);
$region = iso8859_1_to_utf8($this->cdrtool->Record['region']);
$name = iso8859_1_to_utf8($this->cdrtool->Record['dest_name']);
$name_print = $this->cdrtool->Record['dest_name']." (".$dest_id.")";
if (strstr($dest_id, '@')) {
// SIP destination
if ($subscriber) {
$this->_destinations_sip[$reseller_id][$subscriber][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($domain) {
$this->_destinations_sip[$reseller_id][$domain][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($gateway) {
$this->_destinations_sip[$reseller_id][$gateway][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($dest_id) {
$this->_destinations_sip[$reseller_id]["default"][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
}
} else {
// PSTN destination
if (!is_numeric($dest_id)) {
$log = sprintf(
"Error: cannot load non-numeric destination '%s' from row id %d",
$dest_id,
$this->cdrtool->Record['id']
);
syslog(LOG_NOTICE, $log);
continue;
}
if ($subscriber) {
$this->destinations_subscriber_count++;
$this->_destinations[$reseller_id][$subscriber][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
} elseif ($domain) {
$this->destinations_domain_count++;
$this->_destinations[$reseller_id][$domain][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
} elseif ($gateway) {
$this->destinations_gateway_count++;
$this->_destinations[$reseller_id][$gateway][$dest_id]=array(
'name' => $name,
'region'=> $region
);
$this->destinations_count++;
} elseif ($dest_id) {
$this->destinations_default_count++;
$this->_destinations[$reseller_id]["default"][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
}
}
}
$destinations_cache = json_encode($this->_destinations);
$destinations_sip_cache = json_encode($this->_destinations_sip);
$log = sprintf("PSTN destinations cache size: %0.2f MB", strlen($destinations_cache) / 1024 / 1024);
syslog(LOG_NOTICE, $log);
if ($destinations_sip_cache) {
$log = sprintf("SIP destinations cache size: %0.2f MB", strlen($destinations_sip_cache) / 1024 / 1024);
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$query = sprintf(
"update memcache set value = '%s' where `key` = 'destinations'",
addslashes($destinations_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf(
"Cached %d total, %d default, %d gateway, %d domain, %d subscriber destinations",
$this->destinations_count,
$this->destinations_default_count,
$this->destinations_gateway_count,
$this->destinations_domain_count,
$this->destinations_subscriber_count
);
syslog(LOG_NOTICE, $log);
} else {
$query = sprintf(
"insert into memcache (`key`,`value`) values ('destinations','%s')",
addslashes($destinations_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf(
"Cached %d total, %d default, %d gateway, %d domain, %d subscriber destinations",
$this->destinations_count,
$this->destinations_default_count,
$this->destinations_gateway_count,
$this->destinations_domain_count,
$this->destinations_subscriber_count
);
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations_sip'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$query = sprintf(
"update memcache set value = '%s' where `key` = 'destinations_sip'",
addslashes($destinations_sip_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf("Cached %d SIP destinations", $this->destinations_sip_count);
syslog(LOG_NOTICE, $log);
} else {
$query = sprintf(
"insert into memcache (`key`,`value`) values ('destinations_sip','%s')",
addslashes($destinations_sip_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf("Updated cache for %d SIP destinations", $this->destinations_sip_count);
syslog(LOG_NOTICE, $log);
}
return true;
}
function LoadENUMtlds()
{
$_ENUMtlds = array();
$query = "select * from billing_enum_tlds";
$this->cdrtool->query($query);
while ($this->cdrtool->next_record()) {
$_ENUMtlds[trim($this->cdrtool->Record['enum_tld'])] = array(
'discount' => trim($this->cdrtool->Record['discount']),
'e164_regexp' => trim($this->cdrtool->Record['e164_regexp'])
);
}
$this->ENUMtlds = $_ENUMtlds;
$c = count($this->ENUMtlds);
return count($this->ENUMtlds);
}
function LoadDisconnectCodes()
{
}
function initForm()
{
}
function searchForm()
{
}
function showTableHeader()
{
}
function showTableHeaderStatistics()
{
}
function showResultsMenu($hide_rows = "", $begin_datetime = '', $end_datetime = '')
{
global $loginname;
if (!$this->export) {
print "
<form class='form-inline' action=log.phtml method=post>
<div class='row-fluid'>
<div class='span6'>";
print "
<div class=\"btn-group pull-right\">
<a class=\"btn\" href=\"$this->url_edit\" ><i class=icon-search></i> Refine search</a><a class=\"btn\" href=\"$this->url_run\"><i class=\"icon-refresh\"></i> Refresh</a>";
$log_query = sprintf(
"insert into log
(date,login,ip,url,results,rerun,reedit,datasource,reseller_id)
values
(NOW(),'%s','%s','%s','%s','%s','%s','%s',%d)",
addslashes($loginname),
addslashes($_SERVER["REMOTE_ADDR"]),
addslashes($this->url),
addslashes($this->rows),
addslashes($this->url_run),
addslashes($this->url_edit),
addslashes($this->cdr_source),
addslashes($this->CDRTool['filter']['reseller'])
);
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if ($this->rows) {
print "<a class=\"btn\" href=\"$this->url_export\" target=_new><i class=\"icon-file\"></i> Export results to file</a>
</div></div>";
} else {
print "</div></div>";
}
print "
<div class='span6'>
<div class='input-append'>
<input class='input-medium' rel='popover' data-placement=\"bottom\" data-content=\"Want to share the results with others? Enter a name and press Save \" data-original-title=\"Save Query\" placeholder='Query name' type=text name=log_description value=\"$old_description\"><button class='btn' type=submit value=Save>Save</button>
</div>
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
</div>
</div>
</form>
";
if (!$hide_rows) {
print "
<div class=\"alert alert-success\"><center>";
if ($this->rows == 0) {
print "No records found";
} else {
print "$this->rows records found";
}
if ($begin_datetime && $end_datetime) {
printf(" between %s and %s", $begin_datetime, $end_datetime);
}
print "</center></div>
";
}
}
}
function showResultsMenuSubscriber($hide_rows = "", $begin_datetime = '', $end_datetime = '')
{
global $loginname;
if (!$this->export) {
print "
<form action=log.phtml method=post>
<table border=0 align=center>
<tr>
<td>
<td>
<a href=\"$this->url_edit\">Refine search</a>
| <a href=\"$this->url_run\">Refresh</a>
</td>
";
$log_query = sprintf(
"insert into log
(date,login,ip,url,results,rerun,reedit,datasource,reseller_id)
values
(NOW(),'%s','%s','%s','%s','%s','%s','%s',%d)",
addslashes($loginname),
addslashes($_SERVER["REMOTE_ADDR"]),
addslashes($this->url),
addslashes($this->rows),
addslashes($this->url_run),
addslashes($this->url_edit),
addslashes($this->cdr_source),
0
);
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if (!$this->CDRTool['filter']['aNumber']) {
if ($this->rows) {
print " | <a href=\"$this->url_export\" target=_new>Export results to file</a>";
}
print "
</td>
<td valign=middle>
| Save a description for this query:
</td>
<td valign=middle>
<input type=text name=log_description value=\"$old_description\">
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
<input type=submit value=Save>
</td>
</form>
";
}
print "
</tr>
</table>
";
if (!$hide_rows) {
print "<div class=\"alert alert-success\"><center>";
if ($this->rows == 0) {
print "No records found";
} else {
print "$this->rows records found";
}
if ($begin_datetime && $end_datetime) {
printf(" between %s and %s",$begin_datetime,$end_datetime);
}
print "</center>
</div>
";
}
}
}
function showDateTimeElements($f)
{
print "
<tr>
<td valign=middle align=left>
<b>Start Time</b>
</td>
<td><div class='input-append date'>
";
$f->show_element("begin_date","");
print "<span class=\"add-on\">
<i class=\"icon-calendar\"></i>
</span></div> ";
print "Time: ";
print "<div class=\"input-append bootstrap-timepicker\">";
$f->show_element("begin_time","");
print "<span class=\"add-on\"><i class=\"icon-time\"></i></span>
</div>
</td>
</tr>
<tr>
<td valign=middle align=left>
<b>Stop Time</b>
</td>
<td><div class='input-append date'>
";
$f->show_element("end_date","");
print "<span class=\"add-on\">
<i class=\"icon-calendar\"></i>
</span></div> ";
print "Time: ";
print "<div class=\"input-append bootstrap-timepicker\">";
$f->show_element("end_time","");
print "<span class=\"add-on\"><i class=\"icon-time\"></i></span>
</div>
</td>
</tr>
";
}
function showDataSources($f)
{
global $perm;
print "
<tr>
<td class=cdr valign=middle align=left>
<b>Data Source</b>
</td>
<td valign=middle>";
$f->show_element("cdr_source","");
if (count($this->tables) > 0) {
print " Table: ";
$this->f->show_element("cdr_table","");
}
print "
</td>
</tr>
<tr>
";
}
function showPagination($next, $maxrows)
{
$PHP_SELF = $_SERVER["PHP_SELF"];
if (!$this->export) {
print "
<ul class=\"pager\">
";
if ($next != 0) {
$show_next = $this->maxrowsperpage - $next;
if ($show_next < 0) {
$mod_show_next = $show_next - 2 * $show_next;
}
$url_prev = $PHP_SELF.$this->url."&action=search&next=$mod_show_next";
print "<li><a href=\"$url_prev\"> &larr; Previous</a></li>";
}
print "
</td>
<td>
";
if ($this->rows > $this->maxrowsperpage && $this->rows != $maxrows) {
$show_next = $this->maxrowsperpage + $this->next;
$url_next = $PHP_SELF.$this->url."&action=search&next=$show_next";
print "<li><a href=\"$url_next\">Next &rarr;</a></li>";
}
print "
</ul>
";
}
}
function show()
{
}
function dump()
{
}
function unNormalize($where = "", $table)
{
if ($this->skipNormalize) {
return 0;
}
if (!$this->normalizedField) {
return 0;
}
// do not allow renormalization for readonly accounts
global $perm;
if (is_object($perm) && $perm->have_perm('readonly')) return false;
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
$query=sprintf(
"update %s set %s = '0' where %s ",
addslashes($table),
addslashes($this->normalizedField),
$where
);
$c=0;
if ($this->CDRdb->query($query)) {
$c = $this->CDRdb->affected_rows();
$this->reNormalize = true;
}
return $c;
}
function buildWhereForUnnormalizedSessions()
{
$this->whereUnnormalized = sprintf(" %s = '0'",$this->normalizedField);
if ($this->stopTimeField) $this->whereUnnormalized .= " and $this->stopTimeField not like '0000-00-00 00:00:00%' ";
if ($this->CDRFields['MediaTimeout']) {
/*
If we use MediaProxy information then eliminate all possible raise conditions
1. Session started and is in progress:
AcctStopTime = '0000-00-00 00:00:00'
AcctSessionTime = 0
MediaInfo is NULL
ConnectInfo_stop is NULL
2. Session closed with a negative response code ([4-6]XX):
AcctSessionTime = 0
AcctStopTime != '0000-00-00 00:00:00'
MediaInfo is NULL
ConnectInfo_stop is NULL
3. Session received a BYE:
ConnectInfo_stop is not NULL
AcctStopTime != '0000-00-00 00:00:00'
4. Media has timed-out:
MediaInfo = 'timeout'
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
5. MediaProxy update before BYE is received:
MediaInfo = ''
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
6. Mofified 5. for the case where the session received a broken BYE
that did not generate a STOP while MediaProxy generated an UPDATE
*/
$this->whereUnnormalized .= " and (ConnectInfo_stop is not NULL or MediaInfo is NULL or MediaInfo != '' or (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(AcctStopTime) > 20)) ";
}
}
function getUnNormalized($where = "", $table)
{
if ($this->skipNormalize) {
return 0;
}
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
$ReNormalize = $_REQUEST["ReNormalize"];
if ($ReNormalize) $this->unNormalize($where, $table);
if (!$this->normalizedField) {
return 0;
}
$this->buildWhereForUnnormalizedSessions();
$query=sprintf(
"select count(*) as c from %s where %s and %s",
addslashes($table),
$where,
$this->whereUnnormalized
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$c = $this->CDRdb->f('c');
}
return $c;
}
function NormalizeCDRS($where = "", $table = "")
{
$this->missing_destinations=array();
$b=time();
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
if ($this->skipNormalize) {
return 1;
}
if (!$this->normalizedField) {
return 1;
}
$lockName = sprintf("%s:%s", $this->cdr_source, $table);
if (!$this->getNormalizeLock($lockName)) {
//printf("Cannot get obtain lock %s",$lockName);
return true;
}
$this->buildWhereForUnnormalizedSessions();
$this->status['cdr_to_normalize'] = 0;
$this->status['normalized'] = 0;
$this->status['normalize_failures'] = 0;
$query = sprintf(
"select count(*) as c from %s where %s and %s",
addslashes($table),
$where,
$this->whereUnnormalized
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$c=$this->CDRdb->f('c');
}
$this->status['cdr_to_normalize']=$c;
//$this->status['cdr_to_normalize']=$this->CDRdb->num_rows();
//print "<p>$query";
if ($this->status['cdr_to_normalize'] > 0) {
if ($this->ratingEnabled) {
// Load rating tables
$this->RatingTables = new RatingTables();
$this->RatingTables->LoadRatingTables();
}
} else {
return 0;
}
$this->usageKeysForDeletionFromCache = array();
// For loop to process 1k records each time
for ($i = 0; $i <= $this->status['cdr_to_normalize']; $i=$i+1000) {
$query = sprintf(
"select *, UNIX_TIMESTAMP($this->startTimeField) as timestamp
from %s where %s and %s limit 0,1000",
addslashes($table),
$where,
$this->whereUnnormalized
);
if (!$this->CDRdb->query($query)) {
$log = sprintf(
"Database error: %s (%s)\n",
$this->CDRdb->Error,
$this->CDRdb->Errno
);
syslog(LOG_NOTICE, $log);
print $log;
return false;
}
while ($this->CDRdb->next_record()) {
//$Structure=$this->_readCDRNormalizationFieldsFromDB();
$Structure=$this->_readCDRFieldsFromDB('');
if ($this->csv_writter) {
if (!$this->csv_file_cannot_be_opened) {
if (!$this->csv_writter->ready) {
if (!$this->csv_writter->open_file($Structure[$this->CDRNormalizationFields['id']])) {
$this->csv_file_cannot_be_opened = true;
} else {
$this->csv_file_ready = true;
}
}
}
}
$found++;
$CDR = new $this->CDR_class($this, $Structure);
if ($CDR->normalize("Save", $table)) {
$this->status['normalized']++;
if ($this->csv_file_ready) {
if (!$this->csv_writter->write_cdr($CDR)) {
// stop writing future records if we have a failure
$this->csv_file_cannot_be_opened = true;
}
}
if ($CDR->broken_rate) {
$this->brokenRates[$CDR->DestinationId]++;
}
} else {
$this->status['normalize_failures']++;
}
if ($this->reNormalize && !$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]) {
$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]++;
}
if ($this->status['cdr_to_normalize'] > 1000) {
if ($found > $progress*$this->status['cdr_to_normalize']/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
flush();
}
}
}
}
}
if ($this->ratingEnabled && is_array($this->brokenRates) && count($this->brokenRates) > 0) {
if ($this->rating_settings['reportMissingRates']) {
if (count($this->brokenRates)) {
foreach (array_keys($this->brokenRates) as $dest) {
$missingRatesBodytext=$missingRatesBodytext."\nDestination id $dest (".$this->brokenRates[$dest]." calls)";
}
$to = $this->CDRTool['provider']['toEmail'];
$from = $this->CDRTool['provider']['fromEmail'];
$log = sprintf(
"Mailing missing rates for %d destination(s) to %s",
count($this->brokenRates),
$to
);
syslog(LOG_NOTICE, $log);
mail($to, "Missing CDRTool rates",$missingRatesBodytext, "From: $from");
}
}
}
if (count($this->missing_destinations)) {
$to = $this->CDRTool['provider']['toEmail'];
$from = $this->CDRTool['provider']['fromEmail'];
$body = '';
foreach ($this->missing_destinations as $_dest) {
if (!$seen[$_dest]) {
$body .= sprintf("No destination for number %s\n", $_dest);
}
$seen[$_dest]++;
}
mail($to, "Missing CDRTool destinations", $body, "From: $from");
}
if ($this->status['cdr_to_normalize'] > 0) {
$d = time() - $b;
$log = sprintf("Normalization done in %d s, memory usage: %0.2f MB", $d, memory_get_usage() / 1024 / 1024);
syslog(LOG_NOTICE, $log);
}
if ($this->csv_file_ready) {
$this->csv_writter->close_file();
$this->csv_writter->ready = false;
}
if (count($this->usageKeysForDeletionFromCache)) {
$this->resetQuota(array_keys($this->usageKeysForDeletionFromCache));
}
return 1;
}
function NormalizeNumber($Number, $type = "destination", $subscriber = "", $domain = "", $gateway = "", $CountryCode = "", $ENUMtld = "", $reseller_id = 0)
{
$this->CSCODE="";
$Number = strtolower(quoted_printable_decode($Number));
if ($pos = strpos($Number, "@")) {
// this is a SIP URI
$NumberStack['username'] = substr($Number, 0, $pos);
if (strlen($NumberStack['username']) < 1) {
$NumberStack['username'] = "unknown";
}
$NumberStack['domain'] = substr($Number,$pos+1);
$NumberStack['delimiter'] = "@";
$pos = strpos($NumberStack['username'], ":");
if ($pos) {
$NumberStack['protocol'] = substr($NumberStack['username'], 0, $pos+1);
$NumberStack['username'] = substr($NumberStack['username'], $pos+1);
}
if (preg_match("/^(.*)[=:;]/U", $NumberStack['domain'], $p)){
$NumberStack['domain'] = $p[1];
}
} else if (preg_match("/^([a-z0-9]+:)(.*)$/i", $Number, $m)) {
#$oct=preg_split("/\./",$m[2]);
$oct = explode(",", $m[2]);
if(sizeof($oct) == 4) {
// This is a SIP address without username
$NumberStack['username'] = "";
$NumberStack['domain'] = $m[2];
} else {
// This is a SIP address without domain
$NumberStack['username'] = $m[2];
$NumberStack['domain'] = "";
}
$NumberStack['protocol'] = $m[1];
$NumberStack['delimiter'] = "";
} else {
// This is a simple address like a phone number
$NumberStack['protocol'] = "";
$NumberStack['username'] = $Number;
$NumberStack['delimiter'] = "";
$NumberStack['domain'] = "";
}
if (preg_match("/^(.*)[=:;]/U", $NumberStack['domain'], $p)){
$NumberStack['domain'] = $p[1];
}
// Translate the domain
if (is_array($this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'])
&& isset($this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'][$NumberStack['domain']])
) {
$NumberStack['domain'] = $this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'][$NumberStack['domain']];
}
if ($type=="destination" && is_numeric($NumberStack['username'])) {
// strip custom prefix from destination
$usernameLength = strlen($NumberStack['username']);
if (is_array($this->CS_CODES)) {
foreach ($this->CS_CODES as $strip_prefix) {
$prefixLength = strlen($strip_prefix);
$restLength = $usernameLength-$prefixLength;
if ($restLength > 0 and preg_match("/^$strip_prefix(.*)$/", $NumberStack['username'], $m)) {
$NumberStack['username'] = $m[1];
$this->CSCODE = $strip_prefix;
break;
}
}
}
if (!$CountryCode) $CountryCode = $this->CDRTool['normalize']['defaultCountryCode'];
$e164class = $this->E164_class;
$E164 = new $e164class(
$this->intAccessCode,
$this->natAccessCode,
$CountryCode,
$this->ENUMtlds[$ENUMtld]['e164_regexp']
);
$NumberStack['E164'] = $E164->E164Format($NumberStack['username']);
}
if ($type=="destination" && $NumberStack['E164']) {
// lookup destination id for the E164 number
$dst_struct = $this->lookupDestination(
$NumberStack['E164'],
$subscriber,
$domain,
$gateway,$reseller_id
);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = "+".$NumberStack['E164'];
if (!$ENUMtld) {
$NumberStack['Normalized'] = $this->intAccessCode.
$NumberStack['E164'].
$NumberStack['delimiter'].
$NumberStack['domain'];
} else {
$NumberStack['Normalized'] =
$NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
} else {
$dst_struct = $this->lookupDestination(
$Number,
$subscriber,
$domain,
$gateway,
$reseller_id
);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
$NumberStack['Normalized'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
return $NumberStack;
}
function lookupDestination($destination, $subscriber = "", $domain = "", $gateway = "", $reseller_id = 0)
{
if (!$destination) return;
if (is_numeric($destination)) {
return $this->lookupPSTNDestination($destination, $subscriber, $domain, $gateway, $reseller_id);
} else {
return $this->lookupSipDestination($destination, $subscriber, $domain, $gateway, $reseller_id);
}
}
function lookupSipDestination($destination = '', $subscriber = '', $domain = '', $gateway = '', $reseller_id = 0)
{
if ($this->destinations_sip[$reseller_id][$subscriber]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$subscriber];
$fCustomer = "subscriber=$subscriber";
} else if ($this->destinations_sip[$reseller_id][$domain]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$domain];
$fCustomer = "domain=$domain";
} else if ($this->destinations_sip[$reseller_id][$gateway]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$gateway];
$fCustomer = "gateway=$gateway";
} else if ($this->destinations_sip[$reseller_id]['default']) {
$destinations_sip = $this->destinations_sip[$reseller_id]['default'];
$fCustomer = "default";
} else if ($this->destinations_sip[0][$subscriber]) {
$destinations_sip = $this->destinations_sip[0][$subscriber];
$fCustomer = "subscriber=$subscriber";
} else if ($this->destinations_sip[0][$domain]) {
$destinations_sip = $this->destinations_sip[0][$domain];
$fCustomer = "domain=$domain";
} else if ($this->destinations_sip[0][$gateway]) {
$destinations_sip = $this->destinations_sip[0][$gateway];
$fCustomer = "gateway=$gateway";
} else if ($this->destinations_sip[0]['default']) {
$destinations_sip = $this->destinations_sip[0]['default'];
$fCustomer = "default";
}
$ret = false;
if ($destinations_sip[$destination]) {
$ret = array($destination,$destinations_sip[$destination]['name']);
} else {
list($user,$domain) = explode("@", $destination);
if ($domain) {
$domain = sprintf("@%s", $domain);
if ($destinations_sip[$domain]) {
$ret = array($domain, $destinations_sip[$domain]['name']);
}
}
}
return $ret;
}
function lookupPSTNDestination($destination = '', $subscriber = '', $domain = '',$gateway = '', $reseller_id = 0)
{
if ($this->destinations[$reseller_id][$subscriber]) {
$_destinations = $this->destinations[$reseller_id][$subscriber];
$maxLength = $this->destinations_length[$reseller_id][$subscriber];
$fCustomer="subscriber=$subscriber";
} else if ($this->destinations[$reseller_id][$domain]) {
$_destinations = $this->destinations[$reseller_id][$domain];
$maxLength = $this->destinations_length[$reseller_id][$domain];
$fCustomer="domain=$domain";
} else if ($this->destinations[$reseller_id][$gateway]) {
$_destinations = $this->destinations[$reseller_id][$gateway];
$maxLength = $this->destinations_length[$reseller_id][$gateway];
$fCustomer="gateway=$gateway";
} else if ($this->destinations[$reseller_id]['default']) {
$_destinations = $this->destinations[$reseller_id]['default'];
$maxLength = $this->destinations_length[$reseller_id]['default'];
$fCustomer="default";
} else if ($this->destinations[0][$subscriber]) {
$_destinations = $this->destinations[0][$subscriber];
$maxLength = $this->destinations_length[0][$subscriber];
$fCustomer="subscriber=$subscriber";
} else if ($this->destinations[0][$domain]) {
$_destinations = $this->destinations[0][$domain];
$maxLength = $this->destinations_length[0][$domain];
$fCustomer="domain=$domain";
} else if ($this->destinations[0][$gateway]) {
$_destinations = $this->destinations[0][$gateway];
$maxLength = $this->destinations_length[0][$gateway];
$fCustomer="gateway=$gateway";
} else if ($this->destinations[0]['default']) {
$_destinations = $this->destinations[0]['default'];
$maxLength = $this->destinations_length[0]['default'];
$fCustomer="default";
} else {
$log = sprintf(
"Error: cannot find destinations for subscriber='%s', domain ='%s', gateway='%s', reseller='%s'\n",
$subscriber,
$domain,
$gateway,
$reseller_id
);
syslog(LOG_NOTICE, $log);
}
if (count($_destinations) > 0) {
$length = min(strlen($destination), $maxLength);
for ($i = $length; $i > 0; $i--) {
$buf = substr($destination, 0, $i);
if ($_destinations[$buf]) {
return array($buf, $_destinations[$buf]['name']);
}
}
}
$log = sprintf(
"Error: cannot find destination id for %s of customer = '%s', total destinations = %d\n",
$destination,
$fCustomer,
count($_destinations)
);
syslog(LOG_NOTICE, $log);
$this->missing_destinations[] = $destination;
return false;
}
function import($file)
{
}
function RadiusRecordRead($fp)
{
$keepreading=1;
while ($keepreading) {
$contents = fgets($fp, 8192);
if (preg_match("/^$/", $contents)) {
$keepreading=0;
} else {
$record[]=$contents;
}
}
return $record;
}
function RadiusRecordParse($record)
{
unset($radiusParsed);
if (!is_array($record)) {
return 0;
}
foreach ($record as $line) {
$line=trim($line);
foreach (array_keys($this->radiusAttributes) as $attribute) {
if (preg_match("/$attribute = (.*)$/", $line, $m)) {
$value = preg_replace("/\"/", "", trim($m[1]));
$radiusParsed[$attribute] = $value;
}
}
}
return $radiusParsed;
}
function getCDRtables()
{
if (!is_object($this->CDRdb)) return 0;
$_tables=$this->CDRdb->table_names();
$t=count($_tables);
if ($this->table) $this->tables[]=$this->table;
while ($t <> 0) {
$_table=$_tables[$t-1]["table_name"];
if ($_table=='radacct') $this->tables[]='radacct';
if (preg_match("/^(\w+)(\d{6})$/", $_table, $m)) {
if ($list_t > 24) break;
$this->tables[] = $_table;
$list_t++;
}
$t--;
}
$this->tables=array_unique($this->tables);
}
function rotateTable($sourceTable, $month, $action)
{
// create a new table tableYYYYMM and copy data from the main table into it
// if no month is supplied, the default is the previous month
if (!$month) $month=date('Ym', mktime(0, 0, 0, date("m") - 1, "01", date("Y")));
if (!$sourceTable) $sourceTable = $this->table;
if (preg_match("/^(\w+)\d{6}$/", $sourceTable, $m)) {
$destinationTable = $m[1].$month;
} else {
$destinationTable = $sourceTable.$month;
}
print("rotateTable($sourceTable, $month, $destinationTable)\n");
if ($sourceTable == $destinationTable) {
$log = sprintf("Error: cannot copy records to the same table %s.\n", $destinationTable);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$createTableFile = $this->CDRTool['Path'].$this->createTableFile;
if (!$this->createTableFile || !is_readable($createTableFile)) {
$log = sprintf("Error: cannot locate mysql creation file\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$lockFile="/var/lock/CDRTool_".$this->cdr_source."_rotateTable.lock";
$f = fopen($lockFile, "w");
if (flock($f, LOCK_EX + LOCK_NB, $w)) {
if ($w) {
$log = sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
} else {
$log = sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$b=time();
if (!preg_match("/^(\d{4})(\d{2})$/", $month, $m)) {
print "Error: Month $month must be in YYYYMM format\n";
return 0;
} else {
if ($m[2] > 12) {
print "Error: Month must be in YYYYMM format\n";
return 0;
}
$lastMonth = $month;
$startSQL = $m[1]."-".$m[2]."-01";
$stopSQL =date('Y-m-01', mktime(0, 0, 0, $m[2] + 1, "01", $m[1]));
}
$query = sprintf(
"select count(*) as c from %s where %s >='%s' and %s < '%s'\n",
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($startSQL),
addslashes($this->CDRFields['startTime']),
addslashes($stopSQL)
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsSourceTable = $this->CDRdb->f('c');
$log=sprintf("Source table %s has %d records in month %s\n", $sourceTable, $rowsSourceTable, $month);
syslog(LOG_NOTICE, $log);
print $log;
if (!$rowsSourceTable) return 1;
} else {
$log = sprintf("Error: %s (%s)\n", $this->table, $this->CDRdb->Error);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$query = sprintf("select count(*) as c from %s\n", addslashes($destinationTable));
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsDestinationTable = $this->CDRdb->f('c');
$log = sprintf("Destination table %s has %d records\n", $destinationTable, $rowsDestinationTable);
syslog(LOG_NOTICE, $log);
print $log;
if ($rowsDestinationTable != $rowsSourceTable) {
$log = sprintf(
"Error: source table has %d records and destination table has %d records\n",
$rowsSourceTable,
$rowsDestinationTable
);
syslog(LOG_NOTICE, $log);
print $log;
} else {
$log = sprintf("Tables are in sync\n");
syslog(LOG_NOTICE, $log);
print $log;
}
} else {
$log = sprintf("%s (%s)\n", $this->CDRdb->Error, $this->CDRdb->Errno);
syslog(LOG_NOTICE, $log);
print $log;
if ($this->CDRdb->Errno==1146) {
$destinationTableTmp = $destinationTable."_tmp";
$query=sprintf("drop table if exists %s", addslashes($destinationTableTmp));
print($query);
$this->CDRdb->query($query);
if ($query=file_get_contents($createTableFile)) {
$query=preg_replace("/CREATE TABLE.*/", "CREATE TABLE $destinationTableTmp (", $query);
if (!$this->CDRdb->query($query)) {
$log = sprintf("Error creating table %s: %s, %s\n", $destinationTableTmp, $this->CDRdb->Error,$query);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
} else {
$log = sprintf("Cannot read file %s\n",$createTableFile);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
// if we reached this point we start to copy records
$query = sprintf(
"insert into %s select * from %s where %s >='%s' and %s < '%s'",
addslashes($destinationTableTmp),
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($startSQL),
addslashes($this->CDRFields['startTime']),
addslashes($stopSQL)
);
return;
if ($this->CDRdb->query($query)) {
$e=time();
$d=$e-$b;
$rps=0;
if ($this->CDRdb->affected_rows() && $d) $rps=$this->CDRdb->affected_rows()/$d;
$log = printf("Copied %d CDRs into table %s in %d s @ %.0f rps\n",$this->CDRdb->affected_rows(),$destinationTableTmp,$d,$rps);
syslog(LOG_NOTICE,$log);
print $log;
$query=sprinf("rename table %s to %s", addslashes($destinationTableTmp),addslashes($destinationTableTmp));
if (!$this->CDRdb->query($query)) {
printf ("Error renaming table %s to %s: %s\n",$destinationTableTmp,$destinationTable,$this->CDRdb->Error);
return 0;
}
} else {
printf ("Error copying records in table %s: %s\n",$destinationTable,$this->CDRdb->Error);
return 0;
}
}
}
}
function purgeTable($sourceTable, $month)
{
// delete records for a given month with minimal locking of database
// this function is useful after archive of CDR data using rotate script
$begin = time();
if ($month) {
if (!preg_match("/^(\d{4})(\d{2})$/", $month, $m)) {
print "Error: Month must be in YYYYMM format\n";
return 0;
} else {
$beginDate=$m[1]."-".$m[2]."-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, $m[2]+1, '01', $m[1]));
}
} else if (is_int($this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'])) {
$beginDate="1970-01-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, Date('m'), Date('d')-$this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'], Date('Y')));
} else {
return 0;
}
if (!$sourceTable) $sourceTable=$this->table;
$query = sprintf(
"select min(%s) as min,max(%s) as max from %s where %s >= '%s' and %s < '%s' ",
addslashes($this->CDRFields['id']),
addslashes($this->CDRFields['id']),
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($beginDate),
addslashes($this->CDRFields['startTime']),
addslashes($endDate)
);
dprint($query);
if (!$this->CDRdb->query($query)) {
printf("Error: %s", $this->CDRdb->Error);
return 0;
}
$this->CDRdb->next_record();
$min=$this->CDRdb->f('min');
$max=$this->CDRdb->f('max');
if (!$min || !$max) {
$log = sprintf("No CDRs found in %s between %s and %s\n", $sourceTable, $beginDate, $endDate);
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
$deleted=0;
$i=$min;
$interval=100;
$rows2delete=$max-$min;
$found = 0;
print "$rows2delete CDRs will be deleted between $min and $max, $interval at a time\n";
while ($i <= $max) {
$found=$found+$interval;
if ($i + $interval < $max) {
$top=$i;
} else {
$top=$max;
}
$query=sprintf("delete low_priority from %s where %s <= '%d' and %s >= '%d'",
addslashes($sourceTable),
addslashes($this->CDRFields['id']),
addslashes($top),
addslashes($this->CDRFields['id']),
addslashes($min)
);
if ($this->CDRdb->query($query)) {
$deleted=$deleted+$this->CDRdb->affected_rows();
} else {
$log=sprintf("Error: %s (%s)",$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
if ($found > $progress*$rows2delete/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
flush();
}
}
print ".";
flush();
$i=$i+$interval;
}
print "\n";
$end = time();
$duration = $end-$begin;
$rps=0;
if ($deleted && $duration) $rps=$deleted/$duration;
$log=sprintf("%s CDRs of month %s deleted from %s in %d s @ %.0f rps\n",$deleted,$month,$sourceTable,$duration,$rps);
syslog(LOG_NOTICE,$log);
print $log;
return 1;
}
function cacheQuotaUsage($accounts=array())
{
if (!$this->quotaEnabled) return true;
$saved_keys=0;
$failed_keys=0;
foreach (array_keys($accounts) as $_key) {
$query=sprintf("select id from quota_usage where datasource = '%s' and account = '%s'",addslashes($this->cdr_source),addslashes($_key));
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
print($log);
return false;
}
if ($this->cdrtool->num_rows()) {
// sync with quota_usage table
$query=sprintf("update quota_usage set
calls = calls + %d,
duration = duration + %d,
cost = cost + '%s',
cost_today = cost_today + '%s',
traffic = traffic + '%s'
where account = '%s'
",
addslashes($accounts[$_key]['usage']['calls']),
addslashes($accounts[$_key]['usage']['duration']),
addslashes($accounts[$_key]['usage']['cost']),
addslashes($accounts[$_key]['usage']['cost_today']),
addslashes($accounts[$_key]['usage']['traffic']),
addslashes($_key)
);
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
$failed_keys++;
} else {
$saved_keys++;
}
} else {
$quota=$this->getQuota($_key);
$blocked=$this->getBlockedByQuotaStatus($_key);
list($_u,$_d)=explode("@",$_key);
$query=sprintf("insert into quota_usage
(datasource,account,domain,quota,calls,duration,cost,cost_today,traffic,blocked,reseller_id)
values
('%s','%s','%s',%d,%d,'%s','%s','%s','%s','%s',%d)
",
addslashes($this->cdr_source),
addslashes($_key),
addslashes($_d),
addslashes($quota),
addslashes($accounts[$_key]['usage']['calls']),
addslashes($accounts[$_key]['usage']['duration']),
addslashes($accounts[$_key]['usage']['cost']),
addslashes($accounts[$_key]['usage']['cost_today']),
addslashes($accounts[$_key]['usage']['traffic']),
intval($blocked),
addslashes($this->localDomains[$_d]['reseller'])
);
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
$failed_keys++;
} else {
$saved_keys++;
}
}
}
$this->status['cached_keys']['saved_keys'] = $this->status['cached_keys']['saved_keys'] + $saved_keys;
$this->status['cached_keys']['failed_keys'] = $this->status['cached_keys']['failed_keys'] + $failed_keys;
return 1;
}
function getNormalizeLock($lockname='') {
if (!$locker = new DB_Locker()) {
$log=sprintf("Error: cannot init locker database. ");
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$lockname) {
$log=sprintf("Error: no lockname provided. ");
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
unset($this->lock_connection_id);
register_shutdown_function("unLockNormalization",$locker,$lockname);
$query=sprintf("SELECT GET_LOCK('%s',0)",addslashes($lockname));
if ($locker->query($query)) {
$locker->next_record();
$return = $locker->Record["GET_LOCK('$lockname',0)"];
$query=sprintf("SELECT IS_USED_LOCK('%s')",addslashes($lockname));
if ($locker->query($query)) {
$locker->next_record();
$this->lock_connection_id=$locker->Record["IS_USED_LOCK('$lockname')"];
}
if ($return == 0) {
$log=sprintf("Lock %s already aquired by another process with id %s ",$lockname,$this->lock_connection_id);
syslog(LOG_NOTICE, $log);
print "$log\n";
return 0;
} else {
$log=sprintf("Normalize lock id %s aquired for %s ",$this->lock_connection_id,$lockname);
syslog(LOG_NOTICE, $log);
//print "$log\n";
return 1;
}
} else {
$log = sprintf("Database error: failed to request mysql lock %s (%s)\n", $locker->Error, $locker->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
}
function getQuota($account)
{
}
function getBlockedByQuotaStatus($account)
{
}
function resetQuota($accounts = array())
{
if (!$this->quotaEnabled) return true;
$_reset_array = array_unique($accounts);
foreach ($_reset_array as $_el) {
if (strlen($_el)) $_accounts[]=$_el;
}
$_reset_array = $_accounts;
$log=sprintf("Next quota check will rebuild the counters for %s accounts",count($_reset_array));
syslog(LOG_NOTICE,$log );
$query=sprintf("delete from memcache where `key` in ('%s','%s')",addslashes($this->quota_init_flag),addslashes($this->quota_reset_flag));
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->cdrtool->Error,$this->cdrtool->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query=sprintf("insert into memcache (`key`,`value`) values ('%s','%s')",addslashes($this->quota_reset_flag),addslashes(json_encode($_reset_array)));
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->cdrtool->Error,$this->cdrtool->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query="delete from quota_usage where account in (";
$t=0;
foreach ($_reset_array as $_el) {
if ($t) $query.=",";
$query.= sprintf("'%s'",addslashes($_el));
$t++;
}
$query.=")";
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
} else {
return 1;
}
}
}
class CDRS_unknown extends CDRS {
function searchForm() {
return;
}
}
class E164 {
// Class that helps normalization of a telephone number in E164 format
// Based on this normalization, CDRTool rating engine decides whether
// to consider the session a PSTN destination and rate it according
// to the PSTN rating plan
function E164($intAccessCode='00', $natAccessCode='0',$CountryCode='',$ENUMtldRegexp="") {
$this->regexp_international = "/^".$intAccessCode."([0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
function E164Format($Number) {
//dprint "E164Format($Number,ENUMtldRegexp=$this->ENUMtldRegexp)";
// This function returns the full E164 format for a PSTN number without leading zero or +
// E164 = Country Code + Network Code + Subscriber Number
// Example: 31208015100 is an E164 number from Holland (country code 31)
// If nothing is returned by this function the session is considered an Internet destination
if (preg_match($this->regexp_international,$Number,$m)) {
return $m[1];
} else if (preg_match($this->regexp_national,$Number,$m)) {
// Add default country code
return $this->CountryCode.$m[1];
} else if (strlen($this->ENUMtldRegexp)) {
$_regexp="/^".$this->ENUMtldRegexp."\$/";
if (preg_match($_regexp,$Number,$m)) {
return $m[1];
}
}
return false;
}
}
class E164_Europe extends E164 {
function E164_Europe ($intAccessCode='00', $natAccessCode='0',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([1-9][0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class E164_US extends E164 {
function E164_US($intAccessCode='011', $natAccessCode='[1-9][0-9]{2}',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class CDR {
// we need two db descriptors to update a CDR
// within same result set
var $idField = "RadAcctId";
var $callIdField = "AcctSessionId";
var $usernameField = "UserName";
var $domainField = "Realm";
var $gatewayField = "NASIPAddress";
var $gatewayPortField = "CiscoNASPort";
var $timestampField = "timestamp";
var $portIdField = "NASPortId";
var $portTypeField = "NASPortType";
var $startTimeField = "AcctStartTime";
var $stopTimeField = "AcctStopTime";
var $durationField = "AcctSessionTime";
var $inputTrafficField = "AcctInputOctets";
var $outputTrafficField = "AcctOutputOctets";
var $serviceTypeField = "ServiceType";
var $cNumberField = "CalledStationId";
var $aNumberField = "CallingStationId";
var $disconnectField = "H323DisconnectCause";
var $traceIn = "";
var $traceOut = "";
var $defaultApplicationType = "audio";
var $supportedApplicationTypes = array(
'audio',
'message',
'video',
'chat',
'file-transfer'
);
function CDR() {
}
function NormalizeDisconnect() {
$causePrint=$this->CDRS->disconnectCodesDescription[$this->disconnect]." (".$this->disconnect.")";
return $causePrint;
}
function traceOut () {
}
function traceIn () {
}
function show() {
}
function normalize($save="",$table="") {
if (!$table) $table = $this->CDRS->table;
if ($this->CDRS->CSCODE && $CarrierInfo = $this->CDRS->CDRTool['normalize']['CS_CODES'][$this->CDRS->CSCODE]) {
// We found a carrier so we set the BillingId
$this->BillingId = $CarrierInfo[BillingPartyId];
}
if ($save) {
if (!$this->id) {
return 0;
}
$query ="";
$query1 ="";
$query2 ="";
if ($this->CDRS->normalizedField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s='1' ",addslashes($this->CDRS->normalizedField));
}
if ($this->CDRS->BillingPartyIdField && $this->BillingPartyId) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->BillingPartyIdField),addslashes($this->BillingPartyId));
}
if (strlen($this->durationNormalized) && $this->durationNormalized != $this->duration) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s ='%s' ",addslashes($this->CDRS->durationField),addslashes($this->durationNormalized));
$this->duration=$this->durationNormalized;
}
if ($this->CDRS->DestinationIdField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->DestinationIdField),addslashes($this->DestinationId));
}
if ($this->CDRS->ResellerIdField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->ResellerIdField),addslashes($this->ResellerId));
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->usernameField),addslashes($this->usernameNormalized));
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->aNumberField),addslashes($this->aNumberNormalized));
$this->aNumber=$this->aNumberNormalized;
}
if ($this->CDRS->applicationField && $this->applicationNormalized) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->applicationField), addslashes($this->applicationNormalized));
$this->application=$this->applicationNormalized;
}
if ($this->CDRS->flowField && $this->flow) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->flowField),addslashes($this->flow));
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->domainField),addslashes($this->domainNormalized));
$this->domainNumber=$this->domainNormalized;
$this->domain=$this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->cNumberField),addslashes($this->cNumberNormalized));
$this->cNumber=$this->cNumberNormalized;
}
if ($this->CDRS->BillingIdField && $this->BillingId) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->BillingIdField),addslashes($this->BillingId));
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->RemoteAddressField),addslashes($this->RemoteAddressNormalized));
}
if ($this->CDRS->CanonicalURIField && $this->CanonicalURINormalized && $this->CanonicalURINormalized!= $this->CanonicalURI) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->CanonicalURIField),addslashes($this->CanonicalURINormalized));
}
if ($this->stopTimeNormalized) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->stopTimeField),addslashes($this->stopTimeNormalized));
}
if ($this->CDRS->ratingEnabled && ($this->duration || $this->application == 'message')) {
if ($this->DestinationId) {
$Rate = new Rate($this->CDRS->rating_settings, $this->CDRS->cdrtool);
if ($this->application == 'message') {
$RateDictionary = array(
'callId' => $this->callId,
'timestamp' => $this->timestamp,
'duration' => $this->duration,
'DestinationId' => $this->DestinationId,
'BillingPartyId' => $this->BillingPartyId,
'ResellerId' => $this->ResellerId,
'domain' => $this->domain,
'gateway' => $this->gateway,
'RatingTables' => $this->CDRS->RatingTables,
'aNumber' => $this->aNumber,
'cNumber' => $this->cNumber
);
$Rate->calculateMessage($RateDictionary);
} else {
$RateDictionary = array(
'callId' => $this->callId,
'timestamp' => $this->timestamp,
'duration' => $this->duration,
'DestinationId' => $this->DestinationId,
'inputTraffic' => $this->inputTraffic,
'outputTraffic' => $this->outputTraffic,
'BillingPartyId' => $this->BillingPartyId,
'ResellerId' => $this->ResellerId,
'domain' => $this->domain,
'gateway' => $this->gateway,
'RatingTables' => $this->CDRS->RatingTables,
'aNumber' => $this->aNumber,
'cNumber' => $this->cNumber,
'ENUMtld' => $this->ENUMtld,
'application' => $this->application
);
$Rate->calculateAudio($RateDictionary);
}
$this->pricePrint = $Rate->pricePrint;
$this->price = $Rate->price;
$this->rateInfo = $Rate->rateInfo;
$this->rateDuration = $Rate->duration;
if ($Rate->broken_rate) {
$this->broken_rate = true;
}
} else {
$this->rateInfo = '';
$this->pricePrint = '';
$this->price = '';
}
// strict mysql query fails when price is being set to ''
if ($this->pricePrint === null || $this->pricePrint === '') {
$this->pricePrint = '0.00';
}
if ($this->CDRS->priceField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query .= sprintf(
" %s = '%s' ",
addslashes($this->CDRS->priceField),
addslashes($this->pricePrint)
);
if ($this->CDRS->rateField ) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->rateField),addslashes($this->rateInfo));
}
}
}
$query1 = sprintf(
"update %s set %s where %s = '%s'",
addslashes($table),
$query,
addslashes($this->idField),
addslashes($this->id));
dprint_sql($query1);
if ($updatedFields) {
if ($this->CDRS->CDRdb1->query($query1)) {
if ($this->CDRS->CDRdb1->affected_rows()) {
if ( $this->isBillingPartyLocal() && $table == "radacct".date('Ym')) {
// cache usage only if current month
$_traffic = ($this->inputTraffic + $this->outputTraffic) / 2;
$_usage = array(
'calls' => 1,
'duration' => $this->duration,
'cost' => $this->price,
'cost_today' => $this->price,
'traffic' => $_traffic
);
$this->cacheQuotaUsage($_usage);
}
} else {
if (preg_match("/^(\w+)(\d{4})(\d{2})$/", $table, $m)) {
$previousTable=$m[1].date('Ym', mktime(0, 0, 0, $m[3]-1, "01", $m[2]));
$query2 = sprintf("update %s set %s where %s = '%s'",addslashes($previousTable),$query,addslashes($this->idField),addslashes($this->id));
if ($this->CDRS->CDRdb1->query($query2)) {
if ($this->CDRS->CDRdb1->affected_rows()) {
if ($this->isBillingPartyLocal() && $previousTable == "radacct".date('Ym')) {
// cache usage only if current month
$_traffic = ($this->inputTraffic + $this->outputTraffic) / 2;
$_usage = array(
'calls' => 1,
'duration' => $this->duration,
'cost' => $this->price,
'cost_today' => $this->price,
'traffic' => $_traffic
);
$this->cacheQuotaUsage($_usage);
}
}
} else {
$log = sprintf(
"Database error: %s (%s)",
$this->CDRS->CDRdb1->Error,
$this->CDRS->CDRdb1->Errno
);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
}
return 1;
} else {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query1,
$this->CDRS->CDRdb1->Error,
$this->CDRS->CDRdb1->Errno
);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
} else {
if ($this->CDRS->BillingPartyIdField && $CarrierInfo['BillingPartyId']) {
$this->domain = $CarrierInfo['BillingDomain'];
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
$this->username = $this->usernameNormalized;
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
$this->aNumber = $this->aNumberNormalized;
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
$this->domainNumber = $this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
$this->cNumber = $this->cNumberNormalized;
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
$this->RemoteAddress = $this->RemoteAddressNormalized;
}
}
return 1;
}
function cacheQuotaUsage($usage)
{
if (!is_array($usage)) return ;
$accounts[$this->BillingPartyId]['usage'] = $usage;
$this->CDRS->cacheQuotaUsage($accounts);
}
function isCallerLocal()
{
return false;
}
function isCalleeLocal()
{
return false;
}
function isBillingPartyLocal()
{
return false;
}
function obfuscateCallerId()
{
global $obfuscateCallerId;
if ($obfuscateCallerId) {
}
}
function lookupRateFromNetwork($RateDictionary, $fp)
{
$this->rateInfo='';
$this->pricePrint='';
$this->price='';
$countEndofLines=0;
$cmd="ShowPrice";
foreach (array_keys($RateDictionary) as $key) {
$cmd .=" ".$key."=".$RateDictionary[$key]." ";
}
$this->price = 0;
$this->pricePrint = "";
$this->rateInfo = "";
if (fputs($fp,"$cmd\n") !== false) {
$i=0;
while ($i < 100) {
$i++;
$line = fgets($fp,1024);
if (!$line) {
syslog(LOG_NOTICE, "Error: lookupRateFromNetwork(): connection to network socket died");
break;
}
if (preg_match("/^\n/",$line) || preg_match("/^END/",$line)) {
break;
}
if ($i == 1) {
$this->price = trim($line);
$this->pricePrint = number_format($this->price, 4);
continue;
}
$this->rateInfo.=$line;
}
}
}
function lookupGeoLocation($ip)
{
if ($_loc=geoip_record_by_name($ip)) {
return $_loc['country_name'].'/'.$_loc['city'];
} else if ($_loc=geoip_country_name_by_name($ip)) {
return $_loc;
} else {
return '';
}
}
}
function getLocalTime($timezone,$timestamp) {
global $CDRTool;
if (!$timezone || $timezone == $CDRTool['provider']['timezone']) {
return date("Y-m-d H:i:s", $timestamp);
}
putenv("TZ=$timezone");
$startTimeLocal=date("Y-m-d H:i:s", $timestamp);
$timezone=$CDRTool['provider']['timezone'];
putenv("TZ=$timezone");
return $startTimeLocal;
}
function validDay($month,$day,$year) {
if (!$month || !$year) {
return $day;
}
while (1) {
if (!checkdate($month,$day,$year) && $day) {
$day--;
next;
} else {
break;
}
}
return $day;
}
// include CDRTool modules defined in global.inc
if (is_array($CDRToolModules)) {
foreach ($CDRToolModules as $module) {
$module_filename="cdr_".$module.".php";
include($module_filename);
}
}
function unLockNormalization ($dbid,$lockname) {
$query=sprintf("SELECT RELEASE_LOCK('%s')",addslashes($lockname));
$log=sprintf("Unlock %s",$lockname);
syslog(LOG_NOTICE, $log);
if (!$dbid->query($query)) {
$log="Error in unLockNormalization()";
syslog(LOG_NOTICE, $log);
}
}
class SIPonline {
function SIPonline ($datasource='',$database='db',$table='location') {
global $CDRTool;
$expandAll = $_REQUEST['expandAll'];
$domain = $_REQUEST['domain'];
$this->expandAll = $expandAll;
$this->domain = $domain;
$this->datasource = $datasource;
if (strlen($CDRTool['filter']['domain'])) {
$this->allowedDomains=explode(" ",$CDRTool['filter']['domain']);
$allowed_domains_sql="";
$j=0;
foreach ($this->allowedDomains as $_domain) {
if ($j>0) $allowed_domains_sql.=",";
$allowed_domains_sql.="'".addslashes($_domain)."'";
$j++;
}
}
$this->locationDB = new $database;
$this->locationTable = $table;
$this->Registered=array();
$this->countUA=array();
$where = " where (1=1) " ;
if ($allowed_domains_sql) {
$where.= sprintf("and domain in (%s)",addslashes($allowed_domains_sql)) ;
}
$query=sprintf("select count(*) as c, domain from %s %s group by domain order by domain ASC",
addslashes($this->locationTable),
$where
);
$this->locationDB->query($query);
$this->domains=$this->locationDB->num_rows();
while ($this->locationDB->next_record()) {
$this->Registered[$this->locationDB->f('domain')]=$this->locationDB->f('c');
$this->total=$this->total+$this->locationDB->f('c');
}
$query=sprintf("select count(*) as c, user_agent from %s %s",addslashes($this->locationTable),$where);
if ($this->domain) {
$query.=sprintf(" and domain = '%s' ",addslashes($this->domain));
}
$query.="
group by user_agent
order by c DESC";
$this->locationDB->query($query);
while ($this->locationDB->next_record()) {
$this->countUA[$this->locationDB->f('user_agent')]=$this->locationDB->f('c');
}
}
function showHeader() {
print "<table id='opensips_registrar' class='table table-striped table-condensed'>";
print "<thead><tr>
";
if ($this->domain) {
print "
<th></th>
<th width=120 align=right>User@Domain</th>
<th></th>
<th>SIP UA contact</th>
<th>NAT address</th>
<th>User Agent</th>
<th>Expires</th>
<th>Remain</th>
";
} else {
print "
<th></td>
<th align=right>Users@</th>
<th>Domain</th>
";
}
print "
</tr></thead>
";
}
function showFooter() {
print "
<tr>
<th></th>
<th align=right>$this->total users@</td>
<th align=left>$this->domains domains</td>
</tr>
</table>
";
}
function showAll() {
global $found;
$this->showHeader();
foreach (array_keys($this->Registered) as $ld) {
$onlines=$this->Registered[$ld];
if ($this->expandAll || ($this->domain && $this->domain==$ld)) {
$this->show($ld);
} else {
$found++;
$url = sprintf("%s?datasource=%s&domain=%s",
$_SERVER['PHP_SELF'],
urlencode($this->datasource),
urlencode($ld)
);
print "
<tr>
<td valign=top align=right>$found</td>
<td valign=top align=right>$onlines users@</td>
<td valign=top><a href=$url>$ld</a></td>
";
if ($this->domain) {
print "
<td></td>
<td></td>
<td></td>
<td></td>
";
}
print "
</tr>
";
}
}
$this->showfooter();
/*
print "<p>";
$this->showUAdistribution();
*/
}
function show() {
global $found;
$query="SELECT *, SEC_TO_TIME(UNIX_TIMESTAMP(expires)-UNIX_TIMESTAMP(NOW())) AS remain
FROM location
";
if ($this->domain) $query.=sprintf(" where domain = '%s'", addslashes($this->domain));
$query.= " ORDER BY domain ASC, username ASC ";
$this->locationDB->query($query);
while ($this->locationDB->next_record()) {
$found++;
$username = $this->locationDB->f('username');
$domain = $this->locationDB->f('domain');
$contact = $this->locationDB->f('contact');
$received = $this->locationDB->f('received');
$user_agent = $this->locationDB->f('user_agent');
$expires = $this->locationDB->f('expires');
$remain = $this->locationDB->f('remain');
$contact_print=substr($contact,4);
$c_els=explode(";", $contact);
$r_els=explode(";", $received);
$transport="UDP";
if ($c_els[1] && preg_match("/transport=(tcp|tls)/i",$c_els[1],$m)) {
$transport=strtoupper($m[1]);
}
$sip_account=$username."@".$domain;
print "
<tr>
<td valign=top align=right>$found</td>
<td valign=top>$sip_account</td>
<td valign=top>$transport</td>
<td valign=top align=right>$c_els[0]</td>
<td valign=top align=right>$r_els[0]</td>
<td valign=top>$user_agent</td>
<td valign=top>$expires</td>
<td valign=top align=right>$remain</td>
</tr>
";
$seen[$username]++;
$seen[$domain]++;
}
}
function showUAdistribution () {
print "<table border=0 cellspacing=1 class=border>";
print "<tr bgcolor=lightgrey> ";
print "<td></td>";
print "<th>User agent</th>";
print "<th>Users</th>";
print "</tr> ";
- while (list($k,$v) = each($this->countUA)) {
+ foreach ($this->countUA as $k => $v) {
$users=$users+$v;
$count++;
print "<tr> ";
print "<td>$count</td>";
print "<td>$k</td>";
print "<td>$v</td>";
print "</tr>";
}
print "<tr bgcolor=lightgrey> ";
print "<td></td>";
print "<td><b>$this->domain</b></td>";
print "<td><b>$users</b></td>";
print "</tr> ";
print "</table>";
}
}
class PrepaidHistory {
function PrepaidHistory() {
$this->db = new DB_cdrtool;
}
function purge($days=7) {
$beforeDate=Date("Y-m-d", time()-$days*3600*24);
$query=sprintf("delete from prepaid_history where date < '%s' and action like 'Debit balance%s'",addslashes($beforeDate),'%');
if (!$this->db->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)\n",$query,$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE,$log);
} else {
$log=sprintf ("Purged %d records from prepaid history before %s\n",$this->db->affected_rows(),$beforeDate);
print $log;
syslog(LOG_NOTICE,$log);
}
}
}
class CSVWritter {
var $csv_directory = '/var/spool/cdrtool/normalize';
var $filename_extension = '.csv';
var $fields = array();
var $ready = false;
var $cdr_type = array();
var $lines = 0;
function CSVWritter($cdr_source='',$csv_directory='') {
if ($cdr_source) {
$this->cdr_source = $cdr_source;
} else {
$this->cdr_source = 'unknown';
}
if ($csv_directory) {
if (is_dir($csv_directory)) {
$this->csv_directory = $csv_directory;
} else {
$log=sprintf ("CSV writter error: %s is not a directory\n",$csv_directory);
syslog(LOG_NOTICE,$log);
return false;
}
}
$this->directory=$this->csv_directory."/".date("Ymd");
if (!is_dir($this->directory)) {
if (!mkdir($this->directory)) {
$log=sprintf ("CSV writter error: cannot create directory %s\n",$this->directory);
syslog(LOG_NOTICE,$log);
return false;
}
chmod($this->directory, 0775);
}
$this->directory_ready = true;
}
function open_file ($filename_suffix='') {
if ($this->ready) return true;
if (!$this->directory_ready) return false;
if (!$filename_suffix) {
$log=sprintf ("CSV writter error: no filename suffix provided\n");
syslog(LOG_NOTICE,$log);
return false;
}
$this->filename_prefix = strtolower($this->cdr_source).'-'.date('YmdHi');
$this->full_path=rtrim($this->directory,'/').'/'.$this->filename_prefix.'-'.$filename_suffix.$this->filename_extension;
$this->full_path_tmp=$this->full_path.'.tmp';
if (!$this->fp = fopen($this->full_path_tmp, 'w')) {
$log=sprintf ("CSV writter error: cannot open %s for writing\n",$this->full_path_tmp);
syslog(LOG_NOTICE,$log);
return false;
}
$this->ready = true;
return true;
}
function close_file () {
if (!$this->ready) return false;
fclose($this->fp);
if (!rename($this->full_path_tmp, $this->full_path)) {
$log=sprintf ("CSV writter error: cannot rename %s to %s\n",$this->full_path_tmp,$this->full_path);
syslog(LOG_NOTICE,$log);
} else {
$log=sprintf ("%d normalized CDRs written to %s\n",$this->lines, $this->full_path);
syslog(LOG_NOTICE,$log);
}
}
function write_cdr ($CDR) {
if (!$this->ready) return false;
$line = sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
$CDR->id,
$CDR->callId,
$CDR->flow,
$CDR->application,
$CDR->username,
$CDR->CanonicalURI,
$CDR->startTime,
$CDR->stopTime,
$CDR->duration,
$CDR->DestinationId,
$CDR->BillingPartyId,
$CDR->ResellerId,
$CDR->price
);
if (!fputs($this->fp,$line)) {
$this->ready = false;
return false;
}
$this->lines++;
return true;
}
}
class MaxRate extends CSVWritter {
var $skip_prefixes = array();
var $skip_numbers = array();
var $skip_domains = array();
var $rpid_cache = array();
var $translate_uris = array();
function MaxRate ($cdr_source='', $csv_directory='', $db_subscribers='') {
global $MaxRateSettings; // set in global.inc
/*
$MaxRateSettings= array(
'translate_uris'=> array( '1233@10.0.0.2'=>'+1233',
'[1-9][0-9]{4}.*@10.0.0.2'=>'+1233'),
'skip_domains' => array('example.net','10.0.0.1'),
'skip_numbers' => array('1233'), // skip CDRs that has the username part in this array
'skip_prefixes' => array('0031901') // skip CDRs that begin with any of this prefixes
);
*/
if (is_array($MaxRateSettings['skip_domains'])) {
$this->skip_domains=$MaxRateSettings['skip_domains'];
}
if (is_array($MaxRateSettings['skip_numbers'])) {
$this->skip_numbers=$MaxRateSettings['skip_numbers'];
}
if (is_array($MaxRateSettings['skip_prefixes'])) {
$this->skip_prefixes=$MaxRateSettings['skip_prefixes'];
}
if (is_array($MaxRateSettings['translate_uris'])) {
$this->translate_uris=$MaxRateSettings['translate_uris'];
}
$this->AccountsDB = new $db_subscribers();
$this->CSVWritter($cdr_source, $csv_directory);
}
function write_cdr($CDR) {
if (!$this->ready) return false;
# skip if no audio
if ($CDR->application != 'audio') return true;
# skip if no duration
if (!$CDR->duration && ($CDR->disconnect != 200)) return true;
# normalize destination
if ($CDR->CanonicalURIE164) {
$cdr['destination'] = '+'.$CDR->CanonicalURIE164;
} else {
$cdr['destination'] = $CDR->CanonicalURI;
}
list($canonical_username, $canonical_domain)=explode("@",$cdr['destination']);
# skip domains
if ($canonical_domain && in_array($canonical_domain,$this->skip_domains)) return true;
# skip numbers
if ($canonical_username && in_array($canonical_username,$this->skip_numbers)) return true;
# skip prefixes
if ($canonical_username && count($this->skip_prefixes)) {
foreach ($this->skip_prefixes as $prefix) {
if (preg_match("/^$prefix/",$canonical_username)) return true;
}
}
# get RPID if caller is local
if ($CDR->flow != 'incoming') {
$CallerRPID=$this->getRPIDforAccount($CDR->aNumberPrint);
}
if ($CallerRPID) {
# normalize RPID
$cdr['origin'] = '0031'.ltrim($CallerRPID,'0');
} else {
# normalize caller id numbers from PSTN gateway to 00format
if (preg_match("/^\+?0([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+?00([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^anonymous@(.*)$/",$CDR->aNumberPrint) && $CDR->SipRPID) {
if (preg_match("/^\+?0([1-9][0-9]+)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+?00([1-9][0-9]+)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^([1-9][0-9]+)@(.*)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = $m[1];
} else if (preg_match("/^\+([1-9][0-9]+)@(.*)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^\+?0[0-9]?+@?(.*)?$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else if (preg_match("/^.*[a-zA-Z].*$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else if (preg_match("/^ims.imscore.net.*$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else {
$cdr['origin'] = $CDR->SipRPID;
}
} else {
$cdr['origin'] = "0031123456789";
//$cdr['origin'] = $CDR->aNumberPrint;
}
}
# normalize short origins
if (preg_match("/^\d{1,3}@.*$/",$cdr['origin'])) {
$cdr['origin']='+31000000000';
}
# normalize anonymous origins
if (preg_match("/^anonymous@.*$/",$cdr['origin'])) {
$cdr['origin']='+31000000000';
}
#translate destination URIs to desired format
if ($CDR->CanonicalURINormalized && count($this->translate_uris)) {
foreach ($this->translate_uris as $key => $uri) {
if ( preg_match("/^$key/", $CDR->CanonicalURINormalized)) {
$cdr['destination']=$uri;
break;
}
}
}
preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2})$/",$CDR->startTime,$m);
$cdr['start_date'] = sprintf ("%s/%s/%s %s",$m[3],$m[2],$m[1],$m[4]);
$cdr['diversion'] = '';
preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2})$/",$CDR->stopTime,$m);
$cdr['stop_date'] = sprintf ("%s/%s/%s %s",$m[3],$m[2],$m[1],$m[4]);
$cdr['product'] = $this->product;
# normalize duration based on billed duration
if ($CDR->rateDuration) {
$cdr['duration'] = $CDR->rateDuration;
} else {
$cdr['duration'] = $CDR->duration;
}
$rate_info = explode("\n", $CDR->rateInfo);
for ($i = 0; $i < sizeof($rate_info); ++$i)
{
//dprint_r($rate_info[$i]);
if (strpos($rate_info[$i], "ProfileId:") !== false)
{
$cdr['profile'] = ltrim(str_replace("ProfileId: ", '', $rate_info[$i]));
}
}
//$cdr['extra']="$CDR->callId";
list($cdr['username'],$cdr['domain'])= explode('@',$CDR->username);
$cdr['charge_info'] = sprintf('"%s","%s","%s"',$CDR->price,$cdr['profile'],$CDR->destinationName);
if ($CDR->flow == 'on-net') {
# RFP 4.2.1
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['destination'] = '0031'.ltrim($CalleeRPID,'0');
}
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'outgoing') {
# RFP 4.2.2
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'incoming') {
# RFP 4.2.3
if ($this->inbound_trunks[$CDR->SourceIP]) {
$inbound_trunk = $this->inbound_trunks[$CDR->SourceIP];
} else {
$inbound_trunk = 'unknown';
}
$cdr['username'] = $canonical_username;
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['destination'] = '0031'.ltrim($CalleeRPID,'0');
}
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'diverted-on-net') {
# RFP 4.2.4
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
if ($CalleeRPID) {
$cdr['c_num'] = '0031'.ltrim($CalleeRPID,'0');
}
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."incoming-diverted-on-net";
} else if ($CDR->flow == 'diverted-off-net') {
# RFP 4.2.5
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$cdr['c_num'] = $cdr['destination'];
# Set destination to B-Number
$cdr['destination']=$diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."incoming-diverted-off-net";
} else if ($CDR->flow == 'on-net-diverted-on-net') {
# RFP 4.2.6
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['c_num'] = '0031'.ltrim($CalleeRPID,'0');
}
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'on-net-diverted-off-net') {
# RFP 4.2.7
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$cdr['c_num']= $cdr['destination'];
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."$CDR->flow";
}
$cdr['username'] = preg_replace('/caiw0+|test0+/', "", $cdr['username']);
$cdr['origin'] = str_replace('+','00',$cdr['origin']);
$cdr['destination'] = str_replace('+','00',$cdr['destination']);
$cdr['diversion'] = str_replace('+','00',$cdr['diversion']);
$line = sprintf('"%s","%s","%s","%s","%s","%s","%s","%s","%s",%s'."\n",
$CDR->callId,
$cdr['origin'],
$cdr['username'],
$cdr['destination'],
$cdr['diversion'],
$cdr['start_date'],
$cdr['stop_date'],
$cdr['duration'],
$cdr['extra'],
$cdr['charge_info']
);
if (!fputs($this->fp,$line)) {
$log=sprintf ("CSV writter error: cannot append to file %s\n",$this->full_path_tmp);
syslog(LOG_NOTICE,$log);
$this->close_file();
$this->ready = false;
return false;
}
$this->lines++;
return true;
}
function getRPIDforAccount($account) {
if (!$account) return false;
if ($this->rpid_cache[$account]) {
return $this->rpid_cache[$account];
}
list($username,$domain) = explode('@',$account);
$query=sprintf("select * from sip_accounts where username = '%s' and domain = '%s'",addslashes($username),addslashes($domain));
if (!$this->AccountsDB->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->AccountsDB->Error,$this->AccountsDB->Errno);
syslog(LOG_NOTICE,$log);
return false;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
$this->rpid_cache[$account]=$_profile->rpid;
return $_profile->rpid;
} else {
return false;
}
}
}
?>
diff --git a/library/sip_statistics.php b/library/sip_statistics.php
index 4217050..06f5e7b 100644
--- a/library/sip_statistics.php
+++ b/library/sip_statistics.php
@@ -1,954 +1,954 @@
<?php
/**
* Copyright (c) 2022 AG Projects
* https://ag-projects.com
* Author Adrian Georgescu
*
*/
class NetworkStatistics {
// obtain statistics from SIP Thor network
public $statistics = array();
public $status = array();
public $sip_summary = array();
public $sip_proxies = array();
public $node_statistics = array();
public $domain_statistics = array();
public $allowedRoles = array(
'sip_proxy',
'media_relay',
'provisioning_server',
'xcap_server',
'thor_dnsmanager',
'thor_database',
'voicemail_server',
);
public $allowedSummary = array(
'online_accounts',
'total_accounts'
);
public function __construct($engineId, $allowedDomains = array())
{
if (!strlen($engineId)) {
return false;
}
$this->allowedDomains = $allowedDomains;
$this->soapEngineId = $engineId;
require("/etc/cdrtool/ngnpro_engines.inc");
require_once("ngnpro_soap_library.php");
$this->SOAPlogin = array(
"username" => $soapEngines[$this->soapEngineId]['username'],
"password" => $soapEngines[$this->soapEngineId]['password'],
"admin" => true
);
$this->SOAPurl = $soapEngines[$this->soapEngineId]['url'];
$this->SoapAuth = array('auth', $this->SOAPlogin , 'urn:AGProjects:NGNPro', 0, '');
$this->soapclient = new WebService_NGNPro_NetworkPort($this->SOAPurl);
$this->soapclient->setOpt('curl', CURLOPT_TIMEOUT, 5);
$this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if (is_array($soapEngines[$this->soapEngineId]['hostnames'])) {
$this->hostnames = $soapEngines[$this->soapEngineId]['hostnames'];
} else {
$this->hostnames = array();
}
}
public function getStatistics()
{
$this->soapclient->addHeader($this->SoapAuth);
$result = $this->soapclient->getStatistics();
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
$log = sprintf("Error from %s: %s: %s", $this->SOAPurl, $error_fault->detail->exception->errorcode, $error_fault->detail->exception->errorstring);
syslog(LOG_NOTICE, $log);
return false;
}
$this->statistics = json_decode($result, true);
foreach (array_keys($this->statistics) as $_ip) {
if ($_ip == 'summary') {
foreach (array_keys($this->statistics[$_ip]) as $_role) {
if ($_role == 'sip_proxy') {
foreach (array_keys($this->statistics[$_ip][$_role]) as $_section) {
foreach (array_keys($this->statistics[$_ip][$_role][$_section]) as $_domain) {
if (count($this->allowedDomains) && !in_array($_domain, $this->allowedDomains)) {
continue;
}
if (count($this->allowedDomains) && !in_array($_section, $this->allowedSummary)) {
continue;
}
$this->sip_summary[$_section]=$this->sip_summary[$_section]+$this->statistics[$_ip][$_role][$_section][$_domain];
}
}
}
}
continue;
}
foreach (array_keys($this->statistics[$_ip]) as $_role) {
if ($_role == 'sip_proxy') {
$this->node_statistics[$_ip]['sip_proxy']=true;
foreach (array_keys($this->statistics[$_ip][$_role]) as $_section) {
foreach (array_keys($this->statistics[$_ip][$_role][$_section]) as $_domain) {
if (count($this->allowedDomains) && !in_array($_domain, $this->allowedDomains)) {
continue;
}
$this->domain_statistics[$_domain][$_section] = $this->domain_statistics[$_domain][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain];
$this->domain_statistics['total'][$_section] = $this->domain_statistics['total'][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain];
$this->node_statistics[$_ip][$_section] = $this->node_statistics[$_ip][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain];
}
}
}
}
}
}
public function getStatus()
{
$this->soapclient->addHeader($this->SoapAuth);
$result = $this->soapclient->getStatus();
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
$log=sprintf("Error from %s: %s: %s", $this->SOAPurl, $error_fault->detail->exception->errorcode, $error_fault->detail->exception->errorstring);
syslog(LOG_NOTICE, $log);
return false;
}
$this->status = json_decode($result, true);
foreach (array_keys($this->status) as $_id) {
foreach ($this->status[$_id]['roles'] as $_role) {
if ($_role == 'sip_proxy') {
$this->sip_proxies[$this->status[$_id]['ip']]++;
}
if ($_role == 'thor_dnsmanager') {
$this->dns_managers[$this->status[$_id]['ip']]++;
}
if ($_role == 'thor_manager') {
$this->thor_managers[$this->status[$_id]['ip']]++;
}
if ($_role == 'conference_server') {
$this->conference_servers[$this->status[$_id]['ip']]++;
}
if ($_role == 'voicemail_server') {
$this->voicemail_servers[$this->status[$_id]['ip']]++;
}
$ip=$this->status[$_id]['ip'];
$this->roles[$_role][$ip]=array(
'ip' => $ip,
'version' => $this->status[$_id]['version']
);
foreach (array_keys($this->status[$_id]) as $_attr) {
if ($_attr == 'ip' || $_attr == 'version' || $_attr == 'roles') {
continue;
}
$this->roles[$_role][$ip]['attributes'][$_attr]=$this->status[$_id][$_attr];
}
}
}
}
public function showStatus()
{
$this->getStatus();
print "<div class=row><table class=\"span12 table table-condensed table-striped\">";
print "<thead><tr>";
if (count($this->allowedDomains)) {
print "<th>Role</th><th>Address</th><th>Version</th></tr>";
} else {
print "<th>Role</th><th>Address</th><th>Version</th><th>Attributes</th></tr></thead>";
}
foreach (array_keys($this->roles) as $_role) {
if (count($this->allowedDomains)) {
if (!in_array($_role, $this->allowedRoles)) {
continue;
}
}
foreach ($this->roles[$_role] as $_entity) {
if (!$print_role[$_role]) {
$_role_print = preg_replace("/_/", " ", $_role);
} else {
$_role_print = '';
}
if (count($this->allowedDomains)) {
printf(
"<tr><td><b>%s</b></td><td class=span4>%s</td><td>%s</td></tr>",
ucfirst($_role_print),
$this->ip2host($_entity['ip']),
$_entity['version']
);
} else {
$a_print = '';
if (is_array($_entity['attributes'])) {
foreach (array_keys($_entity['attributes']) as $_a1) {
if ($_a1 == 'dburi') {
if (preg_match("/^(mysql:\/\/\w*):\w*(@.*)$/", $_entity['attributes'][$_a1], $m)) {
$val = $m[1].':xxx'.$m[2];
} else {
$val = $_entity['attributes'][$_a1];
}
} else {
$val=$_entity['attributes'][$_a1];
}
$a_print .= sprintf("%s=%s ", $_a1, $val);
}
}
printf(
"<tr><td class=span3><b>%s</b></td><td class=span2>%s</td><td class=span2>%s</td><td>%s</td></tr>",
ucfirst($_role_print),
$this->ip2host($_entity['ip']),
$_entity['version'],
$a_print
);
}
$print_role[$_role]++;
}
}
print "</table>";
}
public function showStatistics()
{
$this->getStatistics();
print "<div class=row><table class='span12 table table-condensed table-striped'>";
print "<thead><tr>";
foreach (array_keys($this->sip_summary) as $_section) {
$_section_print = preg_replace("/_/", " ", $_section);
printf("<th>%s</th>", ucfirst($_section_print));
}
print "</tr></thead><tr>";
foreach (array_keys($this->sip_summary) as $_section) {
printf("<td style='text-align:center'>%s</td>", $this->sip_summary[$_section]);
}
print "</tr>";
print "</table></div>";
}
private function ip2host($ip)
{
if ($this->hostnames[$ip]) {
return $this->hostnames[$ip];
} else {
return $ip;
}
}
}
class SipThorNetworkImage {
// plot graphical SIP Thor network status
public $imgsize = 630;
public $nodes = array();
public $node_statistics = array();
public $display_options = array();
public $accounts_item = 'online_accounts';
public function __construct($engineId, $allowedDomains = array(), $display_options = array())
{
if (!strlen($engineId)) {
return false;
}
if (is_array($display_options)) {
$this->display_options = $display_options;
}
if (array_key_exists('accounts_item', $this->display_options)) {
$this->accounts_item=$this->display_options['accounts_item'];
}
$this->soapEngineId=$engineId;
$NetworkStatistics = new NetworkStatistics($engineId, $allowedDomains);
$NetworkStatistics->getStatus();
$NetworkStatistics->getStatistics();
$this->sip_proxies = $NetworkStatistics->sip_proxies;
$this->conference_servers = $NetworkStatistics->conference_servers;
$this->voicemail_servers = $NetworkStatistics->voicemail_servers;
$this->dns_managers = $NetworkStatistics->dns_managers;
$this->thor_mangers = $NetworkStatistics->thor_managers;
$this->node_statistics = $NetworkStatistics->node_statistics;
$this->hostnames = $NetworkStatistics->hostnames;
if (!$this->display_options['hide_sessions']) {
require_once("media_sessions.php");
$MediaSessions = new MediaSessionsNGNPro($engineId);
$MediaSessions->getSummary();
foreach ($MediaSessions->summary as $_relay) {
$this->node_statistics[$_relay['ip']]['sessions']=$_relay['session_count'];
}
}
}
public function returnImageData()
{
if ($this->display_options['hide_accounts']) {
foreach ($this->node_statistics as $key => $value) {
if ($value['sip_proxy']) {
$this->node_statistics[$key] = array();
$this->node_statistics[$key]['sip_proxy'] = true;
}
}
}
return $this;
}
public function buildImage()
{
$img = imagecreatetruecolor($this->imgsize, $this->imgsize);
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
imagefill($img, 0, 0, $white);
$c=count($this->sip_proxies);
$cx=$this->imgsize/2;
$cy=$cx;
$radius=0.7*$cx;
// Sip Thor node image
$sip_thor_node_img = @imagecreatefrompng('SipThorNode.png');
list($nw, $nh) = getimagesize('SipThorNode.png');
// Internet cloud Image
$cloud_img = @imagecreatefrompng('InternetCloud.png');
list($cw, $ch) = getimagesize('InternetCloud.png');
// Sip Thor title rectangle image
$sip_thor_background_img = @imagecreatefrompng('SipThorNetworkBackground.png');
list($tw, $th) = getimagesize('SipThorNetworkBackground.png');
if (!$this->display_options['hide_frame']) {
imagecopy($img, $sip_thor_background_img, $this->imgsize/2-$tw/2, $this->imgsize/2-$th/2, 0, 0, $tw, $th);
}
imagecopy($img, $cloud_img, $this->imgsize/2-$cw/2, $this->imgsize/2-$ch/2, 0, 0, $cw, $ch);
$dash=false;
$dashsize=2;
for ($angle=0; $angle<=(180+$dashsize); $angle+=$dashsize) {
$x = ($radius * cos(deg2rad($angle)));
$y = ($radius * sin(deg2rad($angle)));
if ($dash) {
imageline($img, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $black);
imageline($img, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $black);
}
$dash=!$dash;
$px=$x;
$py=$y;
if ($dash) {
imageline($img, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $black);
imageline($img, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $black);
}
}
if (count($this->dns_managers)) {
$h1=0;
$t=count($this->dns_managers);
foreach (array_keys($this->dns_managers) as $_ip) {
imagecopy($img, $sip_thor_node_img, $this->imgsize - 120 - $h1, 0, 0, 0, $nw - 20, $nh - 20);
$text = sprintf("DNS%s", $t--);
imagestring($img, 3, $this->imgsize - 65 - $h1, 80, $text, $black);
$v1 = $v1+10;
$h1 = $h1+50;
}
$v1=100;
foreach (array_keys($this->dns_managers) as $_ip) {
imagestring($img, 3, $this->imgsize - 125, $v1, $_ip, $black);
$v1=$v1+10;
}
}
if (count($this->node_statistics)) {
$dashsize=360/count($this->node_statistics);
$j=0;
$node_names=array_keys($this->node_statistics);
for ($angle=0; $angle<360; $angle+=$dashsize) {
$x = ($radius * cos(deg2rad($angle)));
$y = ($radius * sin(deg2rad($angle)));
if ($this->hostnames[$node_names[$j]]) {
$text = $this->hostnames[$node_names[$j]];
// $text = $node_names[$j];
} else {
$text = $node_names[$j];
}
$px = $x;
$py = $y;
if (strlen($this->node_statistics[$node_names[$j]]['online_accounts']) && strlen($this->node_statistics[$node_names[$j]]['sessions'])) {
if (!$this->display_options['hide_accounts']) {
$extra_text1=intval($this->node_statistics[$node_names[$j]][$this->accounts_item]). ' accounts';
}
if (!$this->display_options['hide_sessions']) {
$extra_text2=intval($this->node_statistics[$node_names[$j]]['sessions']). ' sessions';
}
} else if (strlen($this->node_statistics[$node_names[$j]]['online_accounts'])) {
if (!$this->display_options['hide_accounts']) {
$extra_text1=intval($this->node_statistics[$node_names[$j]][$this->accounts_item]). ' accounts';
} else {
$extra_text1=$node_names[$j];
}
$extra_text2="";
} else if (strlen($this->node_statistics[$node_names[$j]]['sessions'])) {
if (!$this->display_options['hide_sessions']) {
$extra_text1=intval($this->node_statistics[$node_names[$j]]['sessions']). ' sessions';
}
$extra_text2="";
}
if (($angle >= 120 && $angle < 240)) {
imagestring($img, 3, $cx+$px-70, $cy+$py-72, $text, $black);
imagestring($img, 3, $cx+$px-70, $cy+$py-62, $extra_text1, $black);
imagestring($img, 3, $cx+$px-70, $cy+$py-52, $extra_text2, $black);
} else {
imagestring($img, 3, $cx+$px-110, $cy+$py-30, $text, $black);
imagestring($img, 3, $cx+$px-110, $cy+$py-20, $extra_text1, $black);
imagestring($img, 3, $cx+$px-110, $cy+$py-10, $extra_text2, $black);
}
imagecopy($img, $sip_thor_node_img, $cx + $px - $nw / 2 + 7, $cy + $py - $nh / 2 + 5, 0, 0, $nw - 20, $nh - 20);
$j++;
}
}
return $img;
}
}
class SIPstatistics {
// build graphical statistics with sip registrar and media relay usage
public $domains = array('total'=>'total');
public function __construct()
{
global $CDRTool;
$this->path=$CDRTool['Path'];
$this->harvest_file = "/tmp/CDRTool-sip-statistics.txt";
$this->harvest_script = $this->path."/scripts/harvestStatistics.php";
$this->mrtgcfg_dir = $this->path."/status/usage";
$this->mrtgcfg_file = $this->path."/status/usage/sip_statistics.mrtg";
$this->mrtg_data_script = $this->path."/scripts/generateMrtgData.php";
$this->mrtg_config_script = $this->path."/scripts/generateMrtgConfig.php";
$this->getDomains();
}
private function getDomains()
{
global $CDRTool;
if (!is_array($CDRTool['statistics']['domains'])) {
return;
}
foreach ($CDRTool['statistics']['domains'] as $_domain) {
$this->domains[$_domain]=$_domain;
}
}
public function generateMrtgConfigFile()
{
if (!$handle = fopen($this->mrtgcfg_file, 'w+')) {
echo "Error opening {$this->mrtgcfg_file}.\n";
return 0;
}
// printing cfg header
fwrite($handle, "
### Global Config Options
WorkDir: {$this->mrtgcfg_dir}
IconDir: {$this->mrtgcfg_dir}/images
Refresh: 300
#WriteExpires: Yes
");
- while (list($key, $value) = each($this->domains)) {
+ foreach ($this->domains as $key => $value) {
fwrite($handle, "\n\n
## {$key}
Target[{$key}_users]: `{$this->mrtg_data_script} {$key} users`
Options[{$key}_users]: growright, gauge, nobanner
BodyTag[{$key}_users]: <BODY LEFTMARGIN=\"1\" TOPMARGIN=\"1\">
#PNGTitle[{$key}_users]: <center>Online Users for {$key}</center>
MaxBytes[{$key}_users]: 5000000
Title[{$key}_users]: Online Users for {$key}
ShortLegend[{$key}_users]: U
XSize[{$key}_users]: 300
YSize[{$key}_users]: 75
Ylegend[{$key}_users]: Users
Legend1[{$key}_users]: Online Users
LegendI[{$key}_users]: Online Users
LegendO[{$key}_users]:
PageTop[{$key}_users]: <H1> Online Users for {$key} </H1>
Target[{$key}_sessions]: `{$this->mrtg_data_script} {$key} sessions`
Options[{$key}_sessions]: growright, nobanner, gauge
BodyTag[{$key}_sessions]: <BODY LEFTMARGIN=\"1\" TOPMARGIN=\"1\">
MaxBytes[{$key}_sessions]: 50000
Title[{$key}_sessions]: Sessions Statistics for {$key}
ShortLegend[{$key}_sessions]: Ses
XSize[{$key}_sessions]: 300
YSize[{$key}_sessions]: 75
Ylegend[{$key}_sessions]: Sessions
Legend1[{$key}_sessions]: Active Sessions
LegendI[{$key}_sessions]: Active Sessions
LegendO[{$key}_sessions]:
PageTop[{$key}_sessions]: <H1> Active Sessions for {$key} </H1>
Target[{$key}_traffic]: `{$this->mrtg_data_script} {$key} traffic`
Options[{$key}_traffic]: gauge, growright, bits, nobanner
BodyTag[{$key}_traffic]: <BODY LEFTMARGIN=\"1\" TOPMARGIN=\"1\">
#PNGTitle[{$key}_traffic]: {$key} traffic
MaxBytes[{$key}_traffic]: 1250000000
Title[{$key}_traffic]: IP traffic for {$key}
XSize[{$key}_traffic]: 300
YSize[{$key}_traffic]: 75
Legend1[{$key}_traffic]: Caller Traffic in Bits per Second
Legend2[{$key}_traffic]: Called Traffic in Bits per Second
LegendI[{$key}_traffic]: caller
LegendO[{$key}_traffic]: called
PageTop[{$key}_traffic]: <H1> IP Traffic for {$key} </H1>
");
}
fclose($handle);
}
public function generateMrtgData($domain, $dataType)
{
$value1 = 0;
$value2 = 0;
$domain = str_replace(".", "\.", $domain);
$lines = explode("\n", file_get_contents($this->harvest_file));
foreach ($lines as $line) {
if (preg_match("/^$domain\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/", $line, $m)) {
if ($dataType == 'sessions') {
$value1 = $m[2];
$value2 = $m[2];
} else if ($dataType == 'traffic') {
$value1 = $m[3];
$value2 = $m[4];
} else if ($dataType == 'users') {
$value1 = $m[1];
$value2 = $m[1];
}
}
}
printf("%d\n%d\n0\n0\n\n", $value1, $value2);
}
public function getOnlineAccountsFromMySQL($class)
{
$domains = array();
$online_devices = 0;
$online_accounts = 0;
if (!class_exists($class)) {
return array();
}
$db = new $class();
$query="select count(*) as c, domain from location group by domain";
dprint_sql($query);
if (!$db->query($query)) {
$log=sprintf("Database error for query %s: %s (%s)", $query, $db->Error, $db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return array();
}
if (!$db->num_rows()) {
return array();
}
while ($db->next_record()) {
$domains[$db->f('domain')]['online_devices'] = intval($db->f('c'));
$online_devices = $online_devices + intval($db->f('c'));
}
$query="select count(distinct(concat(username,domain))) as c, domain from location group by domain";
dprint_sql($query);
if (!$db->query($query)) {
$log = sprintf("Database error for query %s: %s (%s)", $query, $db->Error, $db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return array();
}
if (!$db->num_rows()) {
return array();
}
while ($db->next_record()) {
$domains[$db->f('domain')]['online_accounts'] = intval($db->f('c'));
$online_accounts=$online_accounts+intval($db->f('c'));
}
$domains['total']['online_devices']=$online_devices;
$domains['total']['online_accounts']=$online_accounts;
return $domains;
}
private function writeHarvestFile($body)
{
if (!strlen($body)) {
return 0;
}
if (!$handle = fopen($this->harvest_file, 'w+')) {
$log=sprintf("Error opening mrtg harvest file %s\n", $this->harvest_file);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
fwrite($handle, $body);
fclose($handle);
}
public function harvestStatistics()
{
global $DATASOURCES;
$datasources = array_keys($DATASOURCES);
$totals = array();
foreach ($datasources as $datasource) {
if (!$DATASOURCES[$datasource]['skipStatistics']) {
if ($DATASOURCES[$datasource]['mediaSessions']) {
// MediaProxy 2 via NGNPro
require_once("media_sessions.php");
$MediaSessions = new MediaSessionsNGNPro($DATASOURCES[$datasource]['mediaSessions']);
$MediaSessions->getSessions();
$totals = array_merge_recursive($totals, $MediaSessions->domain_statistics);
} else if ($DATASOURCES[$datasource]['mediaDispatcher']) {
// MediaProxy 2 via dispatcher tcp socket
require_once("media_sessions.php");
$MediaSessions = new MediaSessions($DATASOURCES[$datasource]['mediaDispatcher']);
$MediaSessions->getSessions();
$totals = array_merge_recursive($totals, $MediaSessions->domain_statistics);
} else if ($DATASOURCES[$datasource]['mediaServers']) {
// MediaProxy 1 via relay tcp socket
$MediaSessions = new MediaSessions1($DATASOURCES[$datasource]['mediaServers'], $allowedDomains);
$MediaSessions->getSessions();
$totals = array_merge_recursive($totals, $MediaSessions->domain_statistics);
}
if ($DATASOURCES[$datasource]['networkStatus']) {
// OpenSIPS via NGNPro
$NetworkStatistics = new NetworkStatistics($DATASOURCES[$datasource]['networkStatus']);
$NetworkStatistics->getStatistics();
$totals = array_merge_recursive($totals, $NetworkStatistics->domain_statistics);
} else if ($DATASOURCES[$datasource]['db_registrar']) {
// OpenSIPS via MySQL query
$db_registrar_domains=$this->getOnlineAccountsFromMySQL($DATASOURCES[$datasource]['db_registrar']);
$totals = array_merge_recursive($totals, $db_registrar_domains);
}
}
}
$body="domains\t\t\tonline_accounts\tsessions\tcaller\tcallee\n\n";
foreach (array_keys($totals) as $_domain) {
if (!$totals[$_domain]['online_accounts'] && !$totals[$_domain]['sessions']) {
continue;
}
$body .= sprintf(
"%s\t\t%d\t\t%d\t\t%s\t%s\n",
$_domain,
$totals[$_domain]['online_accounts'],
$totals[$_domain]['sessions'],
intval($totals[$_domain]['caller']),
intval($totals[$_domain]['callee'])
);
}
$this->writeHarvestFile($body);
}
public function buildStatistics()
{
system($this->mrtg_config_script);
system($this->harvest_script);
system("env LANG=C mrtg $this->mrtgcfg_file");
}
}
/**
* MRTGGraphs class sets up the dashboard and creates Entity objects.
*/
class MRTGGraphs {
/**
* MRTG entities
*
* @var array
*/
public $entities = array();
/**
* Server hostname;
*
* @var type
*/
public $hostname;
/**
* Domains;
*
* @var type
*/
public $domains = array();
/**
* Graphs types;
*
* @var type
*/
public $graph_types = array('users','sessions','traffic');
/**
* Construct.
*/
public function __construct()
{
//require("sip_statistics.php");
$title='Platform usage';
if (is_readable("/etc/cdrtool/local/header.phtml")) {
include("/etc/cdrtool/local/header.phtml");
} else {
include("header.phtml");
}
$layout = new pageLayoutLocal();
$layout->showTopMenu($title);
global $CDRTool;
$SIPstatistics = new SIPstatistics();
$allowedDomains = '';
if (strlen($CDRTool['filter']['domain'])) {
$allowedDomains = explode(' ', $CDRTool['filter']['domain']);
}
if (is_array($allowedDomains)) {
$domains = array_intersect($allowedDomains, array_keys($SIPstatistics->domains));
} else {
$domains = array_keys($SIPstatistics->domains);
}
$this->domains[]= $domains;
// read entities in directory for each entry in domain list
foreach ($domains as $entity) {
$entity = sprintf("status/usage/%s", $entity);
foreach ($this->graph_types as $type) {
$final_entity = sprintf("%s_%s.log", $entity, $type);
$this->entities[] = new MRTGEntity(preg_replace("/.log$/", "", $final_entity));
}
}
$this->layout = $layout;
// determine hostname
exec("hostname -f", $hostname);
$this->hostname = $hostname[0];
}
}
/**
* Entity class represents each MRTG entity found in the directory.
*/
class MRTGEntity {
/**
* Entity name.
*
* @var string
*/
public $name;
/**
* Entity title.
*
* @var string
*/
public $title;
/**
* Entity page link.
*
* @var string
*/
public $link;
/**
* Entity log file.
*
* @var string
*/
public $log;
/**
* Construct.
*
* @throws Exception
*/
public function __construct($name)
{
// check entity exists
if (!is_file("{$name}.html")) {
throw new Exception("Could not find MRTG files for entity {$name}");
}
// add name
$this->name = $name;
// create nicer-looking title
$np = explode('_', $name);
$this->title = preg_replace("/status\/usage\//", "", $np[0]);
array_shift($np);
if (in_array('users', $np) && strstr($this->title, 'total')) {
$this->title = ucfirst($this->title)." SIP Accounts online";
} else if (in_array('users', $np)) {
$this->title = "Online SIP accounts on $this->title";
} else if (in_array('traffic', $np) && strstr($this->title, 'total')) {
$this->title = ucfirst($this->title)." relayed RTP traffic";
} else if (in_array('traffic', $np)) {
$this->title = "Relayed RTP traffic for $this->title";
} else if (in_array('sessions', $np) && strstr($this->title, 'total')) {
$this->title = ucfirst($this->title)." active RTP media sessions";
} else if (in_array('sessions', $np)) {
$this->title = "Active RTP media sessions for $this->title";
} else {
$this->title .= " (".implode(" ", $np).")";
}
// add HTML and log files
$this->link = $name.'.html';
$this->log = $name.'.log';
}
/**
* Retrieve and process the entity's log file.
*
* @param boolean $max Set to true to retrieve maximum in/out rather than average.
*
* @return string JSON encoded data
*/
public function retrieveLog($max = false)
{
// arrays for parsed data
$in = $out = $stamps = array();
global $start_date,$stop_date;
foreach (file("{$this->name}.log") as $line) {
// ignore the summary line
if (!isset($header)) {
$header = $line;
continue;
}
$parts = explode(' ', rtrim($line));
//if ($parts[1] == 0 && $parts[2] == 0 && $parts[3] == 0 && $parts[4] == 0) continue;
if ($parts[0] < $start_date->getTimestamp()) {
continue;
}
if ($parts[0] > $stop_date->getTimestamp()) {
continue;
}
array_push($stamps, $parts[0]);
if (strstr($this->name, 'traffic')) {
if ($max) {
$in[] = array($parts[0],round(($parts[3]*8)/1000));
$out[] = array($parts[0]*1000,round(($parts[4]*8)/1000));
} else {
$in[] = array(date('Y-m-d H:i:s', $parts[0]), round(($parts[1]*8)));
$out[] = array(date('Y-m-d H:i:s', $parts[0]), round(($parts[2]*8)));
}
} else {
if ($max) {
$in[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[3]));
$out[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[4]));
} else {
$in[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[1]));
$out[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[2]));
}
}
}
// determine earliest and latest timestamps
$latest = array_shift($stamps);
$earliest = array_pop($stamps);
$interval = 300;
// encode and return response
return json_encode(array(
'earliest' => $earliest,
'latest' => $latest,
'start' => $start_date,
'stop' => $stop_date,
'interval' => $interval,
'intervalMin' => round($interval/60, 0),
'inData' => array_reverse($in),
'outData' => array_reverse($out)
));
}
}
?>
diff --git a/scripts/OpenSIPS/notifyLastSessions.php b/scripts/OpenSIPS/notifyLastSessions.php
index a9e74fd..d64ea07 100755
--- a/scripts/OpenSIPS/notifyLastSessions.php
+++ b/scripts/OpenSIPS/notifyLastSessions.php
@@ -1,21 +1,21 @@
#!/usr/bin/env php
<?php
/**
* Send email to subscribers with the last sessions received in the last 24 hours
* to notify a susbcriber add him to the missed_calls group
*/
set_time_limit(0);
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["notifyLastSessions"])) {
$class_name = $v["class"];
unset($CDRS);
$CDRS = new $class_name($k);
$CDRS->notifyLastSessions(200);
}
}
diff --git a/scripts/OpenSIPS/quotaCheck.php b/scripts/OpenSIPS/quotaCheck.php
index 2861eb8..090001d 100755
--- a/scripts/OpenSIPS/quotaCheck.php
+++ b/scripts/OpenSIPS/quotaCheck.php
@@ -1,70 +1,70 @@
#!/usr/bin/env php
<?php
/**
* This script blocks accounts in OpenSIPS
* based on platform wide or user specified quota
* - quota can be specified in opensips.subscriber.quota
* - account is blocked by adding SIP account in group quota
* and configuring opensips.cfg to reject calls from such users
* - Blocked Users must be deblocked manualy and their quota
* must be changed to a higher value otherwise
* subscriber gets blocked again at the next script run
* - Add this script to cron to run every 5 minutes
* - Notifications are sent once to subscribers
*/
//$verbose=1;
set_time_limit(0);
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
require 'rating.php';
$b = time();
$lockFile = sprintf("/var/lock/CDRTool_QuotaCheck.lock");
$abort_text = "Another check is in progress. Try again later.\n";
$f = fopen($lockFile, "w");
if (flock($f, LOCK_EX + LOCK_NB, $w)) {
if ($w) {
print $abort_text;
syslog(LOG_NOTICE, $abort_text);
exit(2);
}
} else {
print $abort_text;
syslog(LOG_NOTICE, $abort_text);
exit(1);
}
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["UserQuotaClass"])) {
unset($CDRS);
$class_name = $v["class"];
$CDRS = new $class_name($k);
$Quota_class = $v["UserQuotaClass"];
$log=sprintf("Checking user quotas for data source %s\n", $v['name']);
syslog(LOG_NOTICE, $log);
//print $log;
$Quota = new $Quota_class($CDRS);
$Quota->checkQuota($v['UserQuotaNotify']);
$d = time() - $b;
if ($d > 5) {
$log = sprintf("Runtime: %d s", $d);
syslog(LOG_NOTICE, $log);
}
}
}
function deleteQuotaCheckLockfile($lockFile)
{
if (!unlink($lockFile)) {
print "Error: cannot delete lock file $lockFile. Aborting.\n";
syslog(LOG_NOTICE, "Error: cannot delete lock file $lockFile");
}
}
diff --git a/scripts/OpenSIPS/quotaDailyReset.php b/scripts/OpenSIPS/quotaDailyReset.php
index 1872a02..4685100 100755
--- a/scripts/OpenSIPS/quotaDailyReset.php
+++ b/scripts/OpenSIPS/quotaDailyReset.php
@@ -1,26 +1,26 @@
#!/usr/bin/env php
<?php
/**
* This script resets the daily quota system
* This script must be run once at the beginning of each day
*/
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
require 'rating.php';
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["UserQuotaClass"])) {
unset($CDRS);
$class_name = $v["class"];
$CDRS = new $class_name($k);
$Quota_class = $v["UserQuotaClass"];
$log=sprintf("Reset daily user quotas for data source %s\n", $v['name']);
syslog(LOG_NOTICE, $log);
$Quota = new $Quota_class($CDRS);
$Quota->resetDailyQuota();
}
}
diff --git a/scripts/OpenSIPS/quotaDeblock.php b/scripts/OpenSIPS/quotaDeblock.php
index 5d67712..3223b39 100755
--- a/scripts/OpenSIPS/quotaDeblock.php
+++ b/scripts/OpenSIPS/quotaDeblock.php
@@ -1,68 +1,68 @@
#!/usr/bin/env php
<?php
/**
* This script blocks accounts in OpenSIPS
* based on platform wide or user specified quota
* - quota can be specified in opensips.subscriber.quota
* - account is blocked by adding SIP account in group quota
* and configuring opensips.cfg to reject calls from such users
* - Blocked Users must be deblocked manualy and their quota
* must be changed to a higher value otherwise
* subscriber gets blocked again at the next script run
* - Add this script to cron to run every 5 minutes
* - Notifications are sent once to subscribers
*/
// $verbose=1;
set_time_limit(0);
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
require 'rating.php';
$b = time();
$lockFile = sprintf("/var/lock/CDRTool_QuotaDeblock.lock");
$abort_text = "Another deblock process is in progress. Try again later.\n";
$f = fopen($lockFile, "w");
if (flock($f, LOCK_EX + LOCK_NB, $w)) {
if ($w) {
print $abort_text;
syslog(LOG_NOTICE, $abort_text);
exit(2);
}
} else {
print $abort_text;
syslog(LOG_NOTICE, $abort_text);
exit(1);
}
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["UserQuotaClass"])) {
unset($CDRS);
$class_name = $v["class"];
$CDRS = new $class_name($k);
$Quota_class = $v["UserQuotaClass"];
$log = sprintf("Checking user quotas for data source %s\n", $v['name']);
syslog(LOG_NOTICE, $log);
//print $log;
$Quota = new $Quota_class($CDRS);
$Quota->deblockAccounts();
$d = time()-$b;
$log = sprintf("Runtime: %d s", $d);
syslog(LOG_NOTICE, $log);
}
}
function deleteQuotaDeblock($lockFile)
{
if (!unlink($lockFile)) {
print "Error: cannot delete lock file $lockFile. Aborting.\n";
syslog(LOG_NOTICE, "Error: cannot delete lock file $lockFile");
}
}
diff --git a/scripts/OpenSIPS/quotaReset.php b/scripts/OpenSIPS/quotaReset.php
index 731fae8..417bc85 100755
--- a/scripts/OpenSIPS/quotaReset.php
+++ b/scripts/OpenSIPS/quotaReset.php
@@ -1,27 +1,27 @@
#!/usr/bin/env php
<?php
/**
* This script resets the quota system
* This script must be run once at the beginning of the calendar month
*/
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
require 'rating.php';
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["UserQuotaClass"])) {
unset($CDRS);
$class_name = $v["class"];
$CDRS = new $class_name($k);
$Quota_class = $v["UserQuotaClass"];
$log = sprintf("Reset user quotas for data source %s\n", $v['name']);
syslog(LOG_NOTICE, $log);
//print $log;
$Quota = new $Quota_class($CDRS);
$Quota->deleteQuotaInitFlag();
}
}
diff --git a/scripts/OpenSIPS/quotaShowAccounts.php b/scripts/OpenSIPS/quotaShowAccounts.php
index 3d3d1ff..267a42e 100755
--- a/scripts/OpenSIPS/quotaShowAccounts.php
+++ b/scripts/OpenSIPS/quotaShowAccounts.php
@@ -1,33 +1,33 @@
#!/usr/bin/env php
<?php
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
require 'rating.php';
if (!count($argv) || count($argv) != 2) {
printf("Syntax: %s treshhold\n", $_SERVER['PHP_SELF']);
print "Accounts with quota usage percentage greater than the treshhold will be showed.\n";
return 0;
}
if (!preg_match("/^\d{1,2}$/", $argv[1])) {
print "Error: treshold must be an integer between 0 and 100\n";
return 0;
}
-while (list($k, $v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v["UserQuotaClass"])) {
unset($CDRS);
$class_name = $v["class"];
$CDRS = new $class_name($k);
$Quota_class = $v["UserQuotaClass"];
$log=sprintf("Checking user quotas for data source %s\n", $v['name']);
syslog(LOG_NOTICE, $log);
//print $log;
$Quota = new $Quota_class($CDRS);
$Quota->showAccountsWithQuota($argv[1]);
}
}
diff --git a/scripts/purgeTables.php b/scripts/purgeTables.php
index adbe247..770c898 100755
--- a/scripts/purgeTables.php
+++ b/scripts/purgeTables.php
@@ -1,38 +1,38 @@
#!/usr/bin/env php
<?php
require '/etc/cdrtool/global.inc';
require 'cdr_generic.php';
// purge old logs of debit balance
$PrepaidHistory = new PrepaidHistory();
$PrepaidHistory->purge();
print "\n";
// purge old CDRs when using a central radius table
-while (list($k,$v) = each($DATASOURCES)) {
+foreach ($DATASOURCES as $k => $v) {
if (strlen($v['purgeCDRsAfter'])) {
$class_name = $v["class"];
$log = sprintf("Datasource: %s\n", $v['name']);
print $log;
syslog(LOG_NOTICE, $log);
unset($CDRS);
$CDRS = new $class_name($k);
if ($argv[1] && !preg_match("/^(\d{4})(\d{2})$/", $argv[1], $m)) {
print "Error: Month must be in YYYYMM format\n";
continue;
} else {
$endDate = date('Y-m-d', time() - 3600 * 24 * $v['purgeCDRsAfter']);
$log = sprintf("Purge CDRs before %s\n", $endDate);
print $log;
syslog(LOG_NOTICE, $log);
}
$CDRS->purgeTable($argv[1]);
print "\n";
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 26, 7:42 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3414532
Default Alt Text
(287 KB)

Event Timeline