Id |
Start Time |
Flow |
SIP Caller |
Caller Location |
Sip Proxy |
Media |
SIP Destination |
Dur |
Price |
KBIn |
KBOut |
Codecs |
Status |
";
}
function showExportHeader() {
print "id,StartTime,StopTime,BillingParty,BillingDomain,PSTNCallerId,CallerParty,CalledParty,DestinationId,DestinationName,RemoteAddress,CanonicalURI,Duration,Price,SIPProxy,Caller KBIn,Called KBIn,CallingUserAgent,CalledUserAgent,StatusCode,StatusName,Codec,Media\n";
}
function showTableHeaderSubscriber() {
if (!$this->export) {
print "
Id |
Start Time |
SIP Caller |
Caller Location |
Sip Proxy |
SIP Destination |
Duration |
Price |
KBIn |
KBOut |
";
} else {
print "id,StartTime,StopTime,SIPBillingParty,SIPBillingDomain,RemotePartyId,CallerParty,CalledParty,DestinationId,DestinationName,RemoteAddress,CanonicalURI,Duration,Price,SIPProxy,Applications,Caller KBIn,Called KBIn,CallingUserAgent,CalledUserAgent,StatusCode,StatusName,Codec,Application\n";
}
}
function showTableHeaderStatistics() {
$group_byPrint=$this->GROUPBY[$this->group_byOrig];
if (!$this->export) {
print "
|
Calls |
Seconds |
Minutes |
Hours |
Price |
TrafficIn(MB) |
TrafficOut(MB) |
Success |
Failure |
$group_byPrint |
Description |
Action |
";
} else {
print "id,Calls,Seconds,Minutes,Hours,Price,TrafficIn(MB),TrafficOut(MB),Success(%),Success(calls),Failure(%),Failure(calls),$group_byPrint,Description\n";
}
}
function initForm() {
-
// form els added below must have global vars
foreach ($this->FormElements as $_el) {
global ${$_el};
${$_el} = trim($_REQUEST[$_el]);
}
$action = "search";
if ($this->CDRTool['filter']['gateway']) {
$gateway=$this->CDRTool["filter"]["gateway"];
}
if ($this->CDRTool['filter']['aNumber']) {
$UserName=$this->CDRTool['filter']['aNumber'];
}
if ($this->CDRTool['filter']['domain']) {
$Realm = $this->CDRTool['filter']['domain'];
}
if (!$maxrowsperpage) $maxrowsperpage=15;
$this->f = new form;
if (isset($this->CDRTool['dataSourcesAllowed'])) {
while (list($k,$v)=each($this->CDRTool['dataSourcesAllowed'])) {
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"=>"class=span2 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",
"class"=>"span2",
"value"=>$cdr_table,
"extrahtml"=>"class=span2"
));
if ($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"];
list($begin_hour,$begin_min)=explode(":",$begin_time);
list($begin_year,$begin_month,$begin_day)=explode("-",$begin_date);
}
if ($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"];
list($end_hour,$end_min)=explode(":",$end_time);
list($end_year,$end_month,$end_day)=explode("-",$end_date);
}
// corect last day of the month to be valid day
$begin_day = validDay($begin_month,$begin_day,$begin_year);
$end_day = validDay($end_month,$end_day,$end_year);
$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"=>"call_id",
"type"=>"text",
"size"=>"50",
"maxlength"=>"100",
"extrahtml"=>"class=span4"
));
$this->f->add_element(array( "name"=>"UserName",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"a_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"BillingId",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"extra_html"=>"class=span2"
));
$this->f->add_element(array( "name"=>"c_number",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"sip_status",
"type"=>"select",
"options"=>$this->disconnectCodesElements,
"size"=>"1",
"value"=>$sip_status,
"extrahtml"=>"class=span3"
));
$this->f->add_element(array( "name"=>"sip_status_class",
"type"=>"select",
"options"=>$this->disconnectCodesClassElements,
"size"=>"1",
"extrahtml"=>"class=span3"
));
if (!$this->CDRTool['filter']['aNumber']) {
$durations_els = array(
array("label"=>"All calls","value"=>""),
array("label"=>"0 seconds","value"=>"zero"),
array("label"=>"non 0 seconds","value"=>"nonzero"),
array("label"=>"non 0 seconds without 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"=>"one hour","value"=>"onehour"),
array("label"=>"greater than 5 hours","value"=>"> 18000"),
array("label"=>"Un-normalized calls","value"=>"unnormalized"),
array("label"=>"Un-normalized calls > 0s","value"=>"unnormalized_duration"),
array("label"=>"One way media","value"=>"onewaymedia"),
array("label"=>"No media","value"=>"nomedia")
);
} else {
$durations_els = array(
array("label"=>"All calls","value"=>""),
array("label"=>"0 seconds call","value"=>"zero"),
array("label"=>"Succesfull calls","value"=>"nonzero"),
array("label"=>"less than 60 seconds","value"=>"< 60"),
array("label"=>"greater than 1 hour","value"=>"> 3600")
);
$this->GROUPBY=array(
'UserName' => 'SIP Billing Party',
'CallingStationId' => 'SIP Caller Party',
'DestinationId' => 'SIP Destination Id',
'SipApplicationType' => 'Application',
' ' => '-------------',
'hour' => 'Hour of day',
'DAYOFWEEK' => 'Day of Week',
'DAYOFMONTH' => 'Day of Month',
'DAYOFYEAR' => 'Day of Year',
'BYMONTH' => 'Month',
'BYYEAR' => 'Year'
);
}
$flow_els = array(
array("label"=>"Any Call Flow","value"=>""),
array("label"=>"On Net","value"=>"on-net"),
array("label"=>"Incoming","value"=>"incoming"),
array("label"=>"Outgoing","value"=>"outgoing"),
array("label"=>"Transit","value"=>"transit"),
array("label"=>"Diverted On Net","value"=>"diverted-on-net"),
array("label"=>"Diverted Off Net","value"=>"diverted-off-net"),
array("label"=>"On Net Diverted On Net","value"=>"on-net-diverted-on-net"),
array("label"=>"On Net Diverted Off Net","value"=>"on-net-diverted-off-net"),
array("label"=>"Unknown Flow","value"=>"Sip-Session")
);
$this->f->add_element(array( "name"=>"flow",
"type"=>"select",
"options"=>$flow_els,
"value"=>"",
"size"=>"1",
"extrahtml"=>"class=span3"
));
$this->f->add_element(array( "name"=>"duration",
"type"=>"select",
"options"=>$durations_els,
"value"=>"All",
"size"=>"1",
"extrahtml"=>"class=span3"
));
$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",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"c_number_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"UserName_comp",
"type"=>"select",
"options"=>$comp_ops_els,
"value"=>"begin",
"size"=>"1",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array( "name"=>"Realm",
"type"=>"text",
"size"=>"25",
"maxlength"=>"25",
"extrahtml"=>"class=span2"
));
$media_info_els=array(
array("label"=>"","value"=>""),
array("label"=>"Timeout","value"=>"timeout"),
array("label"=>"ICE session","value"=>"ICE session")
);
$this->f->add_element(array( "name"=>"media_info",
"type"=>"select",
"options"=>$media_info_els,
"size"=>"1",
"value"=>"",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("type"=>"submit",
"name"=>"submit",
"value"=>"Search","extrahtml"=>"class=btn"
));
$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",
"extrahtml"=>"class=span2"
));
$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",
"extrahtml"=>"class=span2"
));
$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"=>"Billing Party","value"=>"UserName"),
array("label"=>"Remote Party Id","value"=>"SipRPID"),
array("label"=>"Caller Party","value"=>"CallingStationId"),
array("label"=>"Destination","value"=>"CalledStationId"),
array("label"=>"Duration","value"=>"AcctSessionTime"),
array("label"=>"Input traffic","value"=>"AcctInputOctets"),
array("label"=>"Output traffic","value"=>"AcctOutputOctets"),
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)) {
$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",
"extrahtml"=>"class=span3"
));
$this->f->add_element(array("name"=>"group_by",
"type"=>"select",
"options"=>$group_by_els,
"value"=>$group_by,
"size"=>"1",
"extrahtml"=>"class=span3"
));
$application_els=array(
array("label"=>"Any Application", "value"=>""),
array("label"=>"Audio", "value"=>"audio"),
array("label"=>"Video", "value"=>"video"),
array("label"=>"Message" , "value"=>"message"),
array("label"=>"IM Chat" , "value"=>"chat"),
array("label"=>"Audio + Chat" , "value"=>"audio=2C chat"),
array("label"=>"File Transfer","value"=>"file-transfer")
);
$this->f->add_element(array("name"=>"application",
"type"=>"select",
"options"=>$application_els,
"value"=>$application,
"size"=>"1",
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("name"=>"UserAgent",
"type"=>"text",
"size"=>"25",
"maxlength"=>"50",
"value"=>$UserAgent,
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("name"=>"SipCodec",
"type"=>"text",
"size"=>"10",
"maxlength"=>"50",
"value"=>$SipCodec,
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("name"=>"sip_proxy",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"value"=>$sip_proxy,
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("name"=>"gateway",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"value"=>$gateway,
"extrahtml"=>"class=span2"
));
$this->f->add_element(array("name"=>"DestinationId",
"type"=>"text",
"size"=>"10",
"extrahtml"=>"class=span3"
));
$this->f->add_element(array( "name"=>"ExcludeDestinations",
"type"=>"text",
"size"=>"20",
"maxlength"=>"255",
"extrahtml"=>"class=span3"
));
$this->f->load_defaults();
$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\""
));
}
function searchForm() {
global $perm;
$this->initForm();
$this->f->start("","POST","","","datasource");
print "";
$this->showDataSources ($this->f);
$this->showDateTimeElements ($this->f);
// freeze some form els
if ($this->CDRTool['filter']['aNumber']) {
$ff[]="a_number";
$ff[]="a_number_comp";
$ff[]="UserName";
$ff[]="UserName_comp";
}
if ($this->CDRTool['filter']['domain']) {
$Realm=$this->CDRTool['filter']['domain'];
$ff[]="Realm";
}
if ($this->CDRTool['filter']['gateway']) {
$gateway=$this->CDRTool['filter']['gateway'];
$ff[]="gateway";
}
if (count($ff)) {
$this->f->freeze($ff);
}
print "
SIP Call Id / Source IP
|
Sip Proxy ";
$this->f->show_element("sip_proxy","");
print "
|
";
print "
User Agent / Media Codecs
|
";
$this->f->show_element("UserAgent","");
print " Codec: ";
$this->f->show_element("SipCodec","");
print "
|
";
print "
SIP Billing Party (Username)
|
";
$this->f->show_element("UserName_comp","");
print "
Tech prefix: ";
$this->f->show_element("BillingId","");
print "
|
";
print "
SIP Caller Party (From URI)
|
";
$this->f->show_element("a_number_comp","");
print " ";
$this->f->show_element("a_number");
print "
|
";
print "
SIP Destination (Canonical URI)
|
";
$this->f->show_element("c_number_comp","");
print " ";
$this->f->show_element("c_number","");
print " Exclude: ";
$this->f->show_element("ExcludeDestinations_comp");
$this->f->show_element("ExcludeDestinations","");
print "
|
";
print "
Application / Call Flow
|
";
$this->f->show_element("flow","");
print " ";
$this->f->show_element("application","");
print " Media Info: ";
$this->f->show_element("media_info","");
print "
|
";
print "
Duration / Status
|
";
$this->f->show_element("duration","");
print " ";
$this->f->show_element("sip_status","");
print " ";
$this->f->show_element("sip_status_class","");
print "
|
";
print "
Order by / Group by
|
";
$this->f->show_element("order_by","");
print " ";
$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 " ";
if (!$perm->have_perm('readonly')) {
print "; ReNormalize ";
print "
";
}
print "
|
";
print "
";
$this->f->show_element("submit","");
$this->f->finish();
print "
";
}
function searchFormSubscriber() {
global $perm;
$this->initForm();
$this->f->start("","POST","","","datasource");
print "
";
$this->showDataSources ($this->f);
$this->showDateTimeElements ($this->f);
// freeze some form els
if ($this->CDRTool['filter']['aNumber']) {
$ff[]="UserName";
}
if ($this->CDRTool['filter']['domain']) {
$ff[]="Realm";
}
if ($this->CDRTool["filter"]["gateway"]) {
$ff[]="gateway";
}
if (count($ff)) {
$this->f->freeze($ff);
}
print "
SIP Caller Party
|
";
$this->f->show_element("a_number","");
print "
|
";
print "
SIP Billing Party
|
";
$this->f->show_element("UserName","");
print "
|
";
print "
SIP Destination
|
";
$this->f->show_element("c_number_comp","");
$this->f->show_element("c_number","");
//$this->f->show_element("DestinationId","");
print "
|
";
print "
SIP Session duration
|
";
$this->f->show_element("duration","");
print " Application ";
$this->f->show_element("application","");
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 "
|
";
print "
";
$this->f->show_element("submit","");
$this->f->finish();
print "
";
}
function show() {
global $perm;
if (!is_object($this->CDRdb)) {
$log=sprintf("Error: CDR database is not initalized");
print $log;
return false;
}
foreach ($this->FormElements as $_el) {
${$_el} = trim($_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);
}
// overwrite some elements based on user rights
if ($this->CDRTool['filter']['gateway']) {
$gateway =$this->CDRTool['filter']['gateway'];
}
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);
}
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);
}
} 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;
$this->url=sprintf("?cdr_source=%s&cdr_table=%s",$this->cdr_source,$cdr_table);
if ($this->CDRTool['filter']['domain']) {
$this->url .= sprintf("&Realms=%s",urlencode($this->CDRTool['filter']['domain']));
$Realms = explode(" ",$this->CDRTool['filter']['domain']);
} else if ($Realms) {
$this->url .= sprintf("&Realms=%s",urlencode($Realms));
$Realms = explode(" ",$Realms);
}
if ($this->CDRTool['filter']['aNumber']) {
$this->url .= sprintf("&UserName=%s",urlencode($this->CDRTool['filter']['aNumber']));
}
if ($this->CDRTool['filter']['after_date']) {
$where .= sprintf(" and %s >= '%s' ",addslashes($this->startTimeField),addslashes($this->CDRTool['filter']['after_date']));
}
if ($order_by) {
$this->url.=sprintf("&order_by=%s&order_type=%s",addslashes($order_by),addslashes($order_type));
}
$this->url.=sprintf("&begin_datetime=%s",urlencode($begin_datetime_timestamp));
$this->url.=sprintf("&end_datetime=%s",urlencode($end_datetime_timestamp));
if (!$call_id && $begin_datetime && $end_datetime) {
$where .= sprintf(" (%s >= '%s' and %s < '%s') ",addslashes($this->startTimeField),addslashes($begin_datetime),addslashes($this->startTimeField), addslashes($end_datetime));
} else {
$where .= sprintf(" (%s >= '1970-01-01' ) ",addslashes($this->startTimeField));
}
if ($MONTHYEAR) {
$where .= sprintf(" and %s like '%s%s' ", addslashes($this->startTimeField), addslashes($MONTHYEAR), '%');
$this->url.= sprintf("&MONTHYEAR=%s",urlencode($MONTHYEAR));
}
if ($flow) {
$this->url.=sprintf("&flow=%s",urlencode($flow));
$where .= sprintf(" and %s = '%s' ", addslashes($this->flowField), addslashes($flow));
}
if ($this->CDRTool['filter']['aNumber']) {
// force user to see only CDRS with his a_numbers
$where .= sprintf(" and ( %s = '%s' or %s = '%s') ",
addslashes($this->usernameField),
addslashes($this->CDRTool['filter']['aNumber']),
addslashes($this->CanonicalURIField),
addslashes($this->CDRTool['filter']['aNumber'])
);
$UserName_comp='equal';
$UserName=$this->CDRTool['filter']['aNumber'];
}
if ($UserName_comp == "empty") {
$where .= sprintf(" and %s = ''", addslashes($this->usernameField));
$this->url.=sprintf("&UserName_comp=%s",urlencode($UserName_comp));
} else if (strlen($UserName) && !$this->CDRTool['filter']['aNumber']) {
if (!$UserName_comp) $UserName_comp='begin';
if ($UserName_comp=="begin") {
$where .= sprintf(" and %s like '%s%s'", addslashes($this->usernameField), addslashes($UserName), '%');
} elseif ($UserName_comp=="contain") {
$where .= sprintf(" and %s like '%s%s%s'", addslashes($this->usernameField), '%', addslashes($UserName), '%');
} elseif ($UserName_comp=="equal") {
$where .= sprintf(" and %s = '%s'", addslashes($this->usernameField), addslashes($UserName));
} else {
$where .= sprintf(" and %s = ''", addslashes($this->usernameField));
}
$this->url.=sprintf("&UserName=%s&UserName_comp=%s",urlencode($UserName),$UserName_comp);
}
$a_number=trim($a_number);
if ($a_number_comp == "empty") {
$where .= sprintf(" and %s = ''", addslashes($this->aNumberField));
$this->url.=sprintf("&a_number_comp=%s",urlencode($a_number_comp));
} else if (strlen($a_number)) {
$a_number=urldecode($a_number);
if (!$a_number_comp) $a_number_comp="equal";
$this->url.=sprintf("&a_number=%s",urlencode($a_number));
if ($a_number_comp=="begin") {
$where .= sprintf(" and %s like '%s%s'", addslashes($this->aNumberField), addslashes($a_number), '%');
} elseif ($a_number_comp=="contain") {
$where .= sprintf(" and %s like '%s%s%s'", addslashes($this->aNumberField), '%', addslashes($a_number), '%');
} elseif ($a_number_comp=="equal") {
$where .= sprintf(" and %s = '%s'", addslashes($this->aNumberField), addslashes($a_number));
}
$this->url.=sprintf("&a_number_comp=%s",urlencode($a_number_comp));
}
$c_number=trim($c_number);
if ($c_number_comp == "empty") {
$where .= sprintf(" and %s = ''", addslashes($this->CanonicalURIField));
$this->url.=sprintf("&c_number_comp=%s",urlencode($c_number_comp));
} else if (strlen($c_number)) {
$c_number=urldecode($c_number);
if (!$c_number_comp) $c_number_comp="begin";
if (!$c_number_comp || $c_number_comp=="begin") {
$where .= sprintf(" and %s like '%s%s'", addslashes($this->CanonicalURIField), addslashes($c_number), '%');
} elseif ($c_number_comp=="contain") {
$where .= sprintf(" and %s like '%s%s%s'", addslashes($this->CanonicalURIField), '%', addslashes($c_number), '%');
} elseif ($c_number_comp=="equal") {
$where .= sprintf(" and %s = '%s'", addslashes($this->CanonicalURIField), addslashes($c_number));
}
$this->url.=sprintf("&c_number=%s&c_number_comp=%s",urlencode($c_number),urlencode($c_number_comp));
}
$Realm=trim($Realm);
if ($Realms) {
$where .= sprintf("and %s in (",$this->domainField);
foreach ($Realms as $realm) {
$where .= sprintf("'%s',",addslashes($realm));
}
$where=rtrim($where, ",");
$where .= ") ";
} else if ($Realm) {
$Realm=urldecode($Realm);
$where .= sprintf(" and %s like '%s' ", $this->domainField, addslashes($Realm));
$this->url.=sprintf("&Realm=%s",urlencode($Realm));
}
$BillingId=trim($BillingId);
if (preg_match("/^\d+$/",$BillingId) && $this->BillingIdField) {
$where .= " and $this->BillingIdField = '".addslashes($BillingId)."'";
$this->url.=sprintf("&BillingId=%s",urlencode($BillingId));
}
if ($application) {
$where .= " and $this->applicationField like '%".addslashes($application)."%'";
$this->url.=sprintf("&application=%s",urlencode($application));
}
if ($DestinationId) {
if ($DestinationId=="empty") {
$DestinationIdSQL="";
} else {
$DestinationIdSQL=$DestinationId;
}
$where .= " and $this->DestinationIdField = '".addslashes($DestinationIdSQL)."'";
$this->url.=sprintf("&DestinationId=%s",urlencode($DestinationId));
}
if (strlen(trim($ExcludeDestinations))) {
$ExcludeDestArray=explode(" ",trim($ExcludeDestinations));
foreach ($ExcludeDestArray as $exclDst) {
if (preg_match("/^0+(\d+)$/",$exclDst,$m)) {
$exclDest_id=$m[1];
} else {
$exclDest_id=$exclDst;
}
$where .= " and ".
$this->CanonicalURIField.
" not like '".
addslashes(trim($exclDst)).
"'";
}
$this->url.=sprintf("&ExcludeDestinations=%s",urlencode($ExcludeDestinations));
}
$call_id=trim($call_id);
if ($call_id) {
$call_id=urldecode($call_id);
$where .= " and $this->callIdField = '".addslashes($call_id)."'";
$this->url.=sprintf("&call_id=%s",urlencode($call_id));
}
if ($sip_proxy) {
$sip_proxy=urldecode($sip_proxy);
$where .= " and $this->SipProxyServerField = '".addslashes($sip_proxy)."'";
$this->url.=sprintf("&sip_proxy=%s",urlencode($sip_proxy));
}
if ($SipCodec) {
$this->url.=sprintf("&SipCodec=%s",urlencode($SipCodec));
if ($SipCodec != "empty") {
$where .= " and $this->SipCodecField = '".addslashes($SipCodec)."'";
} else {
$where .= " and $this->SipCodecField = ''";
}
}
if ($SipRPID) {
$this->url.=sprintf("&SipRPID=%s",urlencode($SipRPID));
if ($SipRPID != "empty") {
$where .= " and $this->SipRPIDField = '".addslashes($SipRPID)."'";
} else {
$where .= " and $this->SipRPIDField = ''";
}
}
if ($UserAgent) {
$where .= " and $this->UserAgentField like '%".addslashes($UserAgent)."%'";
$this->url.=sprintf("&UserAgent=%s",urlencode($UserAgent));
}
if (strlen($sip_status)) {
$where .= " and $this->disconnectField ='".addslashes($sip_status)."'";
$this->url.=sprintf("&sip_status=%s",urlencode($sip_status));
}
if ($sip_status_class) {
$where .= " and $this->disconnectField like '$sip_status_class%'";
$this->url.=sprintf("&sip_status_class=%s",urlencode($sip_status_class));
}
if ($this->CDRTool[filter]["gateway"]) {
$gatewayFilter=$this->CDRTool[filter]["gateway"];
$where .= " and $this->gatewayField = '".addslashes($gatewayFilter)."'";
} else if ($gateway) {
$gateway=urldecode($gateway);
$where .= " and $this->gatewayField = '".addslashes($gateway)."'";
$this->url.=sprintf("&gateway=%s",urlencode($gateway));
}
if ($duration) {
if (preg_match("/\d+/",$duration) ) {
$where .= " and ($this->durationField > 0 and $this->durationField $duration) ";
} elseif (preg_match("/onehour/",$duration) ) {
$where .= " and ($this->durationField < 3610 and $this->durationField > 3530) ";
} elseif ($duration == "zero") {
$where .= " and $this->durationField = 0";
} elseif ($duration == "zeroprice" && $this->priceField) {
$where .= " and $this->durationField > 0 and ($this->priceField = '' or $this->priceField is NULL)";
$mongo_where[$this->priceField] = '';
} elseif ($duration == "nonzero") {
$where .= " and $this->durationField > 0";
} elseif ($duration == "onewaymedia") {
$where .= " and (($this->inputTrafficField > 0 && $this->outputTrafficField = 0) || ($this->inputTrafficField = 0 && $this->outputTrafficField > 0)) " ;
} elseif ($duration == "nomedia") {
$where .= " and ($this->inputTrafficField = 0 && $this->outputTrafficField = 0) " ;
}
$this->url.=sprintf("&duration=%s",urlencode($duration));
}
if ($media_info) {
$this->url.=sprintf("&media_info=%s",urlencode($media_info));
$where .= sprintf(" and %s = '%s' ",addslashes($this->MediaInfoField), addslashes($media_info));
}
$this->url.=sprintf("&maxrowsperpage=%s",addslashes($this->maxrowsperpage));
$url_calls = $this->scriptFile.$this->url."&action=search";
if ($group_by) {
$this->url.=sprintf("&group_by=%s",urlencode($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 ($duration == "unnormalized") {
$where .= " and $this->normalizedField = '0' ";
}
if ($duration == "unnormalized_duration") {
$where .= " and $this->normalizedField = '0' and $this->durationField > 0 ";
}
if ($group_by) {
$this->group_byOrig=$group_by;
if ($group_by=="hour") {
$group_by="HOUR(AcctStartTime)";
} else if (preg_match("/^DAY/",$group_by)) {
$group_by="$group_by(AcctStartTime)";
} else if (preg_match("/BYMONTH/",$group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y-%m')";
} else if (preg_match("/BYYEAR/",$group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y')";
} else if ($group_by=="UserAgentType") {
$group_by="SUBSTRING_INDEX($this->SipUserAgentsField, ' ', '1')";
}
$this->group_by=$group_by;
if ($group_by==$this->callIdField) {
$having=sprintf(" having count(%s) > 1 ", addslashes($group_by));
}
$query= sprintf("select sum(%s) as duration, SEC_TO_TIME(sum(%s)) as duration_print, count(%s) as calls, %s from %s where %s group by %s %s ",
addslashes($this->durationField),
addslashes($this->durationField),
$group_by,
$group_by,
addslashes($cdr_table),
$where,
$group_by,
$having
);
} else {
$query = sprintf("select count(*) as records from %s where ", addslashes($cdr_table)). $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 {
printf ("%s",$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=intval($this->next);
}
$j=0;
$z=0;
if ($rows>0) {
if ($call_id && $ReNormalize) {
$query=sprintf("update %s
set %s = '0'
where %s = '%s'",
addslashes($cdr_table),
addslashes($this->normalizedField),
addslashes($this->callIdField),
addslashes($call_id)
);
$this->CDRdb->query($query);
}
if ($UnNormalizedCalls=$this->getUnNormalized($where,$cdr_table)) {
if (!$this->DATASOURCES[$this->cdr_source]['skipNormalizeOnPageLoad']) {
if ($UnNormalizedCalls < $this->maxCDRsNormalizeWeb) {
$this->NormalizeCDRS($where,$cdr_table);
if (!$this->export && $this->status['normalized'] ) {
print "";
print " ";
printf ("%d CDRs normalized. ",$this->status['normalized']);
if ($this->status['cached_keys']['saved_keys']) {
printf ("Quota usage updated for %d accounts. ",$this->status['cached_keys']['saved_keys']);
}
print "
";
}
}
}
}
if ($rows > $this->maxrowsperpage) {
$maxrows=$this->maxrowsperpage+$this->next;
if ($maxrows > $rows) {
$maxrows=$rows;
$prev_rows=$maxrows;
}
} else {
$maxrows=$rows;
}
if ($duration == "unnormalized") {
// if display un normalized calls we must substract
// the amount of calls normalized above
$maxrows=$maxrows-$this->status['normalized'];
}
if ($group_by) {
if ($order_by=="group_by") {
$order_by1=$group_by;
} else {
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";
}
}
$this->SipMethodField=$this->CDRFields['SipMethod'];
$query= "
select sum($this->durationField) as $this->durationField,
SEC_TO_TIME(sum($this->durationField)) as hours,
count($group_by) as calls,
$this->SipMethodField,
2*sum($this->inputTrafficField)/1024/1024 as $this->inputTrafficField,
2*sum($this->outputTrafficField)/1024/1024 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.="
sum($this->inputTrafficField)*8*2/1024/sum($this->durationField) as netrate_in,
sum($this->outputTrafficField)*8*2/1024/sum($this->durationField) as netrate_out
";
if ($this->priceField) {
$query.= ", sum($this->priceField) as $this->priceField ";
}
$_max_rows = intval($this->maxrowsperpage);
if (!$_max_rows) {
$_max_rows = 10;
}
/*
$query.= "
, $group_by as mygroup
from $cdr_table
where $where
group by $group_by
$having
order by $order_by1 $order_type
limit $i,$_max_rows
";
*/
$query.= sprintf(", %s as mygroup from %s
where %s
group by %s
%s
order by %s %s
limit %d, %d
", $group_by, addslashes($cdr_table), $where, $group_by, addslashes($having), addslashes($order_by1), addslashes($order_type), $i, $_max_rows);
dprint($query);
$this->CDRdb->query($query);
$this->showTableHeaderStatistics();
while ($i<$maxrows) {
$found=$i+1;
$this->CDRdb->next_record();
$calls = $this->CDRdb->f('calls');
$seconds = $this->CDRdb->f($this->durationField);
$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');
$AcctInputOctets = number_format($this->CDRdb->f($this->inputTrafficField),2,".","");
$AcctOutputOctets = number_format($this->CDRdb->f($this->outputTrafficField),2,".","");
$NetRateIn = $this->CDRdb->f('netrate_in');
$NetRateOut = $this->CDRdb->f('netrate_out');
$SipMethod = $this->CDRdb->f($this->callTypeField);
$AcctTerminateCause = $this->CDRdb->f($this->disconnectField);
$mygroup = $this->CDRdb->f('mygroup');
$zero = $this->CDRdb->f('zero');
$nonzero = $this->CDRdb->f('nonzero');
$success = number_format($nonzero/$calls*100,2,".","");
$failure = number_format($zero/$calls*100,2,".","");
$NetworkRateIn = number_format($NetRateIn,2);
$NetworkRateOut = number_format($NetRateOut,2);
$NetworkRate = max($NetworkRateIn,$NetworkRateOut);
if ($this->priceField) {
$price = $this->CDRdb->f($this->priceField);
}
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
$traceValue="";
$mygroup_print=quoted_printable_decode($mygroup);
if ($this->group_byOrig==$this->DestinationIdField) {
if ($this->CDRTool['filter']['domain'] && $this->destinations[$this->CDRTool['filter']['domain']]) {
list($_dst_id,$_dst_name)=$this->getPSTNDestinationId($mygroup,'',$this->CDRTool['filter']['domain']);
$description=$_dst_name;
} else {
$description=$this->destinations[0]["default"][$mygroup]["name"];
//list($_dst_id,$_dst_name)=$this->getPSTNDestinationId($mygroup);
//$description=$_dst_name;
}
if ($mygroup) {
$traceValue=$mygroup;
} else {
$traceValue="empty";
}
} else if ($this->group_byOrig==$this->aNumberField) {
# Normalize Called Station Id
$N=$this->NormalizeNumber($mygroup);
$mygroup_print=$N['username']."@".$N[domain];
$description="";
$traceField="a_number";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->CanonicalURIField) {
$traceField="c_number";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->SipProxyServerField) {
$traceField="sip_proxy";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->SipCodecField) {
$traceField="SipCodec";
} else if (preg_match("/UserAgent/",$this->group_byOrig)) {
$traceField="UserAgent";
} else if (preg_match("/^BY/",$this->group_byOrig)) {
$traceField="MONTHYEAR";
} else if ($this->group_byOrig==$this->callIdField) {
$traceField="call_id";
} else if ($this->group_byOrig=="DAYOFWEEK") {
if ($mygroup == "1") {
$description="Sunday";
} else if ($mygroup == "2") {
$description="Monday";
} else if ($mygroup == "3") {
$description="Tuesday";
} else if ($mygroup == "4") {
$description="Wednesday";
} else if ($mygroup == "5") {
$description="Thursday";
} else if ($mygroup == "6") {
$description="Friday";
} else if ($mygroup == "7") {
$description="Saturday";
}
} else if ($this->group_byOrig=="DAYOFMONTH") {
$description =$this->CDRdb->f('day');
} else if ($this->group_byOrig=="DAYOFYEAR") {
$description =$this->CDRdb->f('day');
} else if ($this->group_byOrig=="SourceIP") {
$traceField="gateway";
} else if ($this->group_byOrig=="SipResponseCode") {
$description =$this->disconnectCodesDescription[$mygroup];
$traceField="sip_status";
} else if ($this->group_byOrig=="SipApplicationType") {
$traceField="application";
} else if ($this->group_byOrig=="ServiceType") {
$traceField="flow";
} else {
$description="";
}
if (!$traceField) {
$traceField = $group_by;
}
if (!$traceValue) {
$traceValue = $mygroup;
}
if (!$traceValue) {
$traceValue="";
$comp_type="empty";
} else {
$comp_type="begin";
}
$traceValue_enc=urlencode($traceValue);
if (!$this->export) {
print "
$found |
$calls |
$seconds_print |
$minutes_print |
$hours |
";
if ($perm->have_perm("showPrice")) {
$pricePrint=number_format($price,4,".","");
} else {
$pricePrint='x.xxx';
}
print "
$pricePrint |
$AcctInputOctets |
$AcctOutputOctets |
$success% |
($nonzero calls) |
$failure% |
($zero calls) |
$mygroup_print |
$description |
";
printf("Display calls | ",$url_calls,$traceField,$traceValue_enc,$traceField,$comp_type);
print "
";
} else {
print "$found,";
print "$calls,";
print "$seconds,";
print "$minutes,";
print "$hours,";
if ($perm->have_perm("showPrice")) {
$pricePrint=$price;
} else {
$pricePrint='x.xxx';
}
print "$pricePrint,";
print "$AcctInputOctets,";
print "$AcctOutputOctets,";
print "$success,";
print "$nonzero,";
print "$failure,";
print "$zero,";
print "$mygroup_print,";
print "$description";
print "\n";
}
$i++;
}
if (!$this->export) {
print "
";
}
} else {
if (!$this->export) {
// printf (" For more information about each call click on its Id column.
");
}
if ($order_by=="zeroP" || $order_by=="nonzeroP") {
$order_by="timestamp";
}
$_max_rows = intval($this->maxrowsperpage);
if (!$_max_rows) {
$_max_rows = 10;
}
$query=sprintf("select *, UNIX_TIMESTAMP($this->startTimeField) as timestamp
from %s where %s order by %s %s limit %d, %d",
addslashes($cdr_table),
$where,
addslashes($order_by),
addslashes($order_type),
intval($i),
$_max_rows
);
$this->CDRdb->query($query);
if ($this->CDRTool['filter']['aNumber']) {
$this->showTableHeaderSubscriber();
} else {
if (!$this->export) {
$this->showTableHeader();
} else {
$this->showExportHeader();
}
}
while ($i<$maxrows) {
global $found;
$found=$i+1;
$this->CDRdb->next_record();
$Structure=$this->_readCDRFieldsFromDB('');
//dprint_r($Structure);
$CDR = new $this->CDR_class($this, $Structure);
if ($this->CDRTool['filter']['aNumber']) {
$CDR->showSubscriber();
} else {
if (!$this->export) {
$CDR->show();
} else {
$CDR->export();
}
}
$i++;
}
if (!$this->export) {
print "
";
}
}
$this->showPagination($this->next,$maxrows);
}
}
function LoadDomains() {
if (!$this->db_subscribers) {
$log=printf("Error: Cannot load domains because db_subscribers is not defined in datasource %s",$this->cdr_source);
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
if (!is_object($this->AccountsDB)) {
$log=printf("Error: AccountsDB is not a valid database object");
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
if (strlen($this->DATASOURCES[$this->cdr_source]['enableThor'])) {
$this->domain_table = "sip_domains";
} else {
$this->domain_table = "domain";
}
$query=sprintf("select * from %s",$this->domain_table);
if ($this->CDRTool['filter']['aNumber']) {
$els=explode("@",$this->CDRTool['filter']['aNumber']);
$query.= sprintf(" where domain = '%s' ", addslashes($els[1]));
} else if ($this->CDRTool['filter']['domain']) {
$fdomain=$this->CDRTool['filter']['domain'];
$query.=sprintf(" where domain = '%s' ", addslashes($fdomain));
}
if (!$this->AccountsDB->query($query)) {
$log=sprintf ("Database %s error: %s (%d) %s\n",$this->db_subscribers,$this->AccountsDB->Error,$this->AccountsDB->Errno,$query);
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
while($this->AccountsDB->next_record()) {
if ($this->AccountsDB->f('domain')) {
$this->localDomains[$this->AccountsDB->f('domain')]=array('name' => $this->AccountsDB->f('domain'),
'reseller' => intval($this->AccountsDB->f('reseller_id'))
);
}
}
return count($this->localDomains);
}
function LoadTrustedPeers() {
if (!$this->db_subscribers) {
$log=printf("Error: Cannot load trusted peers because db_subscribers is not defined in datasource %s",$this->cdr_source);
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
if (!is_object($this->AccountsDB)) {
$log=printf("Error: AccountsDB is not a valid database object");
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
if (strlen($this->DATASOURCES[$this->cdr_source]['enableThor'])) {
$this->trusted_table = "sip_trusted";
} else {
$this->trusted_table = "trusted_peers";
}
$query=sprintf("select * from %s",addslashes($this->trusted_table));
if (!$this->AccountsDB->query($query)) {
$log=sprintf ("Database %s error: %s (%d) %s\n",$this->db_subscribers,$this->AccountsDB->Error,$this->AccountsDB->Errno,$query);
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
while($this->AccountsDB->next_record()) {
if ($this->AccountsDB->f('ip')) {
$this->trustedPeers[$this->AccountsDB->f('ip')]=array('ip' => $this->AccountsDB->f('ip'),
'reseller' => intval($this->AccountsDB->f('reseller_id'))
);
}
}
return count($this->trustedPeers);
}
function getQuota($account) {
if (!$this->quotaEnabled) return true;
if (!$account) return;
if (!is_object($this->AccountsDB)) {
$log=printf("Error: AccountsDB is not a valid database object");
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
list($username,$domain) = explode("@",$account);
if ($this->enableThor) {
$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 1 %s: %s (%s)",$query,$this->AccountsDB->Error,$this->AccountsDB->Errno);
syslog(LOG_NOTICE,$log);
return 0;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
return $_profile->quota;
} else {
return 0;
}
} else {
$query=sprintf("select quota from subscriber 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 0;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
return $this->AccountsDB->f('quota');
} else {
return 0;
}
}
}
function getBlockedByQuotaStatus($account) {
if (!$this->quotaEnabled) return true;
if (!$account) return 0;
if (!is_object($this->AccountsDB)) {
$log=printf("Error: AccountsDB is not a valid database object");
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
list($username,$domain) = explode("@",$account);
if ($this->enableThor) {
$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 query2 %s: %s (%s)",$query,$this->AccountsDB->Error,$this->AccountsDB->Errno);
syslog(LOG_NOTICE,$log);
return 0;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
if (in_array('quota',$_profile->groups)) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
} else {
$query=sprintf("select CONCAT(username,'@',domain) as account from grp where grp = 'quota' and 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 0;
}
if ($this->AccountsDB->num_rows()) {
return 1;
} else {
return 0;
}
}
return 0;
}
function notifyLastSessions($count='200',$account='') {
// send emails with last missed and received sessions to subscribers in group $this->missed_calls_group
$lockName=sprintf("%s:notifySessions",$this->cdr_source);
if (!$this->getNormalizeLock($lockName)) {
return true;
}
if (strlen($account)) {
list($username,$domain)=explode('@',$account);
if (!strlen($username) || !strlen($domain)) return false;
} else {
$query=sprintf("select * from memcache where `key` = '%s'",'notifySessionsLastRun');
$this->cdrtool->query($query);
if ($this->cdrtool->num_rows()) {
$this->cdrtool->next_record();
$lastRun=$this->cdrtool->f('value');
if (Date('Y-m-d') == $lastRun) {
$log=sprintf("Notify sessions script already run for date %s\n",$lastRun);
print $log;
syslog(LOG_NOTICE,$log);
return true;
}
}
}
$this->notifySubscribers=array();
require_once('Mail.php');
require_once('Mail/mime.php');
if ($this->enableThor) {
$query=sprintf("select * from sip_accounts");
if (strlen($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 0;
}
if ($this->AccountsDB->num_rows()) {
while ($this->AccountsDB->next_record()) {
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
if (in_array($this->missed_calls_group,$_profile->groups)) {
$this->notifySubscribers[$this->AccountsDB->f('username').'@'.$this->AccountsDB->f('domain')]=array('email'=>$this->AccountsDB->f('email'),'timezone' => $_profile->timezone);
}
}
} else {
return 0;
}
} else {
$query=sprintf("select CONCAT(username,'@',domain) as account,email_address,timezone from grp join subscriber on grp.subscriber_id =subscriber.id where grp = '%s'",
addslashes($this->missed_calls_group));
if (strlen($account)) {
$query.= sprintf (" and username = '%s' and domain = '%s' ",$username,$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 0;
}
if ($this->AccountsDB->num_rows()) {
while ($this->AccountsDB->next_record()) {
$this->notifySubscribers[$this->AccountsDB->f('account')]=array('email'=>$this->AccountsDB->f('email_address'),'timezone' => $this->AccountsDB->f('timezone'));
}
} else {
return 0;
}
}
if (!count($this->notifySubscribers)) return 0;
$j=0;
foreach (array_keys($this->notifySubscribers) as $_subscriber) {
$j++;
$_last_sessions=array();
unset($textBody);
unset($htmlBody);
$query = sprintf("SELECT *, UNIX_TIMESTAMP(%s) as timestamp FROM %s where (%s = '%s' or %s = '%s') and %s > DATE_ADD(NOW(), INTERVAL -1 day) order by %s desc limit 200",
addslashes($this->startTimeField),
addslashes($this->table),
addslashes($this->usernameField),
addslashes($_subscriber),
addslashes($this->CanonicalURIField),
addslashes($_subscriber),
addslashes($this->startTimeField),
addslashes($this->startTimeField)
);
if (!$this->CDRdb->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
if (Date('d')== 1) {
while ($this->CDRdb->next_record()) {
$_last_sessions[]=array('duration' => $this->CDRdb->f($this->durationField),
'from' => $this->CDRdb->f($this->aNumberField),
'to' => $this->CDRdb->f($this->cNumberField),
'username' => $this->CDRdb->f($this->usernameField),
'canonical' => $this->CDRdb->f($this->CanonicalURIField),
'date' => getlocaltime($this->notifySubscribers[$_subscriber]['timezone'],$this->CDRdb->f('timestamp'))
);
}
if (preg_match("/^(\w+)(\d{4})(\d{2})$/",$this->table,$m)) {
$previousTable=$m[1].date('Ym', mktime(0, 0, 0, $m[3]-1, "01", $m[2]));
$query = sprintf("SELECT *, UNIX_TIMESTAMP(%s) as timestamp FROM %s where %s = '%s' and %s > DATE_ADD(NOW(), INTERVAL -1 day) order by %s desc limit 200",
addslashes($this->startTimeField),
addslashes($previousTable),
addslashes($this->CanonicalURIField),
addslashes($_subscriber),
addslashes($this->startTimeField),
addslashes($this->startTimeField)
);
if (!$this->CDRdb->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
while ($this->CDRdb->next_record()) {
$_last_sessions[]=array('duration' => $this->CDRdb->f($this->durationField),
'from' => $this->CDRdb->f($this->aNumberField),
'to' => $this->CDRdb->f($this->cNumberField),
'username' => $this->CDRdb->f($this->usernameField),
'canonical' => $this->CDRdb->f($this->CanonicalURIField),
'date' => getlocaltime($this->notifySubscribers[$_subscriber]['timezone'],$this->CDRdb->f('timestamp'))
);
}
}
} else {
while ($this->CDRdb->next_record()) {
$_last_sessions[]=array('duration' => $this->CDRdb->f($this->durationField),
'from' => $this->CDRdb->f($this->aNumberField),
'to' => $this->CDRdb->f($this->cNumberField),
'username' => $this->CDRdb->f($this->usernameField),
'canonical' => $this->CDRdb->f($this->CanonicalURIField),
'date' => getlocaltime($this->notifySubscribers[$_subscriber]['timezone'],$this->CDRdb->f('timestamp'))
);
}
}
if (!count($_last_sessions)) continue;
$sessions=array('missed' => array(),
'received' => array(),
'diverted' => array()
);
$have_sessions=0;
foreach ($_last_sessions as $_s) {
if ($_s['duration'] == 0 && $_s['canonical'] == $_subscriber) {
$sessions['missed'][]=$_s;
$have_sessions++;
continue;
}
if ($_s['duration'] > 0 && $_s['canonical'] == $_subscriber) {
$sessions['received'][]=$_s;
$have_sessions++;
continue;
}
if ($_s['from'] != $_subscriber && $_s['canonical'] != $_subscriber) {
$sessions['diverted'][]=$_s;
$have_sessions++;
continue;
}
}
if (!$have_sessions) continue;;
if (count($sessions['missed'])) {
// missed sessions
$textBody .= sprintf ("Missed sessions\n\n
Id,Date,From,Duration\n
");
$htmlBody .= sprintf ("Missed Calls
|
Date and Time
|
Caller
|
");
$i=0;
foreach ($sessions['missed'] as $_session) {
$i++;
if ($i >= $count) break;
$htmlBody.=sprintf ("%s | %s | sip:%s |
",
$i,
$_session['date'],
$_session['from'],
$_session['from']
);
$txtBody.=sprintf ("%s,%s,%s,%s,%s\n",
$i,
$_session['date'],
$_session['from'],
$_session['to']
);
}
$htmlBody.="
";
}
if (count($sessions['diverted'])) {
// diverted sessions
$textBody .= sprintf ("Diverted Calls\n\n
Id,Date,From,Diverted to\n
");
$htmlBody .= sprintf ("Diverted Calls
|
Date and Time
|
Caller
|
Diverted to
|
");
$i=0;
foreach ($sessions['diverted'] as $_session) {
$i++;
if ($i >= $count) break;
$htmlBody.=sprintf ("%s | %s | sip:%s | %s |
",
$i,
$_session['date'],
$_session['from'],
$_session['from'],
$_session['canonical']
);
$txtBody.=sprintf ("%s,%s,%s,%s\n",
$i,
$_session['date'],
$_session['from'],
$_session['canonical']
);
}
$htmlBody.="
";
}
if (count($sessions['received'])) {
// received sessions
$textBody .= sprintf ("Received Calls\n\n
Id,Date,From,Duration\n");
$htmlBody .= sprintf ("Received Calls
|
Date and Time
|
Caller
|
Duration
|
");
$i=1;
foreach ($sessions['received'] as $_session) {
if ($i >= $count) break;
$htmlBody.=sprintf ("%s | %s | sip:%s | %s |
",
$i,
$_session['date'],
$_session['from'],
$_session['from'],
$_session['duration']
);
$txtBody.=sprintf ("%s,%s,%s,%s\n",
$i,
$_session['date'],
$_session['from'],
$_session['duration']
);
$i++;
}
$htmlBody.="
";
}
$htmlBody.="This is an automatically generated message, do not reply.";
$txtBody.="\nThis is an automatically generated message, do not reply.\n";
$crlf = "\n";
$hdrs = array(
'From'=> $this->CDRTool['provider']['fromEmail'],
'Subject' => sprintf("Incoming Calls for %s on %s",$_subscriber,date('Y-m-d'))
);
$mime = new Mail_mime($crlf);
$mime->setTXTBody($textBody);
$mime->setHTMLBody($htmlBody);
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
$mail->send($this->notifySubscribers[$_subscriber]['email'], $hdrs, $body);
$log=sprintf("Notify %s at %s with last %d sessions\n",
$_subscriber,
$this->notifySubscribers[$_subscriber]['email'],
count($_last_sessions));
print $log;
syslog(LOG_NOTICE,$log);
}
$query=sprintf("update memcache set `value` = '%s' where `key` = '%s'",Date('Y-m-d'),'notifySessionsLastRun');
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->affected_rows()) {
$query=sprintf("insert into memcache (`value`,`key`) values ('%s','%s')",Date('Y-m-d'),'notifySessionsLastRun');
if (!$this->cdrtool->query($query)) {
if ($this->cdrtool->Errno != 1062) {
$log=sprintf("Database error for query %s: %s (%s)",$query,$this->cdrtool->Error,$this->cdrtool->Errno);
print $log;
syslog(LOG_NOTICE,$log);
return false;
}
}
}
}
function getCallerId($account) {
if (!$account) {
return NULL;
}
if ($this->callerid_cache[$account]) {
return $this->callerid_cache[$account];
}
list($username,$domain) = explode('@',$account);
if ($this->enableThor) {
$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 NULL;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
$this->callerid_cache[$account]=$_profile->rpid;
return $_profile->rpid;
}
} else {
$query=sprintf("select rpid from subscriber 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 NULL;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$rpid = $this->AccountsDB->f('rpid');
$this->callerid_cache[$account]=$rpid;
return $rpid;
}
}
return NULL;
}
function rate_on_net_enabled($username, $domain) {
if ($this->enableThor) {
$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()) {
while ($this->AccountsDB->next_record()) {
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
if (in_array($this->rate_on_net_group,$_profile->groups)) {
return true;
}
}
}
}
return false;
}
}
class CDR_opensips extends CDR {
function CDR_opensips($parent, $CDRfields) {
$this->CDRS = $parent;
$this->cdr_source = $this->CDRS->cdr_source;
foreach (array_keys($this->CDRS->CDRFields) as $field) {
$this->$field = $CDRfields[$this->CDRS->CDRFields[$field]];
}
if ($this->CanonicalURI) {
$this->CanonicalURI = quoted_printable_decode($this->CanonicalURI);
}
if ($this->RemoteAddress) {
$this->RemoteAddress = quoted_printable_decode($this->RemoteAddress);
}
if ($this->BillingPartyId) {
$this->BillingPartyId = quoted_printable_decode($this->BillingPartyId);
}
if ($this->aNumber) {
$this->aNumber = quoted_printable_decode($this->aNumber);
}
if ($this->cNumber) {
$this->cNumber = quoted_printable_decode($this->cNumber);
}
if ($this->SipRPID) {
$this->SipRPID = quoted_printable_decode($this->SipRPID);
}
$this->buildMongoCDR();
if (!$this->application && $this->SipMethod) {
$_method=strtolower($this->SipMethod);
if ($_method == 'message') {
$this->application = 'message';
$this->stopTimeNormalized=$this->startTime;
} else {
$this->application = 'audio';
}
}
if ($this->application == 'message') {
$this->stopTimeNormalized=$this->startTime;
}
$this->application=strtolower($this->application);
$this->application_print=quoted_printable_decode($this->application);
$this->FromHeaderPrint = quoted_printable_decode($this->FromHeader);
if (strstr($this->FromHeaderPrint,';')) {
$_els=explode(";",$this->FromHeaderPrint);
$this->FromHeaderPrint=$_els[0];
}
$this->FromHeaderPrint = htmlentities($this->FromHeaderPrint);
$this->UserAgentPrint = quoted_printable_decode($this->UserAgent);
$app_prefix = preg_replace('/[.].*$/', '', $this->application);
if (!in_array($app_prefix, $this->supportedApplicationTypes)) {
$log=sprintf("Changing application from %s to %s\n", $this->application, $this->defaultApplicationType);
syslog(LOG_NOTICE,$log);
$this->application = $this->defaultApplicationType;
}
//$this->applicationNormalized=$this->application;
if ($this->aNumber) {
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->aNumber,"source");
$this->aNumberPrint = $NormalizedNumber['NumberPrint'];
$this->aNumberNormalized = $NormalizedNumber['Normalized'];
$this->aNumberUsername = $NormalizedNumber['username'];
$this->aNumberDomain = $NormalizedNumber['domain'];
}
if (!$this->BillingPartyId || $this->BillingPartyId == 'n/a') {
$this->BillingPartyId=$this->aNumberPrint;
}
$this->ResellerId=0;
// calculate reseller
$_billing_party_els=explode("@",$this->BillingPartyId);
if ($this->isBillingPartyLocal()) {
$this->ResellerId = $this->CDRS->localDomains[$_billing_party_els[1]]['reseller'];
} else {
if (!strlen($_billing_party_els[0])) $this->BillingPartyId=$_billing_party_els[1];
if (count($_billing_party_els)==2) {
if (!$this->domain) $this->domain=$_billing_party_els[1];
if ($this->CDRS->localDomains[$_billing_party_els[1]]['reseller']) {
$this->ResellerId = $this->CDRS->localDomains[$_billing_party_els[1]]['reseller'];
} else if ($this->CDRS->trustedPeers[$_billing_party_els[1]]['reseller']) {
$this->ResellerId = $this->CDRS->trustedPeers[$_billing_party_els[1]]['reseller'];
}
} else if (count($_billing_party_els)==1) {
$this->ResellerId=$this->CDRS->trustedPeers[$_billing_party_els[0]]['reseller'];
}
}
if (!strlen($this->ResellerId)) {
$this->ResellerId = 0;
}
$this->BillingPartyId=strtolower($this->BillingPartyId);
$this->BillingPartyIdPrint=$this->BillingPartyId;
$this->domainNormalized = $this->domain;
if (is_array($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation_SourceIP']) &&
isset($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation_SourceIP'][$this->SourceIP]) &&
strlen($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation_SourceIP'][$this->SourceIP])) {
$this->domainNormalized=$this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation_SourceIP'][$this->SourceIP];
} else if (is_array($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation']) &&
isset($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation'][$this->domain]) &&
strlen($this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation'][$this->domain])) {
$this->domainNormalized=$this->CDRS->DATASOURCES[$this->cdr_source]['domainTranslation'][$this->domain];
}
$this->domainNormalized=strtolower($this->domainNormalized);
$this->RemoteAddressPrint=quoted_printable_decode($this->RemoteAddress);
$_timestamp_stop=$this->timestamp+$this->duration;
$this->dayofweek = date("w",$this->timestamp);
$this->hourofday = date("G",$this->timestamp);
$this->dayofyear = date("Y-m-d",$this->timestamp);
// Called Station ID or cNumber should not be used for rating purposes because
// it is chosen by the subscriber but the Proxy rewrites it into a different
// final destination (the Canonical URI)
// Canonical URI is the final logical SIP destination after all
// lookups like aliases, usrloc , call forwarding, ENUM
// mappings or PSTN gateways but before the DNS lookup
// Canonical URI must be saved in the SIP Proxy and added as an extra
// Radius attribute in the Radius START packet
if (!$this->CanonicalURI) {
if ($this->RemoteAddress) {
$this->CanonicalURI=$this->RemoteAddress;
} else if ($this->cNumber) {
$this->CanonicalURI=$this->cNumber;
}
}
-
+
if ($this->CanonicalURI) {
$this->CanonicalURIPrint = $this->CanonicalURI;
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->CanonicalURI,"destination",$this->BillingPartyId,$this->domain,$this->gateway,'',$this->ENUMtld,$this->ResellerId);
$this->CanonicalURINormalized = $NormalizedNumber['Normalized'];
$this->CanonicalURIUsername = $NormalizedNumber['username'];
$this->CanonicalURIDomain = $NormalizedNumber['domain'];
$this->CanonicalURIPrint = $NormalizedNumber['NumberPrint'];
$this->CanonicalURIDelimiter = $NormalizedNumber['delimiter'];
$this->CanonicalURIE164 = $NormalizedNumber['E164'];
// Destination Id is used for rating purposes
$this->DestinationId = $NormalizedNumber['DestinationId'];
$this->destinationName = $NormalizedNumber['destinationName'];
$this->region = $NormalizedNumber['region'];
}
if ($this->cNumber) {
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->cNumber,"destination",$this->BillingPartyId,$this->domain,$this->gateway,'',$this->ENUMtld,$this->ResellerId);
$this->cNumberNormalized = $NormalizedNumber['Normalized'];
$this->cNumberUsername = $NormalizedNumber['username'];
$this->cNumberDomain = $NormalizedNumber['domain'];
$this->cNumberPrint = $NormalizedNumber['username'].$NormalizedNumber['delimiter'].$NormalizedNumber['domain'];
$this->cNumberDelimiter = $NormalizedNumber['delimiter'];
$this->cNumberE164 = $NormalizedNumber['E164'];
}
if ($this->RemoteAddress) {
// Next hop is the real destination after all lookups including DNS
$NormalizedNumber = $this->CDRS->NormalizeNumber($this->RemoteAddress,"destination",$this->BillingPartyId,$this->domain,$this->gateway,'',$this->ENUMtld,$this->ResellerId);
$this->RemoteAddressPrint = $NormalizedNumber['NumberPrint'];
$this->RemoteAddressNormalized = $NormalizedNumber['Normalized'];
$this->RemoteAddressDestinationId = $NormalizedNumber['DestinationId'];
$this->RemoteAddressDestinationName = $NormalizedNumber['destinationName'];
$this->RemoteAddressUsername = $NormalizedNumber['username'];
$this->RemoteAddressDelimiter = $NormalizedNumber['delimiter'];
$this->RemoteAddressE164 = $NormalizedNumber['E164'];
$this->remoteGateway = $NormalizedNumber['domain'];
$this->remoteUsername = $NormalizedNumber['username'];
}
$this->isCalleeLocal();
$this->isCallerLocal();
if ($this->CallerIsLocal) {
if ($this->aNumberPrint == $this->BillingPartyId) {
// call is not diverted
if ($this->CalleeIsLocal) {
$this->flow = 'on-net';
} else {
$this->flow = 'outgoing';
}
} else {
// call is diverted
if ($this->CalleeIsLocal) {
$this->flow = 'on-net-diverted-on-net';
} else {
$this->flow = 'on-net-diverted-off-net';
}
}
} else {
if ($this->isBillingPartyLocal()) {
// call is diverted by local user
if ($this->CalleeIsLocal) {
$this->flow = 'diverted-on-net';
} else {
$this->flow = 'diverted-off-net';
}
} else if ($this->CalleeIsLocal) {
$this->flow = 'incoming';
} else {
// transit from trusted peer
$this->flow = 'transit';
}
}
if (($this->flow == 'on-net' || $this->flow == 'diverted-on-net' || $this->flow == 'on-net-diverted-on-net') &&
$this->application == 'audio' &&
$this->CDRS->rating_settings['rate_on_net_calls'] &&
$this->CDRS->rate_on_net_enabled($_billing_party_els[0], $_billing_party_els[1]) &&
!$this->DestinationId &&
$this->CalleeCallerId) {
$_dest = preg_replace("/^\+(\d+)$/","00$1", $this->CalleeCallerId);
$NormalizedNumber = $this->CDRS->NormalizeNumber($_dest,"destination",$this->BillingPartyId,$this->domain,$this->gateway,'',$this->ENUMtld,$this->ResellerId);
$this->DestinationId = $NormalizedNumber['DestinationId'];
$this->destinationName = $NormalizedNumber['destinationName'];
}
if ($this->CDRS->rating_settings['rate_on_net_calls']
&& $this->CDRS->rating_settings['rate_on_net_diverted_calls']
&& ($this->flow == 'on-net-diverted-off-net'
|| $this->flow == 'on-net-diverted-on-net'
|| $this->flow == 'diverted-on-net'
|| $this->flow == 'diverted-off-net')
&& !$this->normalized
&& $this->duration != '0'
&& $this->disconnect == $this->disconnectOrig) {
$query = sprintf("
update
%s
set
AcctStopTime ='%s',
Normalized='0',
AcctSessionTime='%s',
SipResponseCode='200'
where
AcctSessionId='%s'
and SipFromTag='%s'
and SipToTag!='%s'
and (
ServiceType='on-net'
or ServiceType='on-net-diverted-on-net'
or ServiceType='diverted-on-net'
or ServiceType='incoming')
and AcctSessionTime=''",
$this->CDRS->table,
$this->stopTime,
$this->duration,
$this->callId,
$this->SipFromTag,
$this->SipToTag);
$this->tdb = new DB_radius;
dprint($query);
$this->tdb->query($query);
}
if ($this->application == "presence") {
$this->destinationPrint = $this->cNumberUsername.$this->cNumberDelimiter.$this->cNumberDomain;
$this->DestinationForRating = $this->cNumberNormalized;
} else {
if (!$this->DestinationId) {
if ($this->CanonicalURIDomain) {
$this->destinationPrint = $this->CanonicalURIUsername.$this->CanonicalURIDelimiter.$this->CanonicalURIDomain;
} else {
$this->destinationPrint = $this->cNumberUsername.$this->cNumberDelimiter.$this->cNumberDomain;
}
if (strstr($this->CanonicalURINormalized,'@')) {
$this->DestinationForRating = $this->CanonicalURINormalized;
} else {
$this->DestinationForRating = $this->RemoteAddressNormalized;
}
} else {
$this->DestinationForRating = $this->CanonicalURINormalized;
$this->destinationPrint = $this->CanonicalURIPrint;
}
}
if ($this->inputTraffic) {
$this->inputTrafficPrint = number_format($this->inputTraffic/1024,2);
} else {
$this->inputTrafficPrint=0;
}
if ($this->outputTraffic) {
$this->outputTrafficPrint = number_format($this->outputTraffic/1024,2);
} else {
$this->outputTrafficPrint=0;
}
if (!$CDRfields['skip_fix_prepaid_duration']) {
if (!$this->normalized && $this->callId) {
// fix the duration of prepaid sessions if the prepaid duration is different than radius calculated duration
$query=sprintf("select duration from prepaid_history
where session = '%s'
and destination = '%s'
order by id desc limit 1",
addslashes($this->callId),
addslashes($this->destinationPrint) // must be synced with maxsession time
);
if ($this->CDRS->cdrtool->query($query)) {
if ($this->CDRS->cdrtool->num_rows()) {
$this->CDRS->cdrtool->next_record();
$this->durationNormalized = $this->CDRS->cdrtool->f('duration');
$this->durationPrint = sec2hms($this->durationNormalized);
} else {
$this->durationPrint = sec2hms($this->duration);
}
} else {
$log=sprintf("Database error for query %s: %s (%s)",$query,$this->CDRS->cdrtool->Error,$this->CDRS->cdrtool->Errno);
syslog(LOG_NOTICE,$log);
}
} else {
$this->durationPrint = sec2hms($this->duration);
}
} else {
$this->durationPrint = sec2hms($this->duration);
}
if ($this->disconnect) {
$this->disconnectPrint = $this->NormalizeDisconnect($this->disconnect);
}
if ($this->disconnectOrig != $this->disconnect
&& $this->disconnect
&& $this->CDRS->rating_settings['rate_on_net_diverted_calls']) {
$this->disconnectOrigPrint =$this->CDRS->disconnectCodesDescription[$this->disconnectOrig]." (".$this->disconnectOrig.")";
}
$this->traceIn();
$this->traceOut();
$this->obfuscateCallerId();
if ($this->CDRS->rating) {
global $perm;
if (is_object($perm) && $perm->have_perm("showPrice")) {
$this->pricePrint=$this->price;
} else {
$this->pricePrint='x.xxx';
}
}
}
function buildMongoCDR() {
# TODO = remove me
$this->mongo_cdr = array();
$int_values = array('duration', 'inputTraffic', 'outputTraffic', 'timestamp', 'disconnect');
foreach (array_keys($this->CDRS->CDRFields) as $field) {
if (in_array($field, $int_values)) {
$this->mongo_cdr[$field] = intval($this->$field);
} else {
$this->mongo_cdr[$field] = $this->$field;
}
}
if ($this->CanonicalURI) {
$this->mongo_cdr['CanonicalURI'] = $this->CanonicalURI;
}
if ($this->RemoteAddress) {
$this->mongo_cdr['RemoteAddress'] = $this->RemoteAddress;
}
if ($this->BillingPartyId) {
$this->mongo_cdr['BillingPartyId'] = $this->BillingPartyId;
}
if ($this->aNumber) {
$this->mongo_cdr['aNumber'] = $this->aNumber;
}
if ($this->cNumber) {
$this->mongo_cdr['cNumber'] = $this->cNumber;
}
if ($this->SipRPID) {
$this->mongo_cdr['SipRPID'] = $this->SipRPID;
}
}
function buildCDRdetail() {
global $perm;
global $found;
if (!is_object($perm)) return;
$this->geo_location=$this->lookupGeoLocation($this->SourceIP);
$this->cdr_details="
SIP Signalling
";
$this->cdr_details.= sprintf("
Click here to show only this call id
",
$this->CDRS->url_run,
urlencode($this->callId)
);
if ($this->CDRS->sipTrace) {
$trace_datasource = $this->CDRS->sipTrace;
$callid_enc = urlencode(quoted_printable_decode($this->callId));
$fromtag_enc = urlencode(quoted_printable_decode($this->SipFromTag));
$totag_enc = urlencode(quoted_printable_decode($this->SipToTag));
$this->traceLink="
SipProxyServer', '_blank',
'toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=1300px,height=600')\">Click here for the SIP trace ";
$this->cdr_details.= "
";
}
$this->cdr_details.= sprintf("
", $this->traceLink);
$this->cdr_details.= "
From tag:
$this->SipFromTag
Start Time:
$this->startTime $providerTimezone
Stop Time:
$this->stopTime
";
$this->cdr_details.= sprintf("
",$this->geo_location);
$this->cdr_details.= "
Method:
$this->SipMethod from $this->SourceIP:$this->SourcePort
From:
$this->aNumberPrint
From Header:
$this->FromHeaderPrint
User Agent:
$this->UserAgentPrint
To (dialed URI):
$this->cNumberPrint
";
if ($this->CanonicalURI) {
$this->cdr_details.= sprintf("
",htmlentities($this->CanonicalURI));
}
$this->cdr_details.= sprintf("
",htmlentities($this->RemoteAddress));
if ($this->DestinationId) {
$this->cdr_details.= "
Destination:
$this->destinationName ($this->DestinationId)
";
}
if ($this->ENUMtld && $this->ENUMtld != 'none' && $this->ENUMtld != 'N/A') {
$this->cdr_details.= "
";
}
if ($this->SipRPID) {
$this->cdr_details .= "
Caller ID:
$this->SipRPIDPrint
";
}
if ($this->CalleeCallerId) {
$this->cdr_details .= "
Called ID:
$this->CalleeCallerId
";
}
$this->cdr_details.= "
Billing Party:
$this->BillingPartyIdPrint
Reseller:
$this->ResellerId
";
$this->cdr_details.= "
";
if ($this->application != 'message') {
$this->cdr_details.= "
Media Streams
";
if ($this->CDRS->mediaTrace) {
$media_trace_datasource = $this->CDRS->mediaTrace;
$this->mediaTraceLink="
SipProxyServer', '_blank',
'toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=800,height=730')\">Click here for media information ";
$this->cdr_details.= sprintf("
", $this->mediaTraceLink);
}
$this->SipCodec = quoted_printable_decode($this->SipCodec);
if ($this->SipCodec) {
$this->cdr_details.= "
";
}
$this->cdr_details.= "
Caller RTP:
$this->inputTrafficPrint KB
Called RTP:
$this->outputTrafficPrint KB
";
if ($this->MediaInfo) {
$this->cdr_details.= "
Media Info:
$this->MediaInfo
";
}
$this->cdr_details.= "
Applications:
$this->application_print
";
}
if ($this->SipUserAgents) {
$this->SipUserAgents = quoted_printable_decode($this->SipUserAgents);
$callerAgents=explode("+",$this->SipUserAgents);
$callerUA=htmlentities($callerAgents[0]);
$calledUA=htmlentities($callerAgents[1]);
$this->cdr_details.= "
";
}
$this->cdr_details.= "
";
if ($perm->have_perm("showPrice") && $this->normalized) {
$this->cdr_details.= "
Rating
";
if ($this->price > 0 || $this->rate) {
$this->ratePrint=nl2br($this->rate);
$this->cdr_details.= "
$this->ratePrint
";
} else {
$this->cdr_details.= "
Free call
";
}
$this->cdr_details.= "
";
}
$this->cdr_details.= "
";
}
function traceIn () {
$datasource=$this->CDRS->traceInURL[$this->SourceIP];
global $DATASOURCES;
if (!$datasource || !$DATASOURCES[$datasource]) {
return;
}
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$c_number = $this->remoteUsername;
$cdr_table = Date('Ym',time($this->timestamp));
$this->traceIn=
"".
"In".
"";
}
function traceOut () {
$datasource=$this->CDRS->traceOutURL[$this->remoteGateway];
global $DATASOURCES;
if (!$datasource || !$DATASOURCES[$datasource]) {
return;
}
$tplus = $this->timestamp+$this->duration+300;
$tmin = $this->timestamp-300;
$c_number = preg_replace("/^(0+)/","",$this->remoteUsername);
$cdr_table = Date('Ym',time($this->timestamp));
$this->traceOut=
"".
"Out".
"";
}
function show() {
$this->buildCDRdetail();
global $found;
global $perm;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="#F9F9F9";
} else {
$inout_color="white";
}
$this->ratePrint=nl2br($this->rate);
if ($this->CDRS->Accounts[$this->BillingPartyId]['timezone']) {
$timezone_print=$this->CDRS->Accounts[$this->BillingPartyId]['timezone'];
} else {
$timezone_print=$this->CDRS->CDRTool['provider']['timezone'];
}
$found_print=$found;
if ($this->normalized) $found_print.='N';
$providerTimezone=$this->CDRS->CDRTool['provider']['timezone'];
print "
$found_print |
$this->startTime |
$this->flow |
$this->aNumberPrint |
$this->geo_location |
$this->SipProxyServer |
$this->application |
$this->destinationPrint
";
if ($this->DestinationId) {
if ($this->DestinationId != $this->CanonicalURI) {
print " ($this->destinationName $this->DestinationId)";
} else {
print " ($this->destinationName)";
}
}
print " | ";
if (!$this->normalized){
if ($this->duration > 0 ) {
print "$this->duration(s) | ";
} else {
print "in progress | ";
}
} else {
print "
$this->durationPrint |
$this->pricePrint |
$this->inputTrafficPrint |
$this->outputTrafficPrint |
";
}
$SIPclass=substr($this->disconnect,0,1);
if ($SIPclass=="6") {
$status_color="";
} else if ($SIPclass=="5" ) {
$status_color="";
} else if ($SIPclass=="4" ) {
$status_color="";
} else if ($SIPclass=="3" ) {
$status_color="";
} else if ($SIPclass=="2" ) {
$status_color="";
} else {
$status_color="";
}
if ($this->disconnectOrig != $this->disconnect
&& $this->CDRS->rating_settings['rate_on_net_diverted_calls']) {
$disclass=substr($this->disconnectOrig,0,1);
if ($disclass == "6" || $disclass=="5") {
$status1_color="";
} else if ($disclass=="4" ) {
$status1_color="";
} else if ($disclass=="3" ) {
$status1_color="";
} else if ($disclass=="2" ) {
$status1_color="";
} else {
$status1_color="";
}
}
print "
$this->SipCodec |
$status_color $this->disconnectPrint";
if ($this->disconnectOrig != $this->disconnect
&& $this->CDRS->rating_settings['rate_on_net_diverted_calls']) {
print "$status1_color $this->disconnectOrigPrint";
}
print " |
";
}
function export() {
global $found;
$disconnectName = $this->CDRS->disconnectCodesDescription[$this->disconnect];
$UserAgents = explode("+",$this->SipUserAgents);
$CallingUserAgent = trim($UserAgents[0]);
$CalledUserAgent = trim($UserAgents[1]);
print "$found";
print ",$this->startTime";
print ",$this->stopTime";
print ",$this->BillingPartyIdPrint";
print ",$this->domain";
print ",$this->SipRPIDPrint";
print ",$this->aNumberPrint";
print ",$this->destinationPrint";
print ",$this->DestinationId";
print ",$this->destinationName";
print ",$this->RemoteAddressPrint";
print ",$this->CanonicalURIPrint";
print ",$this->duration";
print ",$this->price";
print ",$this->SipProxyServer";
print ",$this->inputTraffic";
print ",$this->outputTraffic";
printf(",%s",preg_replace("/,/","/",quoted_printable_decode($CallingUserAgent)));
printf(",%s",preg_replace("/,/","/",quoted_printable_decode($CalledUserAgent)));
print ",$this->disconnect";
print ",$disconnectName";
printf(",%s",preg_replace("/,/","/",quoted_printable_decode($this->SipCodec)));
print ",$this->application";
print "\n";
}
function showSubscriber() {
$this->buildCDRdetail();
global $found;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
if (!$this->CDRS->export) {
$timezone_print=$this->CDRS->CDRTool['provider']['timezone'];
$found_print=$found;
if ($this->normalized) $found_print.='N';
print "
$found_print |
$this->startTime $timezone_print |
$this->aNumberPrint |
$this->geo_location |
$this->SipProxyServer |
$this->destinationPrint $this->destinationName |
$this->durationPrint |
";
if ($this->CDRS->rating) {
print "$this->pricePrint | ";
}
print "
$this->inputTrafficPrint |
$this->outputTrafficPrint |
";
print "
";
} else {
$disconnectName=$this->CDRS->disconnectCodesDescription[$this->disconnect];
$UserAgents=explode("+",$this->SipUserAgents);
$CallingUserAgent=trim($UserAgents[0]);
$CalledUserAgent=trim($UserAgents[1]);
print "$found,$this->startTime,$this->stopTime,$this->BillingPartyId,$this->domain,$this->aNumberPrint,$this->cNumberPrint,$this->DestinationId,$this->destinationName,$this->RemoteAddressPrint,$this->duration,$this->price,$this->SipProxyServer,$this->inputTraffic,$this->outputTraffic,$CallingUserAgent,$CalledUserAgent,$this->disconnect,$disconnectName,$this->SipCodec,$this->application\n";
}
}
function isBillingPartyLocal() {
$els=explode("@",$this->BillingPartyId);
if ($els[1] && isset($this->CDRS->localDomains[$els[1]])) {
return true;
}
return false;
}
function isCallerLocal() {
if (isset($this->CDRS->localDomains[$this->aNumberDomain])) {
$this->CallerIsLocal=true;
$this->SipRPID = $this->CDRS->getCallerId($this->BillingPartyId);
$this->SipRPIDPrint = $this->SipRPID;
#$this->SipRPIDPrint = quoted_printable_decode($this->SipRPID);
}
}
function isCalleeLocal() {
if (isset($this->CDRS->localDomains[$this->CanonicalURIDomain]) && !preg_match("/^0/",$this->CanonicalURIUsername)) {
$this->CalleeIsLocal=true;
$this->CalleeCallerId=$this->CDRS->getCallerId($this->CanonicalURI);
}
}
function obfuscateCallerId() {
global $obfuscateCallerId;
if ($obfuscateCallerId) {
//Caller party
$caller_els=explode("@",$this->aNumberPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='caller';
}
if (count($caller_els)== 2) {
$this->aNumberPrint=$_user.'@'.$caller_els[1];
} else {
$this->aNumberPrint=$_user;
}
//Billing party
$caller_els=explode("@",$this->BillingPartyIdPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='party';
}
$this->BillingPartyIdPrint=$_user.'@'.$caller_els[1];
// Destination
$caller_els=explode("@",$this->destinationPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='destination';
}
if (count($caller_els)== 2) {
$this->destinationPrint=$_user.'@'.$caller_els[1];
} else {
$this->destinationPrint=$_user;
}
$caller_els=explode("@",$this->cNumberPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='dialedNumber';
}
if (count($caller_els)== 2) {
$this->cNumberPrint=$_user.'@'.$caller_els[1];
} else {
$this->cNumberPrint=$_user;
}
$caller_els=explode("@",$this->RemoteAddressPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='remoteAddress';
}
if (count($caller_els)== 2) {
$this->RemoteAddressPrint=$_user.'@'.$caller_els[1];
} else {
$this->RemoteAddressPrint=$_user;
}
// Canonical URI
$caller_els=explode("@",$this->CanonicalURIPrint);
if (is_numeric($caller_els[0]) && strlen($caller_els[0]>3)) {
$_user=substr($caller_els[0],0,strlen($caller_els[0])-3).'xxx';
} else {
$_user='canonicalURI';
}
if (count($caller_els)== 2) {
$this->CanonicalURIPrint=$_user.'@'.$caller_els[1];
} else {
$this->CanonicalURIPrint=$_user;
}
if (is_numeric($this->SipRPIDPrint) && strlen($this->SipRPIDPrint) > 3) {
$this->SipRPIDPrint=substr($this->SipRPID,0,strlen($this->SipRPID)-3).'xxx';
} else {
$_user='callerId';
}
// IP address
$this->SourceIP='xxx.xxx.xxx.xxx';
}
}
}
class CDRS_opensips_mongo extends CDRS_opensips {
var $CDR_class = "CDR_opensips_mongo";
var $mongo_db_ro = NULL;
var $mongo_db_rw = NULL;
function getCDRtables() {
if (!is_object($this->mongo_db_rw) && !$this->initDatabaseConnection) {
return array();
}
$_tables=array();
try {
$_tables=$this->mongo_db_rw->listCollections();
} catch (Exception $e) {
printf("Caught Mongo exception in getCDRtables(): %s", $e->getMessage());
}
$t=count($_tables);
if ($this->table) $this->tables[]=$this->table;
foreach ($_tables as $_table) {
$_table=strval($_table);
if (preg_match("/^.*\.(radacct\d{6})$/",$_table,$m)) {
if ($list_t > 24) break;
if (!in_array($m[1], $this->tables)) {
$this->tables[]=$m[1];
}
$list_t++;
}
$t--;
}
$this->tables=array_unique($this->tables);
}
function initDatabaseConnection() {
if ($this->DATASOURCES[$this->cdr_source]['mongo_db']) {
$mongo_db = $this->CDRTool['mongo_db'][$this->DATASOURCES[$this->cdr_source]['mongo_db']];
$mongo_uri = $mongo_db['uri'];
$mongo_replicaSet = $mongo_db['replicaSet'];
$mongo_database = $mongo_db['database'];
try {
$mongo_connection_ro = new Mongo("mongodb://$mongo_uri?readPreference=secondaryPreferred", array("replicaSet" => $mongo_replicaSet));
$this->mongo_db_ro = $mongo_connection_ro->selectDB($mongo_database);
$mongo_connection_rw = new Mongo("mongodb://$mongo_uri?readPreference=primaryPreferred", array("replicaSet" => $mongo_replicaSet));
$this->mongo_db_rw = $mongo_connection_rw->selectDB($mongo_database);
return true;
} catch (Exception $e) {
printf("
Caught exception in initDatabaseConnection(): %s", $e->getMessage());
return false;
}
}
return true;
}
function getMongoTable($table, $rw=false) {
try {
if ($rw) {
if (!$this->mongo_db_rw && !$this->initDatabaseConnection()) {
return NULL;
}
$table = $this->mongo_db_rw->selectCollection($table);
} else {
if (!$this->mongo_db_ro && !$this->initDatabaseConnection()) {
return NULL;
}
$table = $this->mongo_db_ro->selectCollection($table);
}
return $table;
} catch (Exception $e) {
printf("
Caught exception in getMongoTable(): %s", $e->getMessage());
}
return NULL;
}
function initCDRFields() {
// init names of CDR fields
foreach (array_keys($this->CDRFields) as $field) {
$mongo_field=$field;
$_field=$field."Field";
$this->$_field=$mongo_field;
}
}
function _readCDRFieldsFromDB($mongo_result) {
foreach (array_keys($this->CDRFields) as $field) {
$CDRStructure[$this->CDRFields[$field]] = $mongo_result[$field];
}
return $CDRStructure;
}
function getUnNormalized($where="",$table) {
# TODO
return 0;
}
function show() {
global $perm;
foreach ($this->FormElements as $_el) {
${$_el} = trim($_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);
}
// overwrite some elements based on user rights
if ($this->CDRTool['filter']['gateway']) {
$gateway =$this->CDRTool['filter']['gateway'];
}
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);
}
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);
}
} 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;
}
$mongo_where = array();
if (!$cdr_table) $cdr_table=$this->table;
$mongo_table_ro = $this->getMongoTable($cdr_table);
$mongo_table_rw = $this->getMongoTable($cdr_table, true);
$this->url=sprintf("?cdr_source=%s&cdr_table=%s",$this->cdr_source,$cdr_table);
if ($this->CDRTool['filter']['domain']) {
$this->url .= sprintf("&Realms=%s",urlencode($this->CDRTool['filter']['domain']));
$Realms = explode(" ",$this->CDRTool['filter']['domain']);
} else if ($Realms) {
$this->url .= sprintf("&Realms=%s",urlencode($Realms));
$Realms = explode(" ",$Realms);
}
if ($this->CDRTool['filter']['aNumber']) {
$this->url .= sprintf("&UserName=%s",urlencode($this->CDRTool['filter']['aNumber']));
}
if ($this->CDRTool['filter']['after_date']) {
$mongo_where[$this->startTimeField] = array('$gte' => $this->CDRTool['filter']['after_date']);
}
if ($order_by) {
$this->url.=sprintf("&order_by=%s&order_type=%s",addslashes($order_by),addslashes($order_type));
}
$this->url.=sprintf("&begin_datetime=%s",urlencode($begin_datetime_timestamp));
$this->url.=sprintf("&end_datetime=%s",urlencode($end_datetime_timestamp));
if (!$call_id && $begin_datetime && $end_datetime) {
$mongo_where[$this->startTimeField] = array('$gte' => $begin_datetime, '$lt' => $end_datetime);
} else {
$mongo_where[$this->startTimeField] = array('$gte' => '1970-01-01');
}
if ($MONTHYEAR) {
$mongo_where[$this->startTimeField] = new MongoRegex("/^$MONTHYEAR/");
$this->url.= sprintf("&MONTHYEAR=%s",urlencode($MONTHYEAR));
}
if ($flow) {
$this->url.=sprintf("&flow=%s",urlencode($flow));
$mongo_where[$this->flowField] = $flow;
}
if ($this->CDRTool['filter']['aNumber']) {
// force user to see only CDRS with his a_numbers
$mongo_where['$or'] = array(array($this->usernameField => $this->CDRTool['filter']['aNumber']), array($this->CanonicalURIField => $this->CDRTool['filter']['aNumber']));
$UserName_comp='equal';
$UserName=$this->CDRTool['filter']['aNumber'];
}
if ($UserName_comp == "empty") {
$mongo_where[$this->usernameField] = '';
$this->url.=sprintf("&UserName_comp=%s",urlencode($UserName_comp));
} else if (strlen($UserName) && !$this->CDRTool['filter']['aNumber']) {
if (!$UserName_comp) $UserName_comp='begin';
if ($UserName_comp=="begin") {
$mongo_where[$this->usernameField] = new MongoRegex("/^$UserName/");
} elseif ($UserName_comp=="contain") {
$mongo_where[$this->usernameField] = new MongoRegex("/$UserName/");
} elseif ($UserName_comp=="equal") {
$mongo_where[$this->usernameField] = $UserName;
} else {
$mongo_where[$this->usernameField] = '';
}
$this->url.=sprintf("&UserName=%s&UserName_comp=%s",urlencode($UserName),$UserName_comp);
}
$a_number=trim($a_number);
if ($a_number_comp == "empty") {
$mongo_where[$this->aNumberField] = '';
$this->url.=sprintf("&a_number_comp=%s",urlencode($a_number_comp));
} else if (strlen($a_number)) {
$a_number=urldecode($a_number);
if (!$a_number_comp) $a_number_comp="equal";
$this->url.=sprintf("&a_number=%s",urlencode($a_number));
if ($a_number_comp=="begin") {
$mongo_where[$this->aNumberField] = new MongoRegex("/^$a_number/");
} elseif ($a_number_comp=="contain") {
$mongo_where[$this->aNumberField] = new MongoRegex("/$a_number/");
} elseif ($a_number_comp=="equal") {
$mongo_where[$this->aNumberField] = $a_number;
}
$this->url.=sprintf("&a_number_comp=%s",urlencode($a_number_comp));
}
$c_number=trim($c_number);
if ($c_number_comp == "empty") {
$mongo_where[$this->CanonicalURIField] = '';
$this->url.=sprintf("&c_number_comp=%s",urlencode($c_number_comp));
} else if (strlen($c_number)) {
$c_number=urldecode($c_number);
if (!$c_number_comp) $c_number_comp="begin";
if (!$c_number_comp || $c_number_comp=="begin") {
$mongo_where[$this->CanonicalURIField] = new MongoRegex("/^$c_number/");
} elseif ($c_number_comp=="contain") {
$mongo_where[$this->CanonicalURIField] = new MongoRegex("/$c_number/");
} elseif ($c_number_comp=="equal") {
$mongo_where[$this->CanonicalURIField] = $c_number;
}
$this->url.=sprintf("&c_number=%s&c_number_comp=%s",urlencode($c_number),urlencode($c_number_comp));
}
$Realm=trim($Realm);
if ($Realms) {
$d_array=array();
foreach ($Realms as $realm) {
$d_array[] = array($this->domainField => $realm);
}
$mongo_where['$or'] = $d_array;
} else if ($Realm) {
$Realm=urldecode($Realm);
$mongo_where[$this->domainField] = $Realm;
$this->url.=sprintf("&Realm=%s",urlencode($Realm));
}
$BillingId=trim($BillingId);
if (preg_match("/^\d+$/",$BillingId) && $this->BillingIdField) {
$mongo_where[$this->BillingIdField] = $BillingId;
$this->url.=sprintf("&BillingId=%s",urlencode($BillingId));
}
if ($application) {
$mongo_where[$this->applicationField] = new MongoRegex("/$application/");
$this->url.=sprintf("&application=%s",urlencode($application));
}
if ($DestinationId) {
if ($DestinationId=="empty") {
$DestinationIdSQL="";
} else {
$DestinationIdSQL=$DestinationId;
}
$mongo_where[$this->DestinationIdField] = $DestinationIdSQL;
$this->url.=sprintf("&DestinationId=%s",urlencode($DestinationId));
}
if (strlen(trim($ExcludeDestinations))) {
# TODO: migrateb clause to mongo
$ExcludeDestArray=explode(" ",trim($ExcludeDestinations));
foreach ($ExcludeDestArray as $exclDst) {
if (preg_match("/^0+(\d+)$/",$exclDst,$m)) {
$exclDest_id=$m[1];
} else {
$exclDest_id=$exclDst;
}
$where .= " and ".
$this->CanonicalURIField.
" not like '".
addslashes(trim($exclDst)).
"'";
}
$this->url.=sprintf("&ExcludeDestinations=%s",urlencode($ExcludeDestinations));
}
$call_id=trim($call_id);
if ($call_id) {
$call_id=urldecode($call_id);
$mongo_where[$this->callIdField] = $call_id;
$this->url.=sprintf("&call_id=%s",urlencode($call_id));
}
if ($sip_proxy) {
$sip_proxy=urldecode($sip_proxy);
$mongo_where[$this->SipProxyServerField] = $sip_proxy;
$this->url.=sprintf("&sip_proxy=%s",urlencode($sip_proxy));
}
if ($SipCodec) {
$this->url.=sprintf("&SipCodec=%s",urlencode($SipCodec));
if ($SipCodec != "empty") {
$mongo_where[$this->SipCodecField] = $SipCodec;
} else {
$mongo_where[$this->SipCodecField] = '';
}
}
if ($SipRPID) {
$this->url.=sprintf("&SipRPID=%s",urlencode($SipRPID));
if ($SipRPID != "empty") {
$mongo_where[$this->SipRPIDField] = $SipRPID;
} else {
$mongo_where[$this->SipRPIDField] = '';
}
}
if ($UserAgent) {
$mongo_where[$this->UserAgentField] = $UserAgent;
$this->url.=sprintf("&UserAgent=%s",urlencode($UserAgent));
}
if (strlen($sip_status)) {
$mongo_where[$this->disconnectField] = $sip_status;
$this->url.=sprintf("&sip_status=%s",urlencode($sip_status));
}
if ($sip_status_class) {
$mongo_where[$this->disconnectField] = new MongoRegex("/^$sip_status_class/");
$this->url.=sprintf("&sip_status_class=%s",urlencode($sip_status_class));
}
if ($this->CDRTool[filter]["gateway"]) {
$mongo_where[$this->gatewayField] = $this->CDRTool[filter]["gateway"];
} else if ($gateway) {
$gateway=urldecode($gateway);
$mongo_where[$this->gatewayField] = $gateway;
$this->url.=sprintf("&gateway=%s",$gateway);
}
if ($duration) {
if (preg_match("/\d+/",$duration) ) {
$mongo_where[$this->durationField] = array('$gt' => 0);;
} elseif (preg_match("/onehour/",$duration) ) {
$mongo_where[$this->durationField] = array('$lt' => 3610, '$gt' => 3530);
} elseif ($duration == "zero") {
$mongo_where[$this->durationField] = 0;
} elseif ($duration == "zeroprice" && $this->priceField) {
$mongo_where[$this->durationField] = array('$gt' => 0);
$mongo_where[$this->priceField] = NULL;
} elseif ($duration == "nonzero") {
$mongo_where[$this->durationField] = array('$gt' => 0);
} elseif ($duration == "onewaymedia") {
$mongo_where['$or'] = array(array($this->outputTrafficField => 0), array($this->inputTrafficField => 0));
} elseif ($duration == "nomedia") {
$mongo_where[$this->inputTrafficField] = 0;
$mongo_where[$this->outputTrafficField] = 0;
}
$this->url.=sprintf("&duration=%s",urlencode($duration));
}
if ($media_info) {
$this->url.=sprintf("&media_info=%s",urlencode($media_info));
$mongo_where[$this->MediaInfoField] = $media_info;
}
$this->url.=sprintf("&maxrowsperpage=%s",addslashes($this->maxrowsperpage));
$url_calls = $this->scriptFile.$this->url."&action=search";
if ($group_by) {
$this->url.=sprintf("&group_by=%s",urlencode($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 ($duration == "unnormalized") {
$mongo_where[$this->normalizedField] = '0';
}
if ($duration == "unnormalized_duration") {
$mongo_where[$this->normalizedField] = '0';
$mongo_where[$this->durationField] = array('$gt' => 0);
}
if ($group_by) {
$this->group_byOrig=$group_by;
if ($group_by=="hour") {
$group_by="HOUR(AcctStartTime)";
} else if (preg_match("/^DAY/",$group_by)) {
$group_by="$group_by(AcctStartTime)";
} else if (preg_match("/BYMONTH/",$group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y-%m')";
} else if (preg_match("/BYYEAR/",$group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y')";
} else if ($group_by=="UserAgentType") {
$group_by="SUBSTRING_INDEX($this->SipUserAgentsField, ' ', '1')";
}
$this->group_by=$group_by;
if ($group_by==$this->callIdField) {
$having=sprintf(" having count(%s) > 1 ", addslashes($group_by));
}
$field = array_search($group_by, $this->CDRFields);
$pipeline=array(
array('$match' => $mongo_where),
array('$group' => array("_id" => sprintf('$%s', $field),
'calls' => array('$sum' => 1))),
array('$match' => array('calls' => array('$gte' => 0)))
);
$rows = 0;
if ($mongo_table_ro) {
try {
$group_results = $mongo_table_ro->aggregate($pipeline);
$rows = count($group_results);
} catch (Exception $e) {
printf("
Caught Mongo exception in show(): %s", $e->getMessage());
}
}
} else {
$rows = 0;
if ($mongo_table_ro) {
try {
$rows = $mongo_table_ro->find($mongo_where)->slaveOkay()->count();
} catch (Exception $e) {
printf("
Caught Mongo exception in show(): %s", $e->getMessage());
}
}
}
dprint_r($mongo_where);
$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 ($call_id && $ReNormalize) {
if ($mongo_table_rw) {
$mongo_table_rw->update(array($this->normalizedField=>0), array('$set' => array($this->callIdField => $call_id)));
}
}
if ($UnNormalizedCalls=$this->getUnNormalized($mongo_where,$cdr_table)) {
if (!$this->DATASOURCES[$this->cdr_source]['skipNormalizeOnPageLoad']) {
if ($UnNormalizedCalls < $this->maxCDRsNormalizeWeb) {
$this->NormalizeCDRS($mongo_where,$cdr_table);
if (!$this->export && $this->status['normalized'] ) {
print "
";
printf ("%d CDRs normalized. ",$this->status['normalized']);
if ($this->status['cached_keys']['saved_keys']) {
printf ("Quota usage updated for %d accounts. ",$this->status['cached_keys']['saved_keys']);
}
print "
";
}
}
}
}
if ($rows > $this->maxrowsperpage) {
$maxrows=$this->maxrowsperpage+$this->next;
if ($maxrows > $rows) {
$maxrows=$rows;
$prev_rows=$maxrows;
}
} else {
$maxrows=$rows;
}
if ($duration == "unnormalized") {
// if display un normalized calls we must substract
// the amount of calls normalized above
$maxrows=$maxrows-$this->status['normalized'];
}
$mongo_order_by = '_id';
if ($order_type == DESC) {
$mongo_order_type = -1;
} else {
$mongo_order_type = 1;
}
if ($group_by) {
if ($order_by == "group_by") {
$mongo_order_by = '_id';
} else {
$_tmp = array_search($order_by, $this->CDRFields);
if (in_array($_tmp, array('price', 'duration','inputTraffic', 'outputTraffic'))) {
$mongo_order_by = $_tmp;
} else {
$mongo_order_by = 'calls';
}
}
$pipeline=array(
array('$match' => $mongo_where),
array('$group' => array('_id' => sprintf('$%s', $field),
'calls' => array( '$sum' => 1),
'duration' => array( '$sum' => '$duration'),
'inputTraffic' => array( '$sum' => '$inputTraffic'),
'outputTraffic' => array( '$sum' => '$outputTraffic'),
'price' => array( '$sum' => '$price'),
'zero' => array( '$sum' => array('$cond'=> array(array('$eq' => array('$duration', 0)), 1, 0 ))),
'nonzero' => array( '$sum' => array('$cond'=> array(array('$gt' => array('$duration', 0)), 1, 0 )))
)
),
array('$match' => array('calls' => array('$gte' => 0))),
array('$sort' => array($mongo_order_by => $mongo_order_type)),
array('$skip' => intval($i)),
array('$limit' => intval($this->maxrowsperpage))
);
//dprint_r($pipeline);
try {
$group_results = $mongo_table_ro->aggregate($pipeline);
} catch (Exception $e) {
printf("Caught Mongo exception in show(): %s", $e->getMessage());
}
$this->showTableHeaderStatistics();
foreach ($group_results as $result) {
$found=$i+1;
$mygroup = $result['_id'];
$calls = $result['calls'];
$seconds = $result['duration'];
$price = $result['price'];
$zero = $result['zero'];
$zeroP = $calls/$zero * 100;
$nonzero = $result['nonzero'];
$nonzeroP = $calls/$nonzero * 100;
$seconds_print = number_format($seconds,0);
$minutes = number_format($seconds/60,0,"","");
$minutes_print = number_format($seconds/60,0);
$hours = sec2hms($seconds);
$AcctInputOctets = number_format($result['inputTraffic'] * 2/ 1024/1024,2,".","");
$AcctOutputOctets = number_format($result['outputTraffic'] * 2/ 1024/1024,2,".","");
$NetRateIn = $result['inputTraffic']*8*2/1024/$seconds;
$NetRateOut = $result['outputTraffic']*8*2/1024/$seconds;
$success = number_format($nonzero/$calls*100,2,".","");
$failure = number_format($zero/$calls*100,2,".","");
$NetworkRateIn = number_format($NetRateIn,2);
$NetworkRateOut = number_format($NetRateOut,2);
$NetworkRate = max($NetworkRateIn,$NetworkRateOut);
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$inout_color="lightgrey";
} else {
$inout_color="white";
}
$traceValue="";
$mygroup_print=quoted_printable_decode($mygroup);
if ($this->group_byOrig==$this->DestinationIdField) {
if ($this->CDRTool['filter']['domain'] && $this->destinations[$this->CDRTool['filter']['domain']]) {
list($_dst_id,$_dst_name)=$this->getPSTNDestinationId($mygroup,'',$this->CDRTool['filter']['domain']);
$description=$_dst_name;
} else {
$description=$this->destinations[0]["default"][$mygroup]["name"];
}
if ($mygroup) {
$traceValue=$mygroup;
} else {
$traceValue="empty";
}
} else if ($this->group_byOrig==$this->aNumberField) {
# Normalize Called Station Id
$N=$this->NormalizeNumber($mygroup);
$mygroup_print=$N['username']."@".$N[domain];
$description="";
$traceField="a_number";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->CanonicalURIField) {
$traceField="c_number";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->SipProxyServerField) {
$traceField="sip_proxy";
$traceValue=urlencode($mygroup);
} else if ($this->group_byOrig==$this->SipCodecField) {
$traceField="SipCodec";
} else if (preg_match("/UserAgent/",$this->group_byOrig)) {
$traceField="UserAgent";
} else if (preg_match("/^BY/",$this->group_byOrig)) {
$traceField="MONTHYEAR";
} else if ($this->group_byOrig==$this->callIdField) {
$traceField="call_id";
} else if ($this->group_byOrig=="SourceIP") {
$traceField = "gateway";
} else if ($this->group_byOrig=="SipResponseCode") {
$description = $this->disconnectCodesDescription[$mygroup];
$traceField="sip_status";
} else if ($this->group_byOrig=="SipApplicationType") {
$traceField="application";
} else if ($this->group_byOrig=="ServiceType") {
$traceField="flow";
} else {
$description="";
}
if (!$traceField) {
$traceField = $group_by;
}
if (!$traceValue) {
$traceValue = $mygroup;
}
if (!$traceValue) {
$traceValue="";
$comp_type="empty";
} else {
$comp_type="begin";
}
$traceValue_enc=urlencode($traceValue);
if (!$this->export) {
print "
$found |
$calls |
$seconds_print |
$minutes_print |
$hours |
";
if ($perm->have_perm("showPrice")) {
$pricePrint=number_format($price,4,".","");
} else {
$pricePrint='x.xxx';
}
print "
$pricePrint |
$AcctInputOctets |
$AcctOutputOctets |
$success% |
($nonzero calls) |
$failure% |
($zero calls) |
$mygroup_print |
$description |
";
printf("Display calls | ",$url_calls,$traceField,$traceValue_enc,$traceField,$comp_type);
print "
";
} else {
print "$found,";
print "$calls,";
print "$seconds,";
print "$minutes,";
print "$hours,";
if ($perm->have_perm("showPrice")) {
$pricePrint=$price;
} else {
$pricePrint='x.xxx';
}
print "$pricePrint,";
print "$AcctInputOctets,";
print "$AcctOutputOctets,";
print "$success,";
print "$nonzero,";
print "$failure,";
print "$zero,";
print "$mygroup_print,";
print "$description";
print "\n";
}
$i++;
}
if (!$this->export) {
print "
";
}
} else {
if (!$this->export) {
// printf ("
";
$basicURL = $protocolURL.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$fullURL = $basicURL;
print "URLs for this trace:
HTML |
TEXT";
if ($this->mediaTrace) {
$media_query = array(
'cdr_source' => $this->mediaTrace,
'callid' => $callid,
'fromtag' => $fromtag,
'totag' => $totag,
'proxyIP' => $proxyIP
);
$this->mediaTraceLink = sprintf(
"
Click here for RTP media information
",
http_build_query($media_query)
);
}
print "
Click on each packet to expand its body content
$this->mediaTraceLink
";
foreach (array_keys($this->trace_array) as $key) {
$this->trace_array[$key]['isProxy'] = 0;
if ($this->trace_array[$key]['direction'] == 'in') {
if (is_array($this->SIPProxies)) {
$thisIP=explode(":", $this->trace_array[$key]['fromip']);
if ($this->isProxy($thisIP[0], $proxyIP)) {
$this->trace_array[$key]['isProxy'] = 1;
}
}
if ($this->trace_array[$key]['fromip'] == $this->trace_array[$key]['toip']) {
$arrow_direction = "loop";
} elseif ($this->column[$this->trace_array[$key]['fromip']] < $this->column[$this->trace_array[$key]['toip']]) {
$arrow_direction = "right";
} else {
$arrow_direction = "left";
}
$this->trace_array[$key]['msg_possition'] = $this->column[$this->trace_array[$key]['toip']];
$this->trace_array[$key]['arrow_possition'] = $this->column[$this->trace_array[$key]['fromip']];
$this->trace_array[$key]['arrow_direction'] = $arrow_direction;
} else {
if ($this->trace_array[$key]['fromip'] == $this->trace_array[$key]['toip']) {
$arrow_direction = "loop";
} elseif ($this->column[$this->trace_array[$key]['fromip']] < $this->column[$this->trace_array[$key]['toip']]) {
$arrow_direction = "right";
} else {
$arrow_direction = "left";
}
$this->trace_array[$key]['msg_possition'] = $this->column[$this->trace_array[$key]['fromip']];
$this->trace_array[$key]['arrow_possition'] = $this->column[$this->trace_array[$key]['toip']];
$this->trace_array[$key]['arrow_direction'] = $arrow_direction;
}
}
echo "
Packet |
Time |
";
$_seen_timeline = array();
foreach (array_keys($this->column) as $_key) {
$IPels = explode(":", $_key);
if (isset($this->hostnames[$IPels[0]])) {
$_hostname = $this->hostnames[$IPels[0]];
} else {
$_hostname = $_key;
}
print "";
if ($proxyIP != $IPels[0] && $this->isProxy($IPels[0], $proxyIP)) {
$trace_query = array(
'cdr_source' => $this->cdr_source,
'callid' => $callid,
'fromtag' => $fromtag,
'totag' => $totag,
'proxyIP' => $IPels[0]
);
$trace_link = sprintf(
"%s:%s",
http_build_query($trace_query),
$_hostname,
$this->column_port[$_key]
);
printf("%s", $trace_link);
} else {
printf("%s", $_hostname);
}
print " | ";
}
print "
";
/* Rows */
$i=0;
foreach (array_keys($this->trace_array) as $key) {
$i++;
$id = $this->trace_array[$key]['id'];
$msg = $this->trace_array[$key]['msg'];
$fromip = $this->trace_array[$key]['fromip'];
$toip = $this->trace_array[$key]['toip'];
$date = substr($this->trace_array[$key]['date'], 11);
$status = $this->trace_array[$key]['status'];
$direction = $this->trace_array[$key]['direction'];
$timestamp = $this->trace_array[$key]['timestamp'];
$method = $this->trace_array[$key]['method'];
$isProxy = $this->trace_array[$key]['isProxy'];
$transport = $this->trace_array[$key]['transport'];
$msg_possition = $this->trace_array[$key]['msg_possition'];
$arrow_possition = $this->trace_array[$key]['arrow_possition'];
$arrow_direction = $this->trace_array[$key]['arrow_direction'];
$md5 = $this->trace_array[$key]['md5'];
if ($i == 1) {
$begin_timestamp = $timestamp;
}
$timeline = $timestamp - $begin_timestamp;
$sip_phone_img = getImageForUserAgent($msg);
if ($seen_msg[$md5]) {
continue;
}
$SIPclass = substr($status, 0, 1);
switch ($SIPclass) {
case 6:
$status_color = "red";
break;
case 5:
$status_color = "red";
break;
case 4:
$status_color = "red";
break;
case 3:
$status_color = "green";
break;
case 2:
$status_color = "green";
break;
case 1:
$status_color = "orange";
break;
default:
$status_color = "blue";
if ($method == "ACK") {
$status_color = 'cyan';
} else if ($method == "CANCEL") {
$status_color = 'magenta';
}
break;
}
$_lines = explode("\n", $msg);
if (preg_match("/^(.*) SIP/", $_lines[0], $m)) {
$_lines[0] = $m[1];
} elseif (preg_match("/^SIP\/2\.0 (.*)/", $_lines[0], $m)) {
$_lines[0] = $m[1];
}
unset($media);
unset($diversions);
$media_index=0;
$search_ice=0;
$search_ip=0;
$contact_header='';
foreach ($_lines as $_line) {
if (preg_match("/^(Diversion: ).*;(.*)$/", $_line, $m)) {
$diversions[]=$m[1].$m[2];
}
if (preg_match("/^Cseq:\s*\d+\s*(.*)$/i", $_line, $m)) {
$status_for_method=$m[1];
}
if (preg_match("/^c=IN \w+ ([\d|\w\.]+)/i", $_line, $m)) {
$media['ip']=$m[1];
}
if (preg_match("/^m=(\w+) (\d+) /i", $_line, $m)) {
$media_index++;
$search_ice=1;
$search_ip=1;
$media['streams'][$media_index]=array(
'type' => $m[1],
'ip' => $media['ip'],
'port' => $m[2],
'ice' => ''
);
}
if ($search_ip && preg_match("/^c=IN \w+ ([\d|\w\.]+)/i", $_line, $m)) {
$media['streams'][$media_index]['ip']=$m[1];
$search_ip=0;
}
if ($search_ice && preg_match("/^a=ice/i", $_line, $m)) {
$media['streams'][$media_index]['ice']="ICE";
$search_ice=0;
}
}
$_els = explode(";", $_lines[0]);
$cell_content = "$_els[0]";
if ($status) {
$cell_content .= " for ".$status_for_method."";
}
if (is_array($diversions)) {
foreach ($diversions as $_diversion) {
$cell_content.="
$_diversion";
}
}
if (is_array($media['streams'])) {
foreach (array_keys($media['streams']) as $_key) {
$_stream = sprintf(
"%s: %s:%s %s",
$media['streams'][$_key]['type'],
$media['streams'][$_key]['ip'],
$media['streams'][$_key]['port'],
$media['streams'][$_key]['ice']
);
if ($media['streams'][$_key]['port']) {
$cell_content.="
$_stream";
} else {
$cell_content.="
$_stream";
}
}
}
$cell_content.="
";
print "
";
$packet_length = strlen($msg);
print "
$i/$this->rows |
$date";
if ($timeline && !isset($_seen_timeline[$timeline])) {
printf(" +%ds", $timeline);
$_seen_timeline[$timeline] = 1;
}
print " $packet_length bytes |
";
$column_current = 1;
while ($column_current <= count($this->column)) {
if ($arrow_possition == $column_current) {
/* First cell, first port, append extra cell */
if ($column_current < count($this->column) && $column_current < $msg_possition) {
print "";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo " | ";
}
$arrowColor = $status_color;
if ($arrow_direction == 'loop') {
print " | ";
}
if ($arrow_possition >= 2 * $msg_possition) {
$arrow_span = ($arrow_possition * 2) - 4;
echo "";
} else {
echo " | ";
}
if ($arrow_direction != 'loop') {
print "";
}
if ($arrow_direction == "left") {
print " $cell_content ";
} else {
print "$cell_content ";
}
echo " | ";
if ($column_current < count($this->column) && $column_current > $msg_possition) {
print "";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo " | ";
}
} else {
if ($msg_possition == $column_current) {
if ($msg_possition < $arrow_possition) {
print "";
if ($direction == 'out') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
} else {
print " | ";
if ($direction == 'out') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
}
} elseif ($arrow_possition != $column_current
&& ( $column_current == 1
|| ( $arrow_possition < $column_current
&& $arrow_possition != $msg_possition)
)) {
print " | ";
print " | ";
print " ";
} elseif ($arrow_possition == $msg_possition) {
echo " | | ";
}
echo "";
}
if ($arrow_possition == $column_current && $column_current == count($this->column)) {
echo "";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo " | ";
}
$column_current++;
if ($arrow_direction == 'loop') {
$seen_msg[$md5]++;
}
}
echo "
";
if (is_array($this->SIPProxies)) {
$IPels = explode(":", $fromip);
$justIP = $IPels[0];
foreach (array_keys($this->SIPProxies) as $localProxy) {
if ($localProxy == $justIP) {
$direction="out";
break;
}
}
}
/* Details */
$trace_span = count($this->column) * 2 + 3;
print "
";
}
print "
";
}
public function showText($proxyIP, $callid, $fromtag, $totag)
{
$this->getTrace($proxyIP, $callid, $fromtag, $totag);
print "
";
if (!count($this->trace_array)) {
print "SIP trace for session id $callid is not available.";
return false;
}
printf("SIP trace on proxy %s for session %s\n--\n\n", $proxyIP, $callid);
foreach (array_keys($this->trace_array) as $key) {
$i++;
printf(
"Packet %d at %s from %s to %s (%s)\n",
$i,
$this->trace_array[$key]['date'],
$this->trace_array[$key]['fromip'],
$this->trace_array[$key]['toip'],
$this->trace_array[$key]['direction']
);
printf(
"\n%s\n",
htmlspecialchars($this->trace_array[$key]['msg'])
);
print "---\n";
}
print "
";
}
public function togglePublicVisibility($callid, $fromtag, $public = '0')
{
$key="callid-".trim($callid).trim($fromtag);
if (!$public) {
$query = sprintf("delete from memcache where `key` = '%s'", addslashes($key));
$this->cdrtool->query($query);
} else {
$query = sprintf("delete from memcache where `key` = '%s'", addslashes($key));
$this->cdrtool->query($query);
$query = sprintf("insert into memcache values ('%s','public')", addslashes($key));
$this->cdrtool->query($query);
}
}
public function purgeRecords($days = '')
{
if ($this->enableThor) {
return true;
}
$b=time();
if ($days) {
$this->purgeRecordsAfter = $days;
} elseif (!$this->purgeRecordsAfter) {
$this->purgeRecordsAfter = 15;
}
$beforeDate=Date("Y-m-d", time()-$this->purgeRecordsAfter*3600*24);
$query = sprintf(
"SELECT id as min, time_stamp FROM %s ORDER BY id ASC limit 1",
addslashes($this->table)
);
if ($this->db->query($query)) {
if ($this->db->num_rows()) {
$this->db->next_record();
$min=$this->db->f('min');
$begindate=$this->db->f('date');
} else {
$log = sprintf("No records found in %s\n", $this->table);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
} else {
$log = sprintf("Error: %s (%s)\n", $this->db->Error, $query);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query=sprintf(
"select id as max from %s where time_stamp < '%s' order by id DESC limit 1",
addslashes($this->table),
addslashes($beforeDate)
);
if ($this->db->query($query) && $this->db->num_rows()) {
$this->db->next_record();
$max=$this->db->f('max');
} else {
$log=sprintf(
"No records found in %s before %s, records start after %s\n",
$this->table,
$beforeDate,
$begindate
);
syslog(LOG_NOTICE, $log);
print $log;
return false;
}
$deleted = 0;
$i = $min;
$interval = 1000;
$rows2delete = $max - $min;
$found = 0;
print "$rows2delete traces to delete between $min and $max\n";
while ($i<=$max) {
$found=$found+$interval;
if ($i + $interval < $max) {
$top=$i;
} else {
$top=$max;
}
$query=sprintf(
"delete low_priority from %s where id >= '%d' and id <='%d'",
addslashes($this->table),
addslashes($min),
addslashes($top)
);
if ($this->db->query($query)) {
$deleted = $deleted + $this->db->affected_rows();
} else {
$log = sprintf("Error: %s (%s)", $this->db->Error, $this->db->Errno);
syslog(LOG_NOTICE, $log);
return false;
}
if ($found > $progress * $rows2delete / 100) {
$progress++;
if ($progress % 10 == 0) {
print "$progress% ";
}
flush();
}
$i = $i + $interval;
}
print "\n";
$e = time();
$d = $e - $b;
$rps = 0;
if ($deleted && $d) {
$rps=$deleted/$d;
}
$log = sprintf(
"%s records before %s from %s deleted in %d s @ %.0f rps\n",
$deleted,
$beforeDate,
$this->table,
$d,
$rps
);
syslog(LOG_NOTICE, $log);
print $log;
return true;
}
}
class Media_trace
{
public $enableThor = false;
public $table = 'media_sessions';
function Media_trace($cdr_source)
{
global $DATASOURCES;
$this->cdr_source = $cdr_source;
$this->cdrtool = new DB_CDRTool();
if (!is_array($DATASOURCES[$this->cdr_source])) {
$log = sprintf("Error: datasource '%s' is not defined", $this->cdr_source);
print $log;
return 0;
}
if (strlen($DATASOURCES[$this->cdr_source]['enableThor'])) {
$this->enableThor = $DATASOURCES[$this->cdr_source]['enableThor'];
}
if ($this->enableThor) {
require("/etc/cdrtool/ngnpro_engines.inc");
require_once("ngnpro_soap_library.php");
if ($DATASOURCES[$this->cdr_source]['soapEngineId'] && in_array($DATASOURCES[$this->cdr_source]['soapEngineId'], array_keys($soapEngines))) {
$this->soapEngineId=$DATASOURCES[$this->cdr_source]['soapEngineId'];
$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, '');
// Instantiate the SOAP client
$this->soapclient = new WebService_NGNPro_SipPort($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);
} else {
print "Error: soapEngineID not defined in datasource $this->cdr_source";
return false;
}
} else {
if ($DATASOURCES[$this->cdr_source]['table']) {
$this->table = $DATASOURCES[$this->cdr_source]['table'];
}
$db_class = $DATASOURCES[$this->cdr_source]['db_class'];
if (class_exists($db_class)) {
$this->db = new $db_class;
} else {
printf("
Error: database class %s is not defined in datasource %s", $db_class, $this->cdr_source);
return false;
}
}
}
private function getTrace($proxyIP, $callid, $fromtag, $totag)
{
if ($this->enableThor) {
// get trace using soap request
if (!$proxyIP || !$callid || !$fromtag) {
echo "
Error: proxyIP or callid or fromtag are not defined
";
return false;
}
if (!is_object($this->soapclient)) {
print "
Error: soap client is not defined";
return false;
}
$filter = array(
'nodeIp' => $proxyIP,
'callId' => $callid,
'fromTag' => $fromtag,
'toTag' => $totag
);
$this->soapclient->addHeader($this->SoapAuth);
$result = $this->soapclient->getMediaTrace($filter);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != 1060) {
printf(
"
",
$this->SOAPurl,
$error_fault->detail->exception->errorstring,
$error_fault->detail->exception->errorcode
);
}
return false;
}
$this->info = json_decode($result);
} else {
if (!is_object($this->db)) {
print "
Error: no database connection defined";
return false;
}
// get trace from SQL
$query = sprintf(
"select info from %s where call_id = '%s' and from_tag = '%s' and to_tag= '%s'",
addslashes($this->table),
addslashes($callid),
addslashes($fromtag),
addslashes($totag)
);
if (!$this->db->query($query)) {
printf(
"
Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
return false;
}
if ($this->db->num_rows()) {
$this->db->next_record();
$this->info = json_decode($this->db->f('info'));
}
}
}
public function show($proxyIP, $callid, $fromtag, $totag)
{
if ($_SERVER['HTTPS'] == "on") {
$protocolURL = "https://";
} else {
$protocolURL = "http://";
}
$this->getTrace($proxyIP, $callid, $fromtag, $totag);
if (!is_object($this->info)) {
echo "
";
return false;
}
if (!count($this->info->streams)) {
echo "
No RTP media streams have been established
";
return;
}
print "
";
print "";
foreach (array_values($this->info->streams) as $_val) {
$_diff=$_val->end_time-$_val->timeout_wait;
$seen_stamp[$_val->start_time]++;
$seen_stamp[$_val->end_time]++;
$seen_stamp[$_diff]++;
$media_types[]=$_val->media_type;
}
print "
Media Information
";
print "
";
printf("Call duration | %s |
", $this->info->duration);
list($relay_ip, $relay_port)=explode(":", $this->info->streams[0]->caller_local);
printf("Media relay | %s |
", $relay_ip);
print "
";
print "
Media Streams
";
print "
";
print " | ";
foreach (array_values($media_types) as $_type) {
printf("%s | ", ucfirst($_type));
}
print "
";
foreach ($this->info->streams[0] as $_val => $_value) {
printf("%s | ", ucfirst(preg_replace("/_/", " ", $_val)));
$j=0;
while ($j < count($media_types)) {
printf("%s | ", $this->info->streams[$j]->$_val);
$j++;
}
printf("
\n");
}
print "
";
print "
Stream Succession
";
$w_legend_bar = 500;
$w_text = 30;
$stamps = array_keys($seen_stamp);
sort($stamps);
$w_table = $w_legend_bar + $w_text;
print "
";
$j = 0;
$_index = 0;
foreach (array_values($this->info->streams) as $_val) {
if ($_val->status == 'unselected ice candidate') {
continue;
}
$_index = $_index+$_val->start_time;
$_duration = $_val->end_time-$_val->start_time;
$_timeout = $_val->timeout_wait;
$duration_print = $_duration;
if ($_val->status == 'conntrack timeout') {
$w_duration = intval(($_duration-$_timeout)*$w_legend_bar/$this->info->duration);
$w_timeout = intval($_timeout*$w_legend_bar/$this->info->duration);
$duration_print = $_duration - $_timeout;
} elseif ($_val->status == 'no-traffic timeout') {
$w_duration = intval($_duration*$w_legend_bar/$this->info->duration);
$w_timeout = intval($_timeout*$w_legend_bar/$this->info->duration);
} elseif ($_val->status == 'closed') {
$w_duration = intval($_duration * $w_legend_bar / $this->info->duration);
$w_timeout = 0;
}
$w_start_time = intval($_index*$w_legend_bar/$this->info->duration);
$w_rest = $w_legend_bar-$w_duration-$w_timeout-$w_start_time;
$w_duration_p = ($w_legend_bar/$w_duration) * 100;
$w_timeout = 0;
if ($w_timeout > 0) {
$w_timeout_p = ($w_legend_bar/$w_timeout) * 100;
}
$w_start_p = 0;
if ($w_start_time > 0) {
$w_start_p = ($w_legend_bar/$w_start_time)* 100;
}
//printf ("%s, %s, %s, %s
\n",$w_start_p,$w_duration_p,$w_timeout_p,$w_rest);
if ($_val->caller_packets != '0' && $_val->callee_packets != '0') {
print "$_val->media_type | ";
print "\n";
//print "\n";
print "";
print " \n";
print " $duration_print \n";
if ($_val->timeout_wait) {
print " $_timeout \n";
} else {
print " \n";
}
//print " | \n";
//print " \n";
print " |
";
} elseif ($_val->status == 'unselected ICE candidate') {
print "ICE session |
";
} else {
print "No stream data found |
";
}
}
print "
";
print "
Legend";
print "
| Session data |
| Timeout period |
";
}
}
include_once("phone_images.php");
function getImageForUserAgent($msg)
{
global $userAgentImages;
$msg_lines = explode("\n", $msg);
foreach ($msg_lines as $line) {
$els = explode(":", $line);
if (strtolower($els[0]) == 'user-agent' || strtolower($els[0]) == 'server') {
foreach ($userAgentImages as $agentRegexp => $image) {
if (preg_match("/^(user-agent|server):.*$agentRegexp/i", $line)) {
return $image;
}
}
}
}
return "unknown.png";
}
function isThorNode($ip, $sip_proxy)
{
if (!$ip || !$sip_proxy) {
return false;
}
$socket = fsockopen($sip_proxy, 9500, $errno, $errstr, 1);
if (!$socket) {
return false;
}
$request=sprintf("is_online %s as sip_proxy", $ip);
if (fputs($socket, "$request\r\n") !== false) {
$ret = trim(fgets($socket, 4096));
fclose($socket);
} else {
fclose($socket);
return false;
}
if ($ret == 'Yes') {
return true;
} else {
return false;
}
}
?>