Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F7313181
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
78 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/cdrlib.phtml b/cdrlib.phtml
index ce9e3ca..c721003 100644
--- a/cdrlib.phtml
+++ b/cdrlib.phtml
@@ -1,2136 +1,2135 @@
<?
if (!$maxrowsperpage) $maxrowsperpage=15;
$tz=$CDRTool['provider']['timezone'];
putenv("TZ=$tz");
class CDRS {
var $CDR_class = 'CDR';
var $intAccessCode = '00';
var $natAccessCode = '0';
var $RatingEngineSocket = false;
var $maxrowsperpage = 15;
var $status = array();
var $normalizedField = 'Normalized';
var $DestinationIdField = 'DestinationId';
var $BillingIdField = 'UserName';
var $sipTraceDataSource = 'sip_trace';
var $defaults = array();
var $whereUnnormalized = '';
var $skipNormalize = false;
var $reNormalize = false;
var $usageKeysForDeletionFromCache = array();
var $mc_key_mu_prefix = 'mu:';
var $CDRNormalizationFields=array('id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'username' => 'UserName',
'domain' => 'Realm',
'gateway' => 'NASIPAddress',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'BillingPartyId' => 'UserName',
'price' => 'Price',
'DestinationId' => 'DestinationId'
);
function _readCDRNormalizationFieldsFromDB() {
foreach (array_keys($this->CDRNormalizationFields) as $field) {
$mysqlField=$this->CDRNormalizationFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function _readCDRFieldsFromDB() {
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField=$this->CDRFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function CDRS($cdr_source) {
global $CDRTool;
global $DATASOURCES;
global $memcache_server;
global $RatingEngine;
if (!$DATASOURCES[$cdr_source] || !$DATASOURCES[$cdr_source]['db_class']) {
$log="Error: cdr_source or database not defined\n";
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
$this->initDefaults();
$this->cdrtool = new DB_CDRTool();
$this->cdr_source = $cdr_source;
$this->CDRTool = $CDRTool;
$this->rating_settings = $RatingEngine;
$this->DATASOURCES = $DATASOURCES;
$this->cdrtool->Halt_On_Error="no";
$this->table = $this->DATASOURCES[$this->cdr_source]['table'];
if (!$memcache_server && $this->defaults['START_MEMCACHE']) {
// for debian systems read the settings from /etc/default/cdrtool
if (preg_match("/yes/i",$this->defaults['START_MEMCACHE'])) {
$memcache_server=$this->defaults['MEMCACHE_IP'].":".$this->defaults['MEMCACHE_PORT'];
} else {
unset($memcache_server);
}
}
if ($memcache_server) {
$mc=new Memcache;
list($memcache_host,$memcache_port)=explode(":",$memcache_server);
if ($mc->pconnect($memcache_host,$memcache_port)) {
$this->mc = &$mc;
if ($mc_stats=$this->mc->getStats()) {
$this->mc_usage=$mc_stats['bytes']/$mc_stats['limit_maxbytes']*100;
}
$log=sprintf ("Connected to memcache %s:%d, usage: %.02f/%.02f MB (%.0f%s), keys: %s\n",$memcache_host,$memcache_port,$mc_stats['bytes']/1024/1024,$mc_stats['limit_maxbytes']/1024/1024,$this->mc_usage,"%",$mc_stats['curr_items']);
} else {
$log=sprintf ("Connection to memcache %s:%d failed\n",$memcache_host,$memcache_port);
}
syslog(LOG_NOTICE, $log);
}
// init names of CDR fields
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField=$this->CDRFields[$field];
$_field=$field."Field";
$this->$_field=$mysqlField;
}
if ($this->DATASOURCES[$this->cdr_source]['rating']) {
$this->ratingEnabled = 1;
$this->rating = $this->DATASOURCES[$this->cdr_source]['rating'];
if ($this->DATASOURCES[$this->cdr_source]['showRate']) $this->showRate = $this->DATASOURCES[$this->cdr_source]['showRate'];
if ($this->DATASOURCES[$this->cdr_source]['rateField']) $this->rateField = $this->DATASOURCES[$this->cdr_source]['rateField'];
if ($this->DATASOURCES[$this->cdr_source]['priceField']) $this->priceField = $this->DATASOURCES[$this->cdr_source]['priceField'];
}
// connect to the CDR database(s)
$_dbClass = $this->DATASOURCES[$this->cdr_source]['db_class'];
if (is_array($_dbClass)) {
if (class_exists($_dbClass[0])) $this->primary_database = $_dbClass[0];
if (class_exists($_dbClass[1])) $this->secondary_database = $_dbClass[1];
} else {
$this->primary_database = $_dbClass;
}
if(!class_exists($this->primary_database)) {
$log="Error instantiating db class: $this->primary_database\n";
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
$this->CDRdb = new $this->primary_database;
// check db connectivity
if (!$this->CDRdb->query('SELECT 1')) {
if ($this->secondary_database) {
$this->CDRdb = new $this->secondary_database;
if (!$this->CDRdb->query('SELECT 1')) {
$log="Error: failed to connect to the CDR database\n";
print $log;
syslog(LOG_NOTICE, $log);
return 0;
} else {
$this->CDRdb1 = new $this->secondary_database;
$this->db_class = $this->secondary_database;
}
}
} else {
$this->CDRdb1 = new $this->primary_database;
$this->db_class = $this->primary_database;
}
if ($this->DATASOURCES[$this->cdr_source]['DestinationIdField']) {
$this->DestinationIdField = $this->DATASOURCES[$this->cdr_source]['DestinationIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['normalizedField']) {
$this->normalizedField=$this->DATASOURCES[$this->cdr_source]['normalizedField'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['intAccessCode'])) {
$this->intAccessCode=$this->DATASOURCES[$this->cdr_source]['intAccessCode'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['natAccessCode'])) {
$this->natAccessCode = $this->DATASOURCES[$this->cdr_source]['natAccessCode'];
}
if ($this->DATASOURCES[$this->cdr_source]['AccountsDBClass'] && class_exists($this->DATASOURCES[$this->cdr_source]['AccountsDBClass'])) {
$this->AccountsDB = new $this->DATASOURCES[$this->cdr_source]['AccountsDBClass'];
$this->AccountsDBClass = $this->DATASOURCES[$this->cdr_source]['AccountsDBClass'];
} else if (class_exists('DB_openser')) {
$this->AccountsDB = new DB_openser();
$this->AccountsDBClass = 'DB_openser';
}
if ($this->DATASOURCES[$this->cdr_source]['BillingIdField']) {
$this->BillingIdField = $this->DATASOURCES[$this->cdr_source]['BillingIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['sipTraceDataSource']) {
$this->sipTraceDataSource=$this->DATASOURCES[$this->cdr_source]['sipTraceDataSource'];
}
if ($this->DATASOURCES[$this->cdr_source]['domain_table']) {
$this->domain_table = $this->DATASOURCES[$this->cdr_source]['domain_table'];
}
if ($this->DATASOURCES[$this->cdr_source]['skipNormalize']) {
$this->skipNormalize = $this->DATASOURCES[$this->cdr_source]['skipNormalize'];
}
if ($this->DATASOURCES[$this->cdr_source]['enableThor']) {
$this->enableThor = $this->DATASOURCES[$this->cdr_source]['enableThor'];
}
if (is_array($this->CDRTool['normalize']['CS_CODES'])) $this->CS_CODES=array_keys($this->CDRTool['normalize']['CS_CODES']);
$this->missed_calls = $this->DATASOURCES[$this->cdr_source]['missed_calls'];
$this->traceInURL = $this->DATASOURCES[$this->cdr_source]['traceInURL'];
$this->traceOutURL = $this->DATASOURCES[$this->cdr_source]['traceOutURL'];
$this->protocolTraceURL = $this->DATASOURCES[$this->cdr_source]['protocolTraceURL'];
$spath = explode("/",$_SERVER["PHP_SELF"]);
$last = count($spath)-1;
$this->scriptFile=$spath[$last];
$this->next = $_REQUEST["next"];
$this->export = $_REQUEST["export"];
$this->trace = $_REQUEST["trace"];
if ($this->export) {
$this->maxrowsperpage=10000000;
} else {
if ($_REQUEST["maxrowsperpage"]) {
$this->maxrowsperpage = $_REQUEST["maxrowsperpage"];
} else {
$this->maxrowsperpage = "25";
}
}
// Init memcache key names to be unique per datasource
$this->mc_key_init = $this->cdr_source.':quotaCheckInit';
$this->mc_key_domains = $this->cdr_source.':domains';
$this->mc_key_accounts = $this->cdr_source.':accounts';
$this->LoadDisconnectCodes();
$this->LoadDestinations();
$this->LoadENUMtlds();
$this->LoadDomains();
$this->getCDRtables();
$this->initOK=1;
}
function initDefaults() {
if (is_readable('/etc/default/cdrtool')) {
$defaultContentLines=explode("\n",file_get_contents('/etc/default/cdrtool'));
foreach ($defaultContentLines as $_line) {
list($defaults_key, $defaults_value)=explode("=",$_line);
if (strlen($defaults_value)) $this->defaults[trim($defaults_key)]=trim($defaults_value);
}
}
}
function LoadDomains() {
}
function LoadAccounts() {
}
function LoadDestinations() {
$_destinations=array();
$_SipDestinations=array();
$this->destinationsCount=0;
$this->sipDestinationsCount=0;
//if (is_object($this->mc) && $mc_destinations = $this->mc->get('destinations') && $mc_SipDestinations = $this->mc->get('SipDestinations')) {
if (is_object($this->mc) && $mc_destinations = $this->mc->get('destinations')) {
$_dests=explode("\n",$mc_destinations);
foreach ($_dests as $_dest) {
if (!strlen($_dest)) continue;
$this->destinationsCount++;
$_els=explode("=",$_dest) ;
$_els_parts=explode(";",$_els[0]);
$_destinations[$_els_parts[0]][$_els_parts[1]]=$_els[1];
}
$mc_SipDestinations = $this->mc->get('SipDestinations');
$_SipDests=explode("\n",$mc_SipDestinations);
foreach ($_SipDests as $_dest) {
if (!strlen($_dest)) continue;
$this->sipDestinationsCount++;
$_els=explode("=",$_dest) ;
$_els_parts=explode(";",$_els[0]);
$_SipDestinations[$_els_parts[0]][$_els_parts[1]]=$_els[1];
}
} else {
$query="select * from destinations";
if ($this->CDRTool['filter']['aNumber']) {
$faNumber=$this->CDRTool['filter']['aNumber'];
$query .= " where subscriber = '$faNumber' or
(subscriber = '' and domain = '' and gateway = '') ";
} else if ($this->CDRTool['filter']['domain']) {
$fdomain=$this->CDRTool['filter']['domain'];
$query .= " where domain = '$fdomain' or
(subscriber = '' and domain = '' and gateway = '') ";
} else if ($this->CDRTool['filter']['gateway']) {
$fgateway=$this->CDRTool['filter']['gateway'];
$query .= " where gateway = '$fgateway' or
(subscriber = '' and domain = '' and gateway = '') ";
}
$this->cdrtool->query($query);
$mc_value_destinations = "\n";
$mc_value_SipDestinations = "\n";
while($this->cdrtool->next_record()) {
$gateway = trim($this->cdrtool->Record['gateway']);
$domain = trim($this->cdrtool->Record['domain']);
$subscriber = trim($this->cdrtool->Record['subscriber']);
$id = trim($this->cdrtool->Record['dest_id']);
$name = trim($this->cdrtool->Record['dest_name']);
$name_print = $this->cdrtool->Record['dest_name']." (".$id.")";
if (strstr($id,'@')) {
// SIP destination
$this->sipDestinationsCount++;
if ($subscriber) {
$_SipDestinations[$subscriber][$id]=$name;
if (is_object($this->mc)) $mc_value_SipDestinations.=$subscriber.";".$id."=".$name."\n";
continue;
}
if ($domain) {
$_SipDestinations[$domain][$id]=$name;
if (is_object($this->mc)) $mc_value_SipDestinations.=$domain.";".$id."=".$name."\n";
continue;
}
if ($gateway) {
$_SipDestinations[$gateway][$id]=$name;
if (is_object($this->mc)) $mc_value_SipDestinations.=$gateway.";".$id."=".$name."\n";
continue;
}
if ($id) {
$_SipDestinations["default"][$id]=$name;
if (is_object($this->mc)) $mc_value_SipDestinations.="default;".$id."=".$name."\n";
}
} else {
// PSTN destination
$this->destinationsCount++;
if ($subscriber) {
$_destinations[$subscriber][$id]=$name;
if (is_object($this->mc)) $mc_value_destinations.=$subscriber.";".$id."=".$name."\n";
continue;
}
if ($domain) {
$_destinations[$domain][$id]=$name;
if (is_object($this->mc)) $mc_value_destinations.=$domain.";".$id."=".$name."\n";
continue;
}
if ($gateway) {
$_destinations[$gateway][$id]=$name;
if (is_object($this->mc)) $mc_value_destinations.=$gateway.";".$id."=".$name."\n";
continue;
}
if ($id) {
$_destinations["default"][$id]=$name;
if (is_object($this->mc)) $mc_value_destinations.="default;".$id."=".$name."\n";
}
}
}
if (is_object($this->mc)) {
if ($this->mc->set('destinations',$mc_value_destinations,0,0)) {
$log=sprintf("Saved %d destinations in memcache key destinations",$this->destinationsCount);
syslog(LOG_NOTICE, $log);
}
if ($this->mc->set('SipDestinations',$mc_value_SipDestinations,0,0)) {
$log=sprintf("Saved %d SIP destinations in memcache key SipDestinations",$this->sipDestinationsCount);
syslog(LOG_NOTICE, $log);
}
}
}
$this->destinations = &$_destinations;
$this->sipDestinations = &$_SipDestinations;
if (is_array($this->destinations)) {
foreach ($this->destinations as $key => $val) {
$this->destinations_length[$key] = max(array_map(strlen, array_keys($val)));
}
}
$c=$this->destinationsCount + $this->sipDestinationsCount;
return $c;
}
function LoadENUMtlds() {
$_ENUMtlds =array();
if (is_object($this->mc) && $_value = $this->mc->get('ENUMtlds')) {
$_ENUMtlds=json_decode($_value,true);
$this->ENUMtlds = &$_ENUMtlds;
$c=count($this->ENUMtlds);
} else {
$query="select * from billing_enum_tlds";
$this->cdrtool->query($query);
$mc_value = "\n";
while($this->cdrtool->next_record()) {
$_ENUMtlds[trim($this->cdrtool->Record['enum_tld'])]=
array('discount' => trim($this->cdrtool->Record['discount']),
'e164_regexp' => trim($this->cdrtool->Record['e164_regexp'])
);
}
if (is_object($this->mc)) {
if ($this->mc->set('ENUMtlds',json_encode($_ENUMtlds),0,0)) {
$log=sprintf("Saved %d ENUM TLDs in memcache key ENUMtlds",count($_ENUMtlds));
syslog(LOG_NOTICE, $log);
}
}
$this->ENUMtlds = &$_ENUMtlds;
$c=count($this->ENUMtlds);
}
return count($this->ENUMtlds);
}
function LoadDisconnectCodes() {
}
function initForm() {
}
function searchForm() {
}
function showTableHeader($begin_datetime,$end_datetime) {
}
function showTableHeaderStatistics($begin_datetime,$end_datetime) {
}
function showResultsMenu($hide_rows="") {
global $loginname;
$REMOTE_ADDR = $_SERVER["REMOTE_ADDR"];
if (!$this->export) {
print "
<form action=log.phtml method=post>
<table border=0 align=center>
<tr>
<td><a href=\"$this->url_edit\" >Refine search</a>
| <a href=\"$this->url_run\">Refresh</a>
</td>
";
$log_query="insert into log
(date,login,ip,url,results,rerun,reedit,datasource)
values
(NOW(),'$loginname','$REMOTE_ADDR','$this->url','$this->rows','$this->url_run','$this->url_edit','$this->cdr_source')";
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if ($this->rows) {
print "<td> | <a href=\"$this->url_export\" target=_new>Export results to file</a></td>";
}
print "
<td valign=middle>
| Save a description for this query:
</td>
<td valign=middle>
<input type=text name=log_description value=\"$old_description\">
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
<input type=submit value=Save>
</td>
</form>
";
print "
</tr>
</table>
";
if (!$hide_rows) {
print "
<table width=100%>
<tr>
<td align=center>
";
if ($this->rows == 0) {
print "No records found.";
} else {
print "$this->rows records found. ";
}
print "</td>
</tr>
</table>
";
}
}
}
function showResultsMenuSubscriber($hide_rows="") {
global $loginname;
$REMOTE_ADDR = $_SERVER["REMOTE_ADDR"];
if (!$this->export) {
print "
<form action=log.phtml method=post>
<table border=0 align=center>
<tr>
<td>
<td>
<a href=\"$this->url_edit\">Refine search</a>
| <a href=\"$this->url_run\">Refresh</a>
</td>
";
$log_query="insert into log
(date,login,ip,url,results,rerun,reedit,datasource)
values
(NOW(),'$loginname','$REMOTE_ADDR','$this->url','$this->rows','$this->url_run','$this->url_edit','$this->cdr_source')";
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if (!$this->CDRTool['filter']['aNumber']) {
if ($this->rows) {
print " | <a href=\"$this->url_export\" target=_new>Export results to file</a>";
}
print "
</td>
<td valign=middle>
| Save a description for this query:
</td>
<td valign=middle>
<input type=text name=log_description value=\"$old_description\">
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
<input type=submit value=Save>
</td>
</form>
";
}
print "
</tr>
</table>
";
if (!$hide_rows) {
print "
<table width=100%>
<tr>
<td align=center>
";
if ($this->rows == 0) {
print "No records found.";
} else {
print "$this->rows records found. ";
}
print "</td>
</tr>
</table>
";
}
}
}
function showDateTimeElements($f) {
print "
<tr>
<td valign=middle align=left>
<b>Start time</b>
</td>
<td>
";
print "Date: ";
$f->show_element("begin_year","");
print "-";
$f->show_element("begin_month","");
print "-";
$f->show_element("begin_day","");
print " Time: ";
$f->show_element("begin_hour","");
print ":";
$f->show_element("begin_min","");
print "
</td>
</tr>
<tr>
</tr>
<tr>
<td valign=middle align=left>
<b>Stop time</b>
</td>
<td>
";
print "Date: ";
$f->show_element("end_year","");
print "-";
$f->show_element("end_month","");
print "-";
$f->show_element("end_day","");
print " Time: ";
$f->show_element("end_hour","");
print ":";
$f->show_element("end_min","");
print "
</td>
</tr>
<tr>
</tr>
";
}
function showDataSources ($f) {
global $perm;
print "
<tr>
<td class=cdr valign=middle align=left>
<b>Data source</b>
</td>
<td valign=middle>";
$f->show_element("cdr_source","");
if (count($this->tables) > 0) {
print " Table: ";
$this->f->show_element("cdr_table","");
}
print "
</td>
</tr>
<tr>
";
}
function showPagination($next,$maxrows) {
$PHP_SELF=$_SERVER["PHP_SELF"];
if (!$this->export) {
print "
<p>
<table border=0 align=center>
<tr>
<td>
";
if ($next!=0 ) {
$show_next=$this->maxrowsperpage-$next;
if ($show_next < 0) {
$mod_show_next = $show_next-2*$show_next;
}
$url_prev=$PHP_SELF.$this->url."&action=search&next=$mod_show_next";
print "<a href=\"$url_prev\">Previous</a> ";
}
print "
</td>
<td>
";
if ($this->rows>$this->maxrowsperpage && $this->rows!=$maxrows) {
$show_next = $this->maxrowsperpage + $this->next;
$url_next = $PHP_SELF.$this->url."&action=search&next=$show_next";
print "<a href=\"$url_next\">Next</a>";
}
print "
</td>
</tr>
</table>
";
}
}
function show() {
}
function dump() {
}
function unNormalize($where="",$table) {
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
if ($this->skipNormalize) {
return 0;
}
if (!$this->normalizedField) {
return 0;
}
$query=sprintf("update %s set %s = '0' where %s ",
$table,
$this->normalizedField,
$where
);
$c=0;
if ($this->CDRdb->query($query)) {
$c=$this->CDRdb->affected_rows();
if ($c) {
if (is_object($this->mc)) $this->mc->delete($this->mc_key_init);
$query=sprintf("delete from memcache where `key`= '%s'",$this->mc_key_init);
$this->cdrtool->query($query);
}
}
$this->reNormalize=true;
return $c;
}
function buildWhereForUnnormalizedSessions () {
$this->whereUnnormalized = sprintf(" %s = '0'",$this->normalizedField);
if ($this->stopTimeField) $this->whereUnnormalized .= " and $this->stopTimeField != '0000-00-00 00:00:00' ";
if ($this->CDRFields['MediaTimeout']) {
/*
If we use MediaProxy information then eliminate all possible raise conditions
1. Session started and is in progress:
AcctStopTime = '0000-00-00 00:00:00'
AcctSessionTime = 0
MediaInfo is NULL
ConnectInfo_stop is NULL
2. Session closed with a negative response code ([4-6]XX):
AcctSessionTime = 0
AcctStopTime != '0000-00-00 00:00:00'
MediaInfo is NULL
ConnectInfo_stop is NULL
3. Session received a BYE:
ConnectInfo_stop is not NULL
AcctStopTime != '0000-00-00 00:00:00'
4. Media has timed-out:
MediaInfo = 'timeout'
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
5. MediaProxy update before BYE is received:
MediaInfo = ''
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
*/
$this->whereUnnormalized .= " and (ConnectInfo_stop is not NULL or MediaInfo is NULL or MediaInfo != '') ";
}
}
function getUnNormalized($where="",$table) {
- if (!$this->db_class) {
- return 0;
- }
-
if ($this->skipNormalize) {
- return 0;
+ return 1;
}
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
$ReNormalize = $_REQUEST["ReNormalize"];
if ($ReNormalize) $this->unNormalize($where,$table);
if (!$this->normalizedField) {
- return 0;
+ return 1;
}
$this->buildWhereForUnnormalizedSessions();
$query=sprintf("select count(*) as c from %s where %s and %s",
$table,
$where,
$this->whereUnnormalized
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$c=$this->CDRdb->f('c');
}
return $c;
}
function NormalizeCDRS($where="",$table) {
- if (!$this->db_class) {
- return 0;
- }
-
$b=time();
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
if ($this->skipNormalize) {
return 0;
}
if (!$this->normalizedField) {
return 0;
}
$lockName=sprintf("%s:%s",$this->cdr_source,$table);
if (!$this->getNormalizeLock($lockName)) {
return 1;
}
$this->buildWhereForUnnormalizedSessions();
$query=sprintf("select *, UNIX_TIMESTAMP($this->startTimeField) as timestamp
from %s where %s and %s",
$table,
$where,
$this->whereUnnormalized
);
$this->status['cdr_to_normalize']=0;
$this->status['normalized']=0;
$this->status['normalize_failures']=0;
$this->CDRdb->query($query);
$this->status['cdr_to_normalize']=$this->CDRdb->num_rows();
- if ($this->status['cdr_to_normalize']>0) {
+ if ($this->status['cdr_to_normalize'] > 0) {
if ($this->ratingEnabled) {
// The rating table will be used in each instance of
// CDR structure but we load the rating related data once
if ($this->DATASOURCES[$this->cdr_source]['EnableNetworkRating'] && $this->rating_settings['socketIP'] && $this->rating_settings['socketPort'] ) {
$fp = fsockopen ($this->rating_settings['socketIP'], $this->rating_settings['socketPort'], $errno, $errstr, 2);
if ($fp) {
$this->RatingEngineSocket = $fp;
} else {
$target=$this->rating_settings['socketIP'].":".$this->rating_settings['socketPort'];
print "<p>";
print "<font color=red>Cannot connect to rating engine $target: $errstr ($errno). </font>";
syslog(LOG_NOTICE, "Error: Cannot connect to rating engine $errstr ($errno)");
-
- // continue loading of rating tables
- $this->RatingTables = new RatingTables();
- $this->RatingTables->LoadRatingTables();
}
- } else {
- // network rating engine not available, load all rates in memory
- $this->RatingTables = new RatingTables();
- $this->RatingTables->LoadRatingTables();
}
+
+ // Load rating tables
+ $this->RatingTables = new RatingTables();
+ $this->RatingTables->LoadRatingTables();
}
} else {
return 0;
}
$this->usageKeysForDeletionFromCache=array();
while ($this->CDRdb->next_record()) {
+
$Structure=$this->_readCDRNormalizationFieldsFromDB();
$found++;
- if (count($Structure) < 6 ) {
- continue;
- }
-
$CDR = new $this->CDR_class(&$this, &$Structure);
if ($CDR->normalize("Save",$table)) {
$this->status['normalized']++;
} else {
$this->status['normalize_failures']++;
}
if ($this->reNormalize && $CDR->pricePrint && !$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]) {
$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]++;
}
if ($this->status['cdr_to_normalize'] > 1000) {
if ($found > $progress*$this->status['cdr_to_normalize']/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
}
flush();
}
}
}
if ($this->ratingEnabled && count($this->brokenRates) >0 ) {
- if ($this->CDRTool[rating][reportMissingRates]) {
+ if ($this->CDRTool['rating']['reportMissingRates']) {
if (count($this->brokenRates)) {
foreach (array_keys($this->brokenRates) as $dest) {
$missingRatesBodytext=$missingRatesBodytext."\nDestination id $dest (".$this->brokenRates[$dest]." calls)";
}
- $to=$this->CDRTool['provider'][toEmail];
- $from=$this->CDRTool['provider'][fromEmail];
+ $to=$this->CDRTool['provider']['toEmail'];
+ $from=$this->CDRTool['provider']['fromEmail'];
mail($to, "Missing CDRTool rates",$missingRatesBodytext, "From: $from");
}
}
}
if ($this->status['cdr_to_normalize']>0) {
$d=time()-$b;
$log=sprintf("Normalization done in %d s, memory usage: %0.2f MB",$d,memory_get_usage()/1024/1024);
syslog(LOG_NOTICE,$log );
if ($this->RatingEngineSocket) {
fclose($this->RatingEngineSocket);
}
}
if (count($this->usageKeysForDeletionFromCache)) {
if (is_object($this->mc)) {
if ($reset_quota_for = $this->mc->get('reset_quota_for')) {
$reset_quota_new=array_merge(json_decode($reset_quota_for),array_keys($this->usageKeysForDeletionFromCache));
} else {
$reset_quota_new=array_keys($this->usageKeysForDeletionFromCache);
}
$this->mc->set('reset_quota_for',json_encode(array_unique($reset_quota_new)));
}
}
return 1;
}
function NormalizeNumber($Number,$type="destination",$subscriber="",$domain="",$gateway="",$CountryCode="",$ENUMtld="") {
$this->CSCODE="";
$Number=strtolower(quoted_printable_decode($Number));
if ($pos = strpos($Number, "@")) {
// this is a SIP URI
$NumberStack['username'] = substr($Number,0,$pos);
if (strlen($NumberStack['username']) < 1) {
$NumberStack['username'] = "unknown";
}
$NumberStack['domain'] = substr($Number,$pos+1);
$NumberStack['delimiter'] = "@";
$pos = strpos($NumberStack['username'], ":");
if ($pos) {
$NumberStack['protocol'] = substr($NumberStack['username'],0,$pos+1);
$NumberStack['username'] = substr($NumberStack['username'],$pos+1);
}
if (preg_match("/^(.*)[=:;]/U",$NumberStack['domain'],$p)){
$NumberStack['domain'] = $p[1];
}
} else if (preg_match("/^([a-z0-9]+:)(.*)$/i",$Number,$m)) {
$oct=preg_split("/\./",$m[2]);
if(sizeof($oct)==4) {
// This is SIP address with no username
$NumberStack['username'] = "";
$NumberStack['domain'] = $m[2];
} else {
// This is SIP address with no domain
$NumberStack['username'] = $m[2];
$NumberStack['domain'] = "";
}
$NumberStack['protocol'] = $m[1];
$NumberStack['delimiter'] = "";
} else {
// This is a simple address like a phone number
$NumberStack['protocol'] = "";
$NumberStack['username'] = $Number;
$NumberStack['delimiter'] = "";
$NumberStack['domain'] = "";
}
if (preg_match("/^(.*)[=:;]/U",$NumberStack['domain'],$p)){
$NumberStack['domain'] = $p[1];
}
if ($type=="destination" && is_numeric($NumberStack['username'])) {
// strip custom prefix from destination
$usernameLength=strlen($NumberStack['username']);
if (is_array($this->CS_CODES)) {
foreach ($this->CS_CODES as $strip_prefix) {
$prefixLength = strlen($strip_prefix);
$restLength = $usernameLength-$prefixLength;
if ($restLength > 0 and preg_match("/^$strip_prefix(.*)$/",$NumberStack['username'],$m)) {
$NumberStack['username']=$m[1];
$this->CSCODE=$strip_prefix;
break;
}
}
}
if ($this->CDRTool['normalize']['E164Class'] && class_exists($this->CDRTool['normalize']['E164Class'])) {
$E164_class = $this->CDRTool['normalize']['E164Class'];
} else {
$E164_class = "E164_Europe";
}
if (!$CountryCode) $CountryCode=$this->CDRTool['normalize']['defaultCountryCode'];
$E164 = new $E164_class($this->intAccessCode, $this->natAccessCode,$CountryCode,$this->ENUMtlds[$ENUMtld]['e164_regexp']);
$NumberStack['E164']=$E164->E164Format($NumberStack['username']);
}
if ($type=="destination" && $NumberStack['E164']) {
// lookup destination id for the E164 number
$dst_struct = $this->lookupDestination($NumberStack[E164],$subscriber,$domain,$gateway);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = "+".$NumberStack[E164];
if (!$ENUMtld) {
$NumberStack['Normalized'] = $this->intAccessCode.
$NumberStack['E164'].
$NumberStack['delimiter'].
$NumberStack['domain'];
} else {
$NumberStack['Normalized'] =
$NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
} else {
$dst_struct = $this->lookupDestination($Number,$subscriber,$domain,$gateway);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
$NumberStack['Normalized'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
return $NumberStack;
}
function lookupDestination($destination,$subscriber="",$domain="",$gateway="") {
if (!$destination) {
return;
}
if (is_numeric($destination)){
return $this->getPSTNDestinationId($destination,$subscriber,$domain,$gateway);
} else {
return $this->getSIPDestinationId($destination,$subscriber,$domain,$gateway);
}
}
function getSIPDestinationId($destination,$subscriber,$domain,$gateway) {
if ($this->sipDestinations[$subscriber]) {
$sipDestinations = $this->sipDestinations[$subscriber];
$fCustomer="subscriber=$subscriber";
} elseif ($this->sipDestinations[$domain]) {
$sipDestinations = $this->sipDestinations[$domain];
$fCustomer="domain=$domain";
} elseif ($this->sipDestinations[$gateway]) {
$sipDestinations = $this->sipDestinations[$gateway];
$fCustomer="gateway=$gateway";
} else {
$sipDestinations = $this->sipDestinations['default'];
$fCustomer="default";
}
if ($sipDestinations[$destination]) {
$ret=array($destination,$sipDestinations[$destination]);
return $ret;
} else {
return false;
}
}
function getPSTNDestinationId($destination,$subscriber,$domain,$gateway) {
if ($this->destinations[$subscriber]) {
$codes = $this->destinations[$subscriber];
$maxLength = $this->destinations_length[$subscriber];
$fCustomer="subscriber=$subscriber";
} elseif ($this->destinations[$domain]) {
$codes = $this->destinations[$domain];
$maxLength = $this->destinations_length[$domain];
$fCustomer="domain=$domain";
} elseif ($this->destinations[$gateway]) {
$codes = $this->destinations[$gateway];
$maxLength = $this->destinations_length[$gateway];
$fCustomer="gateway=$gateway";
} else {
$codes = $this->destinations['default'];
$maxLength = $this->destinations_length['default'];
$fCustomer="default";
}
if (!$destination)
return false;
if (count($codes)>0) {
$length = min(strlen($destination), $maxLength);
for ($i=$length; $i>0; $i--) {
$buf = substr($destination, 0, $i);
if ($codes[$buf]) {
$dest_name=$codes[$buf];
$ret=array($buf,$dest_name);
return $ret;
}
}
}
return false;
}
function import($file) {
}
function RadiusRecordRead($fp) {
$keepreading=1;
while ($keepreading) {
$contents = fgets($fp, 8192);
if (preg_match("/^$/",$contents)) {
$keepreading=0;
} else {
$record[]=$contents;
}
}
return $record;
}
function RadiusRecordParse($record) {
unset($radiusParsed);
if (!is_array($record)) {
return 0;
}
foreach ($record as $line) {
$line=trim($line);
foreach (array_keys($this->radiusAttributes) as $attribute) {
if (preg_match("/$attribute = (.*)$/",$line,$m)) {
$value=preg_replace("/\"/","",trim($m[1]));
$radiusParsed[$attribute]= $value;
}
}
}
return $radiusParsed;
}
function getCDRtables() {
if (!is_object($this->CDRdb)) return 0;
$_tables=$this->CDRdb->table_names();
$t=count($_tables);
if ($this->table) $this->tables[]=$this->table;
while ($t <> 0 ) {
$_table=$_tables[$t]["table_name"];
if ($_table=='radacct') $this->tables[]='radacct';
if (preg_match("/^(\w+)\d{6}$/",$_table,$m)) {
if ($list_t >24) break;
$this->tables[]=$_table;
$list_t++;
}
$t--;
}
$this->tables=array_unique($this->tables);
}
function rotateTable($sourceTable,$month,$action) {
// create a new table tableYYYYMM and copy data from the main table into it
// if no month is supplied, the default is the previous month
if (!$month) $month=date('Ym', mktime(0, 0, 0, date("m")-1, "01", date("Y")));
if (!$sourceTable) $sourceTable=$this->table;
if (preg_match("/^(\w+)\d{6}$/",$sourceTable,$m)) {
$destinationTable=$m[1].$month;
} else {
$destinationTable=$sourceTable.$month;
}
print("rotateTable($sourceTable,$month,$destinationTable)\n");
if ($sourceTable == $destinationTable) {
$log=sprintf("Error: cannot copy records to the same table %s.\n",$destinationTable);
syslog(LOG_NOTICE,$log);
print $log;
return 0;;
}
$createTableFile=$this->CDRTool['Path'].$this->createTableFile;
if (!$this->createTableFile || !is_readable($createTableFile)) {
$log=sprintf("Error: cannot locate mysql creation file\n");
syslog(LOG_NOTICE,$log);
print $log;
return 0;;
}
$lockFile="/var/lock/CDRTool_".$this->cdr_source."_rotateTable.lock";
$f=fopen($lockFile,"w");
if (flock($f, LOCK_EX + LOCK_NB, $w)) {
if ($w) {
$log=sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE,$log);
print $log;
return 0;;
}
} else {
$log=sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE,$log);
print $log;
return 0;;
}
$b=time();
if (!preg_match("/^(\d{4})(\d{2})$/",$month,$m)) {
print "Error: Month $month must be in YYYYMM format\n";
return 0;
} else {
if ($m[2] > 12) {
print "Error: Month must be in YYYYMM format\n";
return 0;
}
$lastMonth=$month;
$startSQL=$m[1]."-".$m[2]."-01";
$stopSQL =date('Y-m-01', mktime(0, 0, 0, $m[2]+1, "01", $m[1]));
}
$query=sprintf("select count(*) as c from %s
where %s >='%s'
and %s < '%s'\n",
$sourceTable,
$this->CDRFields['startTime'],$startSQL,
$this->CDRFields['startTime'],$stopSQL);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsSourceTable=$this->CDRdb->f('c');
$log=sprintf ("Source table %s has %d records in month %s\n",$sourceTable,$rowsSourceTable,$month);
syslog(LOG_NOTICE,$log);
print $log;
if (!$rowsSourceTable) return 1;
} else {
$log=sprintf ("Error: %s (%s)\n",$this->table,$this->CDRdb->Error);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
$query=sprintf("select count(*) as c from %s\n", $destinationTable);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsDestinationTable = $this->CDRdb->f('c');
$log=sprintf ("Destination table %s has %d records\n",$destinationTable,$rowsDestinationTable);
syslog(LOG_NOTICE,$log);
print $log;
if ($rowsDestinationTable != $rowsSourceTable) {
$log=sprintf ("Error: source table has %d records and destination table has %d records\n",$rowsSourceTable,$rowsDestinationTable);
syslog(LOG_NOTICE,$log);
print $log;
} else {
$log=sprintf ("Tables are in sync\n");
syslog(LOG_NOTICE,$log);
print $log;
}
} else {
$log=sprintf ("%s (%s)\n",$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
if ($this->CDRdb->Errno==1146) {
$destinationTableTmp=$destinationTable."_tmp";
$query=sprintf("drop table if exists %s",$destinationTableTmp);
print($query);
$this->CDRdb->query($query);
if ($query=file_get_contents($createTableFile)) {
$query=preg_replace("/CREATE TABLE.*/","CREATE TABLE $destinationTableTmp (",$query);
if (!$this->CDRdb->query($query)) {
$log=sprintf ("Error creating table %s: %s, %s\n",$destinationTableTmp,$this->CDRdb->Error,$query);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
} else {
$log=sprintf ("Cannot read file %s\n",$createTableFile);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
// if we reached this point we start to copy records
$query=sprintf("insert into %s
select * from %s
where %s >='%s'
and %s < '%s'",
$destinationTableTmp,
$sourceTable,
$this->CDRFields['startTime'],$startSQL,
$this->CDRFields['startTime'],$stopSQL);
print ($query);
return ;
if ($this->CDRdb->query($query)) {
$e=time();
$d=$e-$b;
$rps=0;
if ($this->CDRdb->affected_rows() && $d) $rps=$this->CDRdb->affected_rows()/$d;
$log=printf ("Copied %d CDRs into table %s in %d s @ %.0f rps\n",$this->CDRdb->affected_rows(),$destinationTableTmp,$d,$rps);
syslog(LOG_NOTICE,$log);
print $log;
$query="rename table $destinationTableTmp to $destinationTableTmp";
if (!$this->CDRdb->query($query)) {
printf ("Error renaming table %s to %s: %s\n",$destinationTableTmp,$destinationTable,$this->CDRdb->Error);
return 0;
}
} else {
printf ("Error copying records in table %s: %s\n",$destinationTable,$this->CDRdb->Error);
return 0;
}
}
}
}
function purgeTable($sourceTable,$month) {
// delete records for a given month with minimal locking of database
// this function is useful after archive of CDR data using rotate script
$begin=time();
if ($month) {
if (!preg_match("/^(\d{4})(\d{2})$/",$month,$m)) {
print "Error: Month must be in YYYYMM format\n";
return 0;
} else {
$beginDate=$m[1]."-".$m[2]."-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, $m[2]+1, '01', $m[1]));
}
} else if (is_int($this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'])) {
$beginDate="1970-01-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, Date('m'), Date('d')-$this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'], Date('Y')));
} else {
return 0;
}
if (!$sourceTable) $sourceTable=$this->table;
$query=sprintf("select min(%s) as min,max(%s) as max from %s where %s >= '%s' and %s < '%s' ",
$this->CDRFields['id'],$this->CDRFields['id'],$sourceTable,$this->CDRFields['startTime'],$beginDate,$this->CDRFields['startTime'],$endDate);
print($query);
if (!$this->CDRdb->query($query)) {
printf ("Error: %s",$this->CDRdb->Error);
return 0;
}
$this->CDRdb->next_record();
$min=$this->CDRdb->f('min');
$max=$this->CDRdb->f('max');
if (!$min || !$max) {
$log=sprintf("No CDRs found in %s between %s and %s\n",$sourceTable,$beginDate,$endDate);
print $log;
syslog(LOG_NOTICE,$log);
return 0;
}
$deleted=0;
$i=$min;
$interval=100;
$rows2delete=$max-$min;
$found = 0;
print "$rows2delete CDRs will be deleted between $min and $max, $interval at a time\n";
while ($i <= $max) {
$found=$found+$interval;
if ($i + $interval < $max) {
$top=$i;
} else {
$top=$max;
}
$query=sprintf("delete low_priority from %s
where %s <= '%d' and %s >= '%d'",
$sourceTable,
$this->CDRFields['id'],
$top,
$this->CDRFields['id'],
$min);
if ($this->CDRdb->query($query)) {
$deleted=$deleted+$this->CDRdb->affected_rows();
} else {
$log=sprintf("Error: %s (%s)",$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
if ($found > $progress*$rows2delete/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
flush();
}
}
print ".";
flush();
$i=$i+$interval;
}
print "\n";
$end = time();
$duration = $end-$begin;
$rps=0;
if ($deleted && $duration) $rps=$deleted/$duration;
$log=sprintf("%s CDRs of month %s deleted from %s in %d s @ %.0f rps\n",$deleted,$month,$sourceTable,$duration,$rps);
syslog(LOG_NOTICE,$log);
print $log;
return 1;
}
function getMonthlyUsageFromCache($account) {
// retuns array with usage information saved with cacheMonthlyUsage
$_usage=array();
$mc_key=sprintf("%s%s",$this->mc_key_mu_prefix,$account);
if (is_object($this->mc)) {
// use memcache server
$previousUsage = $this->mc->get($mc_key);
} else {
// use MySQL server
$query=sprintf("select value from memcache where `key` ='%s'",$mc_key);
if ($this->cdrtool->query($query) && $this->cdrtool->num_rows()) {
$this->cdrtool->next_record();
$previousUsage=$this->cdrtool->f('value');
}
}
if ($previousUsage) {
$_usage=$this->parseMonthlyUsage($previousUsage);
}
return $_usage;
}
function cacheMonthlyUsage($accounts=array()) {
$saved_keys=0;
$failed_keys=0;
foreach (array_keys($accounts) as $_key) {
if (!$accounts[$_key]['usage']['calls']) continue;
$mc_value=sprintf("calls=%d duration=%d cost=%0.4f traffic=%0.2f",
$accounts[$_key]['usage']['calls'],
$accounts[$_key]['usage']['duration'],
$accounts[$_key]['usage']['cost'],
$accounts[$_key]['usage']['traffic']
);
$mc_key=sprintf("%s%s",$this->mc_key_mu_prefix,trim($_key));
if (is_object($this->mc)) {
// use memcache server
$mc_expire=time()+31*24*3600; // 31 days
if ($this->mc->set($mc_key,$mc_value,0,$mc_expire)) { // expire in 30 days
$saved_keys++;
} else {
$failed_keys++;
}
} else {
// use MySQL storage
$query=sprintf("delete from memcache where `key` = '%s'",$mc_key);
$this->cdrtool->query($query);
$query=sprintf("insert into memcache (`key`,`value`) values ('%s','%s')\n",
$mc_key,
$mc_value
);
if ($this->cdrtool->query($query) && $this->cdrtool->affected_rows()) {
$saved_keys++;
} else {
$failed_keys++;
}
}
}
$this->status['cached_keys']['saved_keys'] = $this->status['cached_keys']['saved_keys'] + $saved_keys;
$this->status['cached_keys']['failed_keys'] = $this->status['cached_keys']['failed_keys'] + $failed_keys;
return 1;
}
function parseMonthlyUsage($usage) {
if (!$usage) return ;
$_els=explode(" ",trim($usage));
$t=0;
while ($t < count($_els)) {
$_dict = explode("=",$_els[$t]);
$_key = $_dict[0];
$_value = $_dict[1];
if (!$_key) continue;
$_usage[$_key]=$_value;
$t++;
}
return $_usage;
}
function getNormalizeLock($lockname='') {
if (!$locker = new DB_Locker()) {
$log=sprintf("Error: cannot init locker database. ");
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$lockname) {
$log=sprintf("Error: no lockname provided. ");
syslog(LOG_NOTICE, $log);
return 0;
}
unset($this->lock_connection_id);
register_shutdown_function("unLockNormalization",$locker,$lockname);
$query=sprintf("SELECT GET_LOCK('%s',0)",$lockname);
if ($locker->query($query)) {
$locker->next_record();
$return = $locker->Record[0];
$query=sprintf("SELECT IS_USED_LOCK('%s')",$lockname);
if ($locker->query($query)) {
$locker->next_record();
$this->lock_connection_id=$locker->Record[0];
}
if ($return == 0) {
$log=sprintf(" Warning: data source %s normalize in progress, lock id %s ",$lockname,$this->lock_connection_id);
syslog(LOG_NOTICE, $log);
print "$log\n";
return 0;
} else {
$log=sprintf(" Normalize lock id %s aquired for %s ",$this->lock_connection_id,$lockname);
syslog(LOG_NOTICE, $log);
//print "$log\n";
return 1;
}
} else {
syslog(LOG_NOTICE, "Error: failed to request mysql lock");
return 0;
}
}
}
class CDRS_unknown extends CDRS {
function searchForm() {
return;
}
}
class E164_Europe extends E164 {
function E164_Europe ($intAccessCode='00', $natAccessCode='0',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([1-9][0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class E164_US extends E164 {
function E164_US($intAccessCode='011', $natAccessCode='[1-9][0-9]{2}',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class CDR {
// we need two db descriptors to update a CDR
// within same result set
var $idField = "RadAcctId";
var $callIdField = "AcctSessionId";
var $usernameField = "UserName";
var $domainField = "Realm";
var $gatewayField = "NASIPAddress";
var $gatewayPortField = "CiscoNASPort";
var $timestampField = "timestamp";
var $portIdField = "NASPortId";
var $portTypeField = "NASPortType";
var $startTimeField = "AcctStartTime";
var $stopTimeField = "AcctStopTime";
var $durationField = "AcctSessionTime";
var $inputTrafficField = "AcctInputOctets";
var $outputTrafficField = "AcctOutputOctets";
var $serviceTypeField = "ServiceType";
var $cNumberField = "CalledStationId";
var $aNumberField = "CallingStationId";
var $disconnectField = "H323DisconnectCause";
var $traceIn = "";
var $traceOut = "";
var $defaultApplicationType = "audio";
var $supportedApplicationTypes = array('audio',
'presence',
'message',
'video'
);
function CDR() {
}
function NormalizeDisconnect() {
$causePrint=$this->CDRS->disconnectCodesDescription[$this->disconnect]." (".$this->disconnect.")";
return $causePrint;
}
function traceOut () {
}
function traceIn () {
}
function show() {
}
function normalize($save="",$table) {
- if (!$table) $table=&$this->CDRS->table;
+ if (!$table) $table = $this->CDRS->table;
if ($this->CDRS->CSCODE && $CarrierInfo = $this->CDRS->CDRTool['normalize'][CS_CODES][$this->CDRS->CSCODE]) {
// We found a carrier so we set the BillingId
$this->BillingId = $CarrierInfo[BillingPartyId];
}
if ($save) {
+ if (!$this->id) {
+ return 0;
+ }
+
$query ="";
$query1 ="";
$query2 ="";
if ($this->CDRS->normalizedField) {
$Field=$this->CDRS->normalizedField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query .= " $Field = '1' ";
$updatedFields++;
}
if ($this->CDRS->DestinationIdField) {
$Field=$this->CDRS->DestinationIdField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".$this->DestinationId."' ";
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
$Field=$this->CDRS->usernameField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->usernameNormalized)."' ";
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
$Field=$this->CDRS->aNumberField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->aNumberNormalized)."' ";
$this->aNumber=$this->aNumberNormalized;
}
if ($this->CDRS->applicationTypeField && $this->applicationTypeNormalized) {
$Field=$this->CDRS->applicationTypeField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->applicationTypeNormalized)."' ";
$this->applicationType=$this->applicationTypeNormalized;
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
$Field=$this->CDRS->domainField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->domainNormalized)."' ";
$this->domainNumber=$this->domainNormalized;
$this->domain=$this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
$Field=$this->CDRS->cNumberField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->cNumberNormalized)."' ";
$this->cNumber=$this->cNumberNormalized;
}
- if ($this->CDRS->CustomerNameField && $this->CustomerName) {
- $Field=$this->CDRS->CustomerNameField;
- if ($updatedFields) $query .= ", ";
- $updatedFields++;
- $query.=" $Field = '".addslashes($this->CustomerName)."' ";
- }
-
- if ($this->CDRS->CustomerIdField && $this->CustomerId) {
- $Field=$this->CDRS->CustomerIdField;
- if ($updatedFields) $query .= ", ";
- $updatedFields++;
- $query.=" $Field = '".addslashes($this->CustomerId)."' ";
- }
-
if ($this->CDRS->BillingIdField && $this->BillingId) {
$Field=$this->CDRS->BillingIdField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->BillingId)."' ";
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
$Field=$this->CDRS->RemoteAddressField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->RemoteAddressNormalized)."' ";
}
if ($this->CDRS->CanonicalURIField && $this->CanonicalURINormalized && $this->CanonicalURINormalized!= $this->CanonicalURI) {
$Field=$this->CDRS->CanonicalURIField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".addslashes($this->CanonicalURINormalized)."' ";
}
if ($this->CDRS->ratingEnabled && $this->duration) {
+ /*
+ # since we changed the lookup of the rating entries directly to mysql query
+ # it seems that is faster not to go over the network
+
if ($this->CDRS->RatingEngineSocket && $this->NetworkRateDictionary) {
// get pricing from network rating engine
$this->lookupRateFromNetwork(&$this->NetworkRateDictionary,&$this->CDRS->RatingEngineSocket);
} else {
+ $Rate = new Rate($this->CDRS->rating_settings, $this->cdrtool);
- $Rate = new Rate($this->CDRS->rating_settings, $this->cdrtool);
$RateDictionary=array(
'callId' => $this->callId,
'timestamp' => $this->timestamp,
'duration' => $this->duration,
'DestinationId' => $this->DestinationId,
'inputTraffic' => $this->inputTraffic,
'outputTraffic' => $this->outputTraffic,
'BillingPartyId' => $this->BillingPartyId,
'domain' => $this->domain,
'gateway' => $this->gateway,
'RatingTables' => &$this->CDRS->RatingTables,
'applicationType' => $this->applicationType,
'aNumber' => $this->aNumber,
'cNumber' => $this->cNumber,
- 'destinationName' => $this->destinationName,
'ENUMtld' => $this->ENUMtld
);
$Rate->calculate(&$RateDictionary);
-
+
$this->pricePrint = $Rate->pricePrint;
$this->price = $Rate->price;
$this->rateInfo = $Rate->rateInfo;
-
}
+ */
+
+ $Rate = new Rate($this->CDRS->rating_settings, $this->cdrtool);
+
+ $RateDictionary=array(
+ 'callId' => $this->callId,
+ 'timestamp' => $this->timestamp,
+ 'duration' => $this->duration,
+ 'DestinationId' => $this->DestinationId,
+ 'inputTraffic' => $this->inputTraffic,
+ 'outputTraffic' => $this->outputTraffic,
+ 'BillingPartyId' => $this->BillingPartyId,
+ 'domain' => $this->domain,
+ 'gateway' => $this->gateway,
+ 'RatingTables' => &$this->CDRS->RatingTables,
+ 'applicationType' => $this->applicationType,
+ 'aNumber' => $this->aNumber,
+ 'cNumber' => $this->cNumber,
+ 'ENUMtld' => $this->ENUMtld
+ );
+
+ $Rate->calculate(&$RateDictionary);
+
+ $this->pricePrint = $Rate->pricePrint;
+ $this->price = $Rate->price;
+ $this->rateInfo = $Rate->rateInfo;
if ($this->CDRS->priceField) {
$Field=$this->CDRS->priceField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".$this->pricePrint."' ";
if ($this->CDRS->rateField ) {
$Field=$this->CDRS->rateField;
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=" $Field = '".$this->rateInfo."' ";
}
}
}
- if (!$this->id) {
- return 0;
- }
-
$query1 = sprintf("update %s set %s where %s = '%s'",$table,$query,$this->idField,$this->id);
if ($updatedFields) {
if ($this->CDRS->CDRdb1->query($query1)) {
if ($this->CDRS->CDRdb1->affected_rows()) {
if ($table == $this->CDRS->table) {
// cache usage only if current month
$_traffic=($this->inputTraffic+$this->outputTraffic)/2;
$_usage[$this->BillingPartyId]['usage']=array("calls" => 1,
"duration" => $this->duration,
"cost" => $Rate->price,
"traffic" => $_traffic
);
$this->cacheMonthlyUsage($_usage);
}
} else {
if (preg_match("/^(\w+)(\d{4})(\d{2})$/",$table,$m)) {
$previousTable=$m[1].date('Ym', mktime(0, 0, 0, $m[3]-1, "01", $m[2]));
$query2 = sprintf("update %s set %s where %s = '%s'",$previousTable,$query,$this->idField,$this->id);
if ($this->CDRS->CDRdb1->query($query2)) {
if ($previousTable == $this->CDRS->table) {
// cache usage only if current month
$_traffic=($this->inputTraffic+$this->outputTraffic)/2;
$_usage[$this->BillingPartyId]['usage']=array("calls" => 1,
"duration" => $this->duration,
"cost" => $Rate->price,
"traffic" => $_traffic
);
$this->cacheMonthlyUsage($_usage);
}
} else {
$log=sprintf ("Database error: %s (%s)",$this->CDRS->CDRdb1->Error,$this->CDRS->CDRdb1->Errno);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
}
return 1;
} else {
$log=sprintf ("Database error: %s (%s)",$this->CDRS->CDRdb1->Error,$this->CDRS->CDRdb1->Errno);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
} else {
if ($this->CDRS->BillingPartyIdField && $CarrierInfo['BillingPartyId']) {
$this->domain = $CarrierInfo[BillingDomain];
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
$this->username=$this->usernameNormalized;
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
$this->aNumber=$this->aNumberNormalized;
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
$this->domainNumber=$this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
$this->cNumber=$this->cNumberNormalized;
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
$this->RemoteAddress=$this->RemoteAddressNormalized;
}
}
return 1;
}
function cacheMonthlyUsage($accounts) {
if (!is_array($accounts)) return ;
foreach (array_keys($accounts) as $_account) {
if ($this->CallerIsLocal) {
$_usage = $this->CDRS->getMonthlyUsageFromCache($_account);
$accounts[$_account]['usage']['calls'] = $accounts[$_account]['usage']['calls'] + $_usage['calls'];
$accounts[$_account]['usage']['duration'] = $accounts[$_account]['usage']['duration'] + $_usage['duration'];
$accounts[$_account]['usage']['cost'] = $accounts[$_account]['usage']['cost'] + $_usage['cost'];
$accounts[$_account]['usage']['traffic'] = $accounts[$_account]['usage']['traffic'] + $_usage['traffic'];
} else {
return ;
}
}
$this->CDRS->cacheMonthlyUsage($accounts);
}
function isCallerLocal() {
return 0;
}
function isCalleeLocal() {
return 0;
}
function obfuscateCallerId() {
global $obfuscateCallerId;
if ($obfuscateCallerId) {
}
}
function lookupRateFromNetwork(&$RateDictionary,&$fp) {
$this->rateInfo='';
$this->pricePrint='';
$this->price='';
$countEndofLines=0;
$cmd="ShowPrice";
foreach (array_keys(&$RateDictionary) as $key) {
$cmd .=" ".$key."=".$RateDictionary[$key]." ";
}
$this->price = 0;
$this->pricePrint = "";
$this->rateInfo = "";
if (fputs($fp,"$cmd\n") !== false) {
$i=0;
while ($i < 100) {
$i++;
$line = fgets($fp,1024);
if (!$line) {
syslog(LOG_NOTICE, "Error: lookupRateFromNetwork(): connection to network socket died");
break;
}
if (preg_match("/^\n/",$line) || preg_match("/^END/",$line)) {
break;
}
if ($i == 1) {
$this->price = trim($line);
$this->pricePrint = number_format($this->price,4);
continue;
}
$this->rateInfo.=$line;
}
}
}
}
function getLocalTime($timezone,$timestamp) {
global $CDRTool;
if (!$timezone || $timezone == $CDRTool['provider']['timezone']) {
return date("Y-m-d H:i:s", $timestamp);
}
putenv("TZ=$timezone");
$startTimeLocal=date("Y-m-d H:i:s", $timestamp);
$timezone=$CDRTool['provider']['timezone'];
putenv("TZ=$timezone");
return $startTimeLocal;
}
function sec2hms ($duration) {
// return seconds in HH:MM:SS format
$sum1=$duration;
$duration_print="";
$duration_hour=floor($sum1/3600);
if ($duration_hour > 0) {
$sum1=$sum1-($duration_hour*3600);
$duration_print="$duration_hour:";
}
$duration_min=floor($sum1/60);
if ($duration_min > 0) {
$sum1=$sum1-($duration_min*60);
if ($duration_min < 10) {
$duration_min="0"."$duration_min";
}
$duration_print="$duration_print"."$duration_min:";
} else {
$duration_print="$duration_print"."00:";
}
if ($sum1< 10 ) {
$duration_sec="0"."$sum1";
} else {
$duration_sec=$sum1;
}
$duration_print="$duration_print"."$duration_sec";
return $duration_print;
}
function validDay($month,$day,$year) {
if (!$month || !$year) {
return $day;
}
while (1) {
if (!checkdate($month,$day,$year) && $day) {
$day--;
next;
} else {
break;
}
}
return $day;
}
$ratingLibFile=$CDRTool['Path']."/rating_lib.phtml";
if (is_readable($ratingLibFile)) {
require_once($ratingLibFile);
}
// include CDRTool modules defined in global.inc
foreach ($CDRToolModules as $module) {
$module_filename=$CDRTool['Path']."/cdrlib_".$module.".phtml";
if (is_readable($module_filename)) include($module_filename);
$module_filename=$CDRTool['Path']."/local/cdrlib_".$module.".phtml";
if (is_readable($module_filename)) include($module_filename);
}
function unLockNormalization ($dbid,$lockname) {
$query=sprintf("SELECT RELEASE_LOCK('%s')",$lockname);
$log=sprintf("Unlock %s",$lockname);
syslog(LOG_NOTICE, $log);
if (!$dbid->query($query)) {
$log="Error in unLockNormalization()";
syslog(LOG_NOTICE, $log);
}
}
?>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Feb 1, 10:56 AM (23 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3489240
Default Alt Text
(78 KB)
Attached To
Mode
rCDRT CDRTool
Attached
Detach File
Event Timeline
Log In to Comment