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 @@ '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 "
"; if ($this->rating) { print ""; } print " "; } 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 "
Calls Seconds Minutes HoursPriceSuccess Failure $group_byPrint Description Action
"; } 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 "

You do not have the right for statistics."; 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 ("

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 "

"; } 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 "
Date and time Username Source In Destination Out Dur Price Context Channel in Channel out Account App (Duration)
$found $calls $seconds_print $minutes_print $hours $pricePrint $success% ($nonzero calls) $failure% ($zero calls) $mygroup_print $description Display calls
"; } } 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 "
"; } } } $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 " "; $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 " "; print " "; print " "; print " "; print " "; print " "; print "
Context "; $this->f->show_element("context",""); print "
Channels Incomming "; $this->f->show_element("channel_in",""); print "Outgoing"; $this->f->show_element("channel_out",""); print "
Username "; $this->f->show_element("UserName_comp",""); $this->f->show_element("UserName",""); print "
Source "; $this->f->show_element("a_number_comp",""); $this->f->show_element("a_number",""); print "
Destination "; $this->f->show_element("c_number_comp",""); $this->f->show_element("c_number",""); print "
Duration "; $this->f->show_element("duration",""); print " Application "; $this->f->show_element("applicationType",""); print "
Order by "; $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 "    ReNormalize"; print " "; print "

"; $this->f->show_element("submit",""); $this->f->finish(); print "
"; } function searchFormSubscriber() { global $perm; // Start displaying form $this->initForm(); $this->f->start("","POST","","","datasource"); print " "; $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 " "; print " "; print " "; print " "; print " "; print "
Context "; $this->f->show_element("context",""); print "
Channels Incomming "; $this->f->show_element("channel_in",""); print "Outgoing"; $this->f->show_element("channel_out",""); print "
Source "; $this->f->show_element("a_number_comp",""); $this->f->show_element("a_number",""); print "
Destination "; $this->f->show_element("c_number_comp",""); $this->f->show_element("c_number",""); print "
Duration "; $this->f->show_element("duration",""); print " Application "; $this->f->show_element("applicationType",""); print "
Order by "; $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 "    ReNormalize"; print " "; print "

"; $this->f->show_element("submit",""); $this->f->finish(); print "
"; } } class CDR_asterisk extends CDR { function CDR_asterisk($parent,$CDRfields) { dprint("
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= "". "In". ""; } 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= "". "Out". ""; } 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="
"; if ($this->price > 0) { $CallInfoVerbose.= "
Rating information
$this->ratePrint
"; } $CallInfoVerbose.= "
"; print " $found_print $this->startTime $this->username $this->aNumberPrint $this->traceIn $this->cNumberPrint $this->destinationName $this->DestinationId $this->traceOut $this->durationPrint $this->pricePrint $this->domain $this->channelIn $this->channelOut $this->billingAccount $this->applicationType ($this->appDurationPrint) $CallInfoVerbose "; } 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 @@ '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 "
"; if ($this->rating) { print " "; } print " "; print ""; } 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 "
Calls Seconds Minutes HoursPriceMB In MB Out Success Failure $group_byPrint Description Type Action
"; if ($this->rating) { print ""; } print " "; } else { print "$found,$calls,$seconds,$minutes,$hours,$AcctInputOctets,$AcctOutputOctets,$success,$nonzero,$failure,$zero,$mygroup_print,$description\n"; } $i++; } if (!$this->export) { print "
"; } print " "; } 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 "
Date and time Caller Party In Destination Out Dur"; if ($this->rating) { if ($this->showRate) { print "Rate Price "; } print " Gateway KBIn KBOut Disconnect Channel Direction CallType
"; $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 " "; print " "; print " "; print " "; print " "; print " "; print "
Gateway "; $this->f->show_element("RemoteAddress",""); print " Local gateway:"; $this->f->show_element("NASIPAddress",""); print " Port Id "; $this->f->show_element("NASPortId",""); print "
Call Id "; $this->f->show_element("call_id",""); print "
Caller Party "; $this->f->show_element("a_number_comp",""); $this->f->show_element("a_number",""); print " Direction "; $this->f->show_element("H323CallOrigin",""); print "
Destination "; $this->f->show_element("c_number_comp",""); $this->f->show_element("c_number",""); print " Technology "; $this->f->show_element("H323CallType",""); print "
Call duration "; $this->f->show_element("duration",""); print " Disconnection cause "; $this->f->show_element("release_cause",""); print " ReNormalize"; print ""; print "
Order by "; $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 "

"; $this->f->show_element("submit",""); $this->f->finish(); print "
"; } 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 "

You do not have the right for statistics."; 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 ("

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 "

$found $calls $seconds_print $minutes_print $hours$pricePrint$AcctInputOctets $AcctOutputOctets $success% ($nonzero calls) $failure% ($zero calls) $mygroup_print $description $H323CallType Display calls
"; } } 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 " "; } } 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("
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="In"; } } 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= "". "Out". ""; } 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 " $found $this->startTime $this->aNumberPrint $this->traceIn $this->cNumberPrint $this->destinationName $this->DestinationId $this->traceOut "; if ($this->duration) { print "$this->durationPrint"; } else { print "$this->durationPrint"; } if ($this->CDRS->rating) { $this->ratePrint=nl2br($this->rate); if ($this->showRate) { print "$this->ratePrint"; } if ($this->price) { $quotedRate = addcslashes(nl2br($this->rate), "\n\r"); $jscode="onMouseOver=\"stm('Rating info', '$quotedRate', Style['right'])\" onMouseOut=\"htm()\""; } else { $jscode = ""; } print "$this->pricePrint "; } print " $this->gateway $this->inputTrafficPrint $this->outputTrafficPrint $this->disconnectPrint ($this->disconnect) $this->NASPortIdPrint $this->H323CallOrigin $this->H323CallType "; } 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 @@ '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 "
"; print "
url_edit\" > Refine searchurl_run\"> Refresh"; $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 "url_export\" target=_new> Export results to file
"; } else { print "
"; } print "
"; if (!$hide_rows) { print "
"; 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 "
"; } } } function showResultsMenuSubscriber($hide_rows = "", $begin_datetime = '', $end_datetime = '') { global $loginname; if (!$this->export) { print "
"; $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 " | url_export\" target=_new>Export results to file"; } print " "; } print "
url_edit\">Refine search | url_run\">Refresh | Save a description for this query:
"; if (!$hide_rows) { print "
"; 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 "
"; } } } function showDateTimeElements($f) { print " Start Time
"; $f->show_element("begin_date",""); print "
"; print "Time: "; print "
"; $f->show_element("begin_time",""); print "
Stop Time
"; $f->show_element("end_date",""); print "
"; print "Time: "; print "
"; $f->show_element("end_time",""); print "
"; } function showDataSources($f) { global $perm; print " Data Source "; $f->show_element("cdr_source",""); if (count($this->tables) > 0) { print " Table: "; $this->f->show_element("cdr_table",""); } print " "; } function showPagination($next, $maxrows) { $PHP_SELF = $_SERVER["PHP_SELF"]; if (!$this->export) { print " "; } } 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 "

$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 ""; print " "; if ($this->domain) { print " "; } else { print " "; } print " "; } function showFooter() { print "
User@Domain SIP UA contact NAT address User Agent Expires Remain Users@ Domain
$this->total users@ $this->domains domains
"; } 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 " $found $onlines users@ $ld "; if ($this->domain) { print " "; } print " "; } } $this->showfooter(); /* print "

"; $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 " $found $sip_account $transport $c_els[0] $r_els[0] $user_agent $expires $remain "; $seen[$username]++; $seen[$domain]++; } } function showUAdistribution () { print ""; print " "; print ""; print ""; print ""; print " "; - while (list($k,$v) = each($this->countUA)) { + foreach ($this->countUA as $k => $v) { $users=$users+$v; $count++; print " "; print ""; print ""; print ""; print ""; } print " "; print ""; print ""; print ""; print " "; print "
User agentUsers
$count$k$v
$this->domain$users
"; } } 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 @@ 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 "

"; print ""; if (count($this->allowedDomains)) { print ""; } else { print ""; } 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( "", 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( "", ucfirst($_role_print), $this->ip2host($_entity['ip']), $_entity['version'], $a_print ); } $print_role[$_role]++; } } print "
RoleAddressVersion
RoleAddressVersionAttributes
%s%s%s
%s%s%s%s
"; } public function showStatistics() { $this->getStatistics(); print "
"; print ""; foreach (array_keys($this->sip_summary) as $_section) { $_section_print = preg_replace("/_/", " ", $_section); printf("", ucfirst($_section_print)); } print ""; foreach (array_keys($this->sip_summary) as $_section) { printf("", $this->sip_summary[$_section]); } print ""; print "
%s
%s
"; } 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]: #PNGTitle[{$key}_users]:
Online Users for {$key}
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]:

Online Users for {$key}

Target[{$key}_sessions]: `{$this->mrtg_data_script} {$key} sessions` Options[{$key}_sessions]: growright, nobanner, gauge BodyTag[{$key}_sessions]: 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]:

Active Sessions for {$key}

Target[{$key}_traffic]: `{$this->mrtg_data_script} {$key} traffic` Options[{$key}_traffic]: gauge, growright, bits, nobanner BodyTag[{$key}_traffic]: #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]:

IP Traffic for {$key}

"); } 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 $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 $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 $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 $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 $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 $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 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"; } }