Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/library/cdr_generic.php b/library/cdr_generic.php
index eebf910..53bf7de 100644
--- a/library/cdr_generic.php
+++ b/library/cdr_generic.php
@@ -1,3423 +1,3356 @@
<?php
$tz = $CDRTool['provider']['timezone'];
putenv("TZ=$tz");
class CDRS {
var $CDR_class = 'CDR';
var $intAccessCode = '00';
var $natAccessCode = '0';
var $maxrowsperpage = 15;
var $status = array();
var $normalizedField = 'Normalized';
var $DestinationIdField = 'DestinationId';
var $BillingIdField = 'UserName';
var $defaults = array();
var $whereUnnormalized = '';
var $skipNormalize = false;
var $reNormalize = false;
var $usageKeysForDeletionFromCache = array();
var $localDomains = array();
var $trustedPeers = array();
var $maxCDRsNormalizeWeb = 500;
var $E164_class = 'E164_Europe';
var $quotaEnabled = false;
var $csv_writter = false;
var $CallerIsLocal = false;
var $CalleeIsLocal = false;
var $CDRNormalizationFields = array(
'id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'username' => 'UserName',
'domain' => 'Realm',
'gateway' => 'NASIPAddress',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'BillingPartyId' => 'UserName',
'sipRPID' => 'SipRPID',
'ResellerId' => 'BillingId',
'price' => 'Price',
'DestinationId' => 'DestinationId'
);
function _readCDRNormalizationFieldsFromDB()
{
foreach (array_keys($this->CDRNormalizationFields) as $field) {
$mysqlField = $this->CDRNormalizationFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function _readCDRFieldsFromDB($fields)
{
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField = $this->CDRFields[$field];
$CDRStructure[$mysqlField] = $this->CDRdb->f($mysqlField);
}
return $CDRStructure;
}
function initCDRFields()
{
// init names of CDR fields
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField = $this->CDRFields[$field];
$_field = $field."Field";
$this->$_field = $mysqlField;
}
}
function initDatabaseConnection()
{
// connect to the CDR database(s)
if(!$this->DATASOURCES[$this->cdr_source]['db_class']) {
$log = sprintf("Error: \$DATASOURCES['%s']['db_class'] is not defined (init)", $this->cdr_source);
syslog(LOG_NOTICE, $log);
return 0;
}
$_dbClass = $this->DATASOURCES[$this->cdr_source]['db_class'];
if (is_array($_dbClass)) {
if ($_dbClass[0]) $this->primary_database = $_dbClass[0];
if ($_dbClass[1]) $this->secondary_database = $_dbClass[1];
} else {
$this->primary_database = $_dbClass;
}
if(!class_exists($this->primary_database)) {
$log = sprintf("Error: database class '%s' is not defined", $this->primary_database);
syslog(LOG_NOTICE, $log);
return 0;
}
$this->CDRdb = new $this->primary_database;
// check db connectivity
if (!$this->CDRdb->query('SELECT 1')) {
$log = sprintf("Error: failed to connect to the primary CDR database %s\n", $this->primary_database);
syslog(LOG_NOTICE, $log);
if ($this->secondary_database) {
$this->CDRdb = new $this->secondary_database;
if (!$this->CDRdb->query('SELECT 1')) {
$log = sprintf("Error: failed to connect to the secondary CDR database %s\n", $this->secondary_database);
syslog(LOG_NOTICE, $log);
return 0;
} else {
$this->CDRdb1 = new $this->secondary_database;
$this->db_class = $this->secondary_database;
}
} else {
return 0;
}
} else {
$this->CDRdb1 = new $this->primary_database;
$this->db_class = $this->primary_database;
}
return 1;
}
function CDRS($cdr_source)
{
global $CDRTool;
global $DATASOURCES;
global $RatingEngine;
if (!$cdr_source) {
$log = "Error: cdr_source not defined\n";
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$DATASOURCES[$cdr_source]) {
$log = sprintf("Error: no such datasource defined (%s)\n", $cdr_source);
syslog(LOG_NOTICE, $log);
return 0;
}
$this->initDefaults();
$this->cdrtool = new DB_CDRTool();
$this->cdr_source = $cdr_source;
$this->CDRTool = $CDRTool;
$this->rating_settings = $RatingEngine;
$this->DATASOURCES = $DATASOURCES;
$this->cdrtool->Halt_On_Error = "no";
$this->table = $this->DATASOURCES[$this->cdr_source]['table'];
- #TODO remove me, I am used to temporary sync mysql data with mongo data
- if ($DATASOURCES[$cdr_source]['mongo_db']) {
- $mongo_db = $this->CDRTool['mongo_db'][$DATASOURCES[$this->cdr_source]['mongo_db']];
- $mongo_uri = $mongo_db['uri'];
- $mongo_replicaSet = $mongo_db['replicaSet'];
- $mongo_database = $mongo_db['database'];
- try {
- $mongo_connection = new Mongo("mongodb://$mongo_uri", array("replicaSet" => $mongo_replicaSet));
- $db = $mongo_connection->selectDB($mongo_database);
- $this->mongo_table = $db->selectCollection($this->table);
- } catch (Exception $e) {
- printf("<p>Caught exception in initDatabaseConnection(): %s", $e->getMessage());
- return 0;
- }
- } else {
- $this->mongo_table = NULL;
- }
-
$this->initCDRFields();
if ($this->DATASOURCES[$this->cdr_source]['rating']) {
$this->ratingEnabled = 1;
$this->rating = $this->DATASOURCES[$this->cdr_source]['rating'];
if ($this->DATASOURCES[$this->cdr_source]['showRate']) $this->showRate = $this->DATASOURCES[$this->cdr_source]['showRate'];
if ($this->DATASOURCES[$this->cdr_source]['rateField']) $this->rateField = $this->DATASOURCES[$this->cdr_source]['rateField'];
if ($this->DATASOURCES[$this->cdr_source]['priceField']) $this->priceField = $this->DATASOURCES[$this->cdr_source]['priceField'];
}
if ($this->DATASOURCES[$this->cdr_source]['UserQuotaClass']) {
$this->quotaEnabled = 1;
$this->quota_init_flag = $this->cdr_source.':quotaCheckInit';
$this->quota_reset_flag = $this->cdr_source.':reset_quota_for';
if ($this->DATASOURCES[$this->cdr_source]['daily_quota']) {
$this->daily_quota=$this->DATASOURCES[$this->cdr_source]['daily_quota'];
}
}
$this->initDatabaseConnection();
if ($this->DATASOURCES[$this->cdr_source]['DestinationIdField']) {
$this->DestinationIdField = $this->DATASOURCES[$this->cdr_source]['DestinationIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['normalizedField']) {
$this->normalizedField = $this->DATASOURCES[$this->cdr_source]['normalizedField'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['intAccessCode'])) {
$this->intAccessCode = $this->DATASOURCES[$this->cdr_source]['intAccessCode'];
}
if (strlen($this->DATASOURCES[$this->cdr_source]['natAccessCode'])) {
$this->natAccessCode = $this->DATASOURCES[$this->cdr_source]['natAccessCode'];
}
if ($this->DATASOURCES[$this->cdr_source]['db_subscribers']) {
if (class_exists($this->DATASOURCES[$this->cdr_source]['db_subscribers'])) {
$this->AccountsDB = new $this->DATASOURCES[$this->cdr_source]['db_subscribers'];
$this->db_subscribers = $this->DATASOURCES[$this->cdr_source]['db_subscribers'];
} else {
$log = sprintf(
"Error: subscribers database class %s is not defined",
$this->DATASOURCES[$this->cdr_source]['db_subscribers']
);
syslog(LOG_NOTICE, $log);
return 0;
}
} else if (class_exists('DB_opensips')) {
$this->AccountsDB = new DB_opensips();
$this->db_subscribers = 'DB_opensips';
} else {
$log = sprintf(
"Error: subscribers database is not defined, please define 'db_subscribers' in datasource '%s'",
$this->cdr_source
);
syslog(LOG_NOTICE, $log);
return 0;
}
if ($this->DATASOURCES[$this->cdr_source]['BillingIdField']) {
$this->BillingIdField = $this->DATASOURCES[$this->cdr_source]['BillingIdField'];
}
if ($this->DATASOURCES[$this->cdr_source]['E164_class']) {
if (class_exists($this->DATASOURCES[$this->cdr_source]['E164_class'])) {
$this->E164_class = $this->DATASOURCES[$this->cdr_source]['E164_class'];
} else {
printf(
"Error: E164 class '%s' defined in datasource %s does not exist, using default '%s'",
$this->DATASOURCES[$this->cdr_source]['E164_class'],
$this->cdr_source,
$this->E164_class
);
}
}
if ($this->DATASOURCES[$this->cdr_source]['sipTrace']) {
$this->sipTrace = $this->DATASOURCES[$this->cdr_source]['sipTrace'];
}
if ($this->DATASOURCES[$this->cdr_source]['mediaTrace']) {
$this->mediaTrace = $this->DATASOURCES[$this->cdr_source]['mediaTrace'];
}
if ($this->DATASOURCES[$this->cdr_source]['domain_table']) {
$this->domain_table = $this->DATASOURCES[$this->cdr_source]['domain_table'];
}
if ($this->DATASOURCES[$this->cdr_source]['skipNormalize']) {
$this->skipNormalize = $this->DATASOURCES[$this->cdr_source]['skipNormalize'];
}
if ($this->DATASOURCES[$this->cdr_source]['enableThor']) {
$this->enableThor = $this->DATASOURCES[$this->cdr_source]['enableThor'];
}
if (is_array($this->CDRTool['normalize']['CS_CODES'])) $this->CS_CODES=array_keys($this->CDRTool['normalize']['CS_CODES']);
$this->missed_calls = $this->DATASOURCES[$this->cdr_source]['missed_calls'];
$this->traceInURL = $this->DATASOURCES[$this->cdr_source]['traceInURL'];
$this->traceOutURL = $this->DATASOURCES[$this->cdr_source]['traceOutURL'];
$this->protocolTraceURL = $this->DATASOURCES[$this->cdr_source]['protocolTraceURL'];
$spath = explode("/",$_SERVER["PHP_SELF"]);
$last = count($spath)-1;
$this->scriptFile=$spath[$last];
$this->next = $_REQUEST["next"];
$this->export = $_REQUEST["export"];
$this->trace = $_REQUEST["trace"];
if ($this->export) {
$this->maxrowsperpage=10000000;
} else {
if ($_REQUEST["maxrowsperpage"]) {
$this->maxrowsperpage = $_REQUEST["maxrowsperpage"];
} else {
$this->maxrowsperpage = "25";
}
}
$this->LoadDisconnectCodes();
$this->LoadDestinations();
$this->LoadENUMtlds();
$this->LoadDomains();
$this->LoadTrustedPeers();
$this->getCDRtables();
if ($this->DATASOURCES[$this->cdr_source]['csv_writer_class']) {
$csv_writter_class=$this->DATASOURCES[$this->cdr_source]['csv_writer_class'];
if (class_exists($csv_writter_class)) {
$this->csv_writter = new $csv_writter_class(
$this->cdr_source,
$this->DATASOURCES[$this->cdr_source]['csv_directory'],
$this->db_subscribers
);
}
}
$this->initOK=1;
}
function initDefaults()
{
if (is_readable('/etc/default/cdrtool')) {
$defaultContentLines = explode("\n", file_get_contents('/etc/default/cdrtool'));
foreach ($defaultContentLines as $_line) {
list($defaults_key, $defaults_value) = explode("=", $_line);
if (strlen($defaults_value)) $this->defaults[trim($defaults_key)]=trim($defaults_value);
}
}
}
function LoadDomains()
{
}
function LoadTrustedPeers()
{
}
function LoadAccounts()
{
}
function LoadDestinations()
{
$_destinations = array();
$_destinations_sip = array();
$this->destinations_count = 0;
$this->destinations_sip_count = 0;
$query = sprintf("select `value` from memcache where `key` = 'destinations'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$b = time();
$this->cdrtool->next_record();
$_destinations = json_decode($this->cdrtool->f('value'),true);
foreach (array_keys($_destinations) as $_key1) {
foreach(array_keys($_destinations[$_key1]) as $_key2) {
$this->destinations_count = $this->destinations_count + count($_destinations[$_key1][$_key2]);
}
}
if (!$this->destinations_count) {
$log = "Error: cached destinations key contains no data";
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations_sip'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$this->cdrtool->next_record();
$_destinations_sip = json_decode($this->cdrtool->f('value'), true);
foreach (array_keys($_destinations_sip) as $_key1) {
foreach (array_keys($_destinations_sip[$_key1]) as $_key2) {
$this->destinations_sip_count = $this->destinations_count + count($_destinations_sip[$_key1][$_key2]);
}
}
}
/*
$e=time();
$log=sprintf("Read %d PSTN destinations from cache in %d seconds",$this->destinations_count,$e-$b);
syslog(LOG_NOTICE,$log);
if ($this->destinations_sip_count) {
$e=time();
$log=sprintf("Read %d SIP destinations from cache in %d seconds",$this->destinations_sip_count,$e-$b);
syslog(LOG_NOTICE,$log);
}
*/
$this->destinations = $_destinations;
$this->destinations_sip = $_destinations_sip;
unset($_destinations);
unset($_destinations_sip);
} else {
$this->CacheDestinations();
$this->destinations = $this->_destinations;
$this->destinations_sip = $this->_destinations_sip;
unset($this->_destinations);
unset($this->_destinations_sip);
}
if (is_array($this->destinations)) {
foreach (array_keys($this->destinations) as $_reseller) {
foreach ($this->destinations[$_reseller] as $key => $val) {
$this->destinations_length[$_reseller][$key] = max(array_map(strlen, array_keys($val)));
}
}
}
$c = $this->destinations_count + $this->destinations_sip_count;
return $c;
}
function CacheDestinations()
{
$this->_destinations = array();
$this->_destinations_sip = array();
$this->destinations_count = 0;
$this->destinations_sip_count = 0;
$b=time();
$query = "select * from destinations";
if ($this->CDRTool['filter']['aNumber']) {
$faNumber=$this->CDRTool['filter']['aNumber'];
$query .= sprintf(" where subscriber = '%s' or (subscriber = '' and domain = '' and gateway = '') ", addslashes($faNumber));
} else if ($this->CDRTool['filter']['domain']) {
$fdomain=$this->CDRTool['filter']['domain'];
$query .= sprintf(" where domain = '%s' or (subscriber = '' and domain = '' and gateway = '') ", addslashes($fdomain));
} else if ($this->CDRTool['filter']['gateway']) {
$fgateway=$this->CDRTool['filter']['gateway'];
$query .= sprintf(" where gateway = '%s' or (subscriber = '' and domain = '' and gateway = '') ",addslashes($fgateway));
}
$this->cdrtool->query($query);
if (!$this->cdrtool->num_rows()) {
$log = "Error: could not find any entries in the destinations table";
syslog(LOG_NOTICE, $log);
return 0;
}
$destinations_cache = "\n";
$destinations_sip_cache = "\n";
$this->destinations_count = 0;
$this->destinations_default_count = 0;
$this->destinations_gateway_count = 0;
$this->destinations_domain_count = 0;
$this->destinations_subscriber_count = 0;
$j=0;
while ($this->cdrtool->next_record()) {
$j++;
$reseller_id = $this->cdrtool->Record['reseller_id'];
$gateway = trim($this->cdrtool->Record['gateway']);
$domain = trim($this->cdrtool->Record['domain']);
$subscriber = trim($this->cdrtool->Record['subscriber']);
$dest_id = trim($this->cdrtool->Record['dest_id']);
$region = utf8_encode($this->cdrtool->Record['region']);
$name = utf8_encode($this->cdrtool->Record['dest_name']);
$name_print = $this->cdrtool->Record['dest_name']." (".$dest_id.")";
if (strstr($dest_id, '@')) {
// SIP destination
if ($subscriber) {
$this->_destinations_sip[$reseller_id][$subscriber][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($domain) {
$this->_destinations_sip[$reseller_id][$domain][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($gateway) {
$this->_destinations_sip[$reseller_id][$gateway][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
} elseif ($dest_id) {
$this->_destinations_sip[$reseller_id]["default"][$dest_id] = array(
'name' => $name,
'region' => $region
);
$this->destinations_sip_count++;
}
} else {
// PSTN destination
if (!is_numeric($dest_id)) {
$log = sprintf(
"Error: cannot load non-numeric destination '%s' from row id %d"
,$dest_id
,$this->cdrtool->Record['id']
);
syslog(LOG_NOTICE, $log);
continue;
}
if ($subscriber) {
$this->destinations_subscriber_count++;
$this->_destinations[$reseller_id][$subscriber][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
} elseif ($domain) {
$this->destinations_domain_count++;
$this->_destinations[$reseller_id][$domain][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
} elseif ($gateway) {
$this->destinations_gateway_count++;
$this->_destinations[$reseller_id][$gateway][$dest_id]=array(
'name' => $name,
'region'=> $region
);
$this->destinations_count++;
} elseif ($dest_id) {
$this->destinations_default_count++;
$this->_destinations[$reseller_id]["default"][$dest_id]=array(
'name' => $name,
'region' => $region
);
$this->destinations_count++;
}
}
}
$destinations_cache = json_encode($this->_destinations);
$destinations_sip_cache = json_encode($this->_destinations_sip);
$log = sprintf("PSTN destinations cache size: %0.2f MB", strlen($destinations_cache) / 1024 / 1024);
syslog(LOG_NOTICE, $log);
if ($destinations_sip_cache) {
$log = sprintf("SIP destinations cache size: %0.2f MB", strlen($destinations_sip_cache) / 1024 / 1024);
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$query = sprintf(
"update memcache set value = '%s' where `key` = 'destinations'",
addslashes($destinations_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf(
"Cached %d total, %d default, %d gateway, %d domain, %d subscriber destinations",
$this->destinations_count,
$this->destinations_default_count,
$this->destinations_gateway_count,
$this->destinations_domain_count,
$this->destinations_subscriber_count
);
syslog(LOG_NOTICE, $log);
} else {
$query = sprintf(
"insert into memcache (`key`,`value`) values ('destinations','%s')",
addslashes($destinations_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf(
"Cached %d total, %d default, %d gateway, %d domain, %d subscriber destinations",
$this->destinations_count,
$this->destinations_default_count,
$this->destinations_gateway_count,
$this->destinations_domain_count,
$this->destinations_subscriber_count
);
syslog(LOG_NOTICE, $log);
}
$query = sprintf("select `value` from memcache where `key` = 'destinations_sip'");
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->cdrtool->num_rows()) {
$query = sprintf(
"update memcache set value = '%s' where `key` = 'destinations_sip'",
addslashes($destinations_sip_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf("Cached %d SIP destinations", $this->destinations_sip_count);
syslog(LOG_NOTICE, $log);
} else {
$query = sprintf(
"insert into memcache (`key`,`value`) values ('destinations_sip','%s')",
addslashes($destinations_sip_cache)
);
if (!$this->cdrtool->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->cdrtool->Error,
$this->cdrtool->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf("Updated cache for %d SIP destinations", $this->destinations_sip_count);
syslog(LOG_NOTICE, $log);
}
return true;
}
function LoadENUMtlds()
{
$_ENUMtlds = array();
$query = "select * from billing_enum_tlds";
$this->cdrtool->query($query);
while ($this->cdrtool->next_record()) {
$_ENUMtlds[trim($this->cdrtool->Record['enum_tld'])] = array(
'discount' => trim($this->cdrtool->Record['discount']),
'e164_regexp' => trim($this->cdrtool->Record['e164_regexp'])
);
}
$this->ENUMtlds = $_ENUMtlds;
$c = count($this->ENUMtlds);
return count($this->ENUMtlds);
}
function LoadDisconnectCodes()
{
}
function initForm()
{
}
function searchForm()
{
}
function showTableHeader()
{
}
function showTableHeaderStatistics()
{
}
function showResultsMenu($hide_rows = "", $begin_datetime = '', $end_datetime = '')
{
global $loginname;
if (!$this->export) {
print "
<form class='form-inline' action=log.phtml method=post>
<div class='row-fluid'>
<div class='span6'>";
print "
<div class=\"btn-group pull-right\">
<a class=\"btn\" href=\"$this->url_edit\" ><i class=icon-search></i> Refine search</a><a class=\"btn\" href=\"$this->url_run\"><i class=\"icon-refresh\"></i> Refresh</a>";
$log_query = sprintf(
"insert into log
(date,login,ip,url,results,rerun,reedit,datasource,reseller_id)
values
(NOW(),'%s','%s','%s','%s','%s','%s','%s',%d)",
addslashes($loginname),
addslashes($_SERVER["REMOTE_ADDR"]),
addslashes($this->url),
addslashes($this->rows),
addslashes($this->url_run),
addslashes($this->url_edit),
addslashes($this->cdr_source),
addslashes($this->CDRTool['filter']['reseller'])
);
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if ($this->rows) {
print "<a class=\"btn\" href=\"$this->url_export\" target=_new><i class=\"icon-file\"></i> Export results to file</a>
</div></div>";
} else {
print "</div></div>";
}
print "
<div class='span6'>
<div class='input-append'>
<input class='input-medium' rel='popover' data-placement=\"bottom\" data-content=\"Want to share the results with others? Enter a name and press Save \" data-original-title=\"Save Query\" placeholder='Query name' type=text name=log_description value=\"$old_description\"><button class='btn' type=submit value=Save>Save</button>
</div>
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
</div>
</div>
</form>
";
if (!$hide_rows) {
print "
<div class=\"alert alert-success\"><center>";
if ($this->rows == 0) {
print "No records found";
} else {
print "$this->rows records found";
}
if ($begin_datetime && $end_datetime) {
printf(" between %s and %s", $begin_datetime, $end_datetime);
}
print "</center></div>
";
}
}
}
function showResultsMenuSubscriber($hide_rows = "", $begin_datetime = '', $end_datetime = '')
{
global $loginname;
if (!$this->export) {
print "
<form action=log.phtml method=post>
<table border=0 align=center>
<tr>
<td>
<td>
<a href=\"$this->url_edit\">Refine search</a>
| <a href=\"$this->url_run\">Refresh</a>
</td>
";
$log_query = sprintf(
"insert into log
(date,login,ip,url,results,rerun,reedit,datasource,reseller_id)
values
(NOW(),'%s','%s','%s','%s','%s','%s','%s',%d)",
addslashes($loginname),
addslashes($_SERVER["REMOTE_ADDR"]),
addslashes($this->url),
addslashes($this->rows),
addslashes($this->url_run),
addslashes($this->url_edit),
addslashes($this->cdr_source),
0
);
if ($this->cdrtool->query($log_query)) {
$this->cdrtool->query("select LAST_INSERT_ID() as lid");
$this->cdrtool->next_record();
$current_log=$this->cdrtool->f('lid');
}
if (!$this->CDRTool['filter']['aNumber']) {
if ($this->rows) {
print " | <a href=\"$this->url_export\" target=_new>Export results to file</a>";
}
print "
</td>
<td valign=middle>
| Save a description for this query:
</td>
<td valign=middle>
<input type=text name=log_description value=\"$old_description\">
<input type=hidden name=current_log value=$current_log>
<input type=hidden name=task value=edit>
<input type=submit value=Save>
</td>
</form>
";
}
print "
</tr>
</table>
";
if (!$hide_rows) {
print "<div class=\"alert alert-success\"><center>";
if ($this->rows == 0) {
print "No records found";
} else {
print "$this->rows records found";
}
if ($begin_datetime && $end_datetime) {
printf(" between %s and %s",$begin_datetime,$end_datetime);
}
print "</center>
</div>
";
}
}
}
function showDateTimeElements($f)
{
print "
<tr>
<td valign=middle align=left>
<b>Start Time</b>
</td>
<td><div class='input-append date'>
";
$f->show_element("begin_date","");
print "<span class=\"add-on\">
<i class=\"icon-calendar\"></i>
</span></div> ";
print "Time: ";
print "<div class=\"input-append bootstrap-timepicker\">";
$f->show_element("begin_time","");
print "<span class=\"add-on\"><i class=\"icon-time\"></i></span>
</div>
</td>
</tr>
<tr>
<td valign=middle align=left>
<b>Stop Time</b>
</td>
<td><div class='input-append date'>
";
$f->show_element("end_date","");
print "<span class=\"add-on\">
<i class=\"icon-calendar\"></i>
</span></div> ";
print "Time: ";
print "<div class=\"input-append bootstrap-timepicker\">";
$f->show_element("end_time","");
print "<span class=\"add-on\"><i class=\"icon-time\"></i></span>
</div>
</td>
</tr>
";
}
function showDataSources($f)
{
global $perm;
print "
<tr>
<td class=cdr valign=middle align=left>
<b>Data Source</b>
</td>
<td valign=middle>";
$f->show_element("cdr_source","");
if (count($this->tables) > 0) {
print " Table: ";
$this->f->show_element("cdr_table","");
}
print "
</td>
</tr>
<tr>
";
}
function showPagination($next, $maxrows)
{
$PHP_SELF = $_SERVER["PHP_SELF"];
if (!$this->export) {
print "
<ul class=\"pager\">
";
if ($next != 0) {
$show_next = $this->maxrowsperpage - $next;
if ($show_next < 0) {
$mod_show_next = $show_next - 2 * $show_next;
}
$url_prev = $PHP_SELF.$this->url."&action=search&next=$mod_show_next";
print "<li><a href=\"$url_prev\"> &larr; Previous</a></li>";
}
print "
</td>
<td>
";
if ($this->rows > $this->maxrowsperpage && $this->rows != $maxrows) {
$show_next = $this->maxrowsperpage + $this->next;
$url_next = $PHP_SELF.$this->url."&action=search&next=$show_next";
print "<li><a href=\"$url_next\">Next &rarr;</a></li>";
}
print "
</ul>
";
}
}
function show()
{
}
function dump()
{
}
function unNormalize($where = "", $table)
{
if ($this->skipNormalize) {
return 0;
}
if (!$this->normalizedField) {
return 0;
}
// do not allow renormalization for readonly accounts
global $perm;
if (is_object($perm) && $perm->have_perm('readonly')) return false;
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
$query=sprintf(
"update %s set %s = '0' where %s ",
addslashes($table),
addslashes($this->normalizedField),
$where
);
$c=0;
if ($this->CDRdb->query($query)) {
$c = $this->CDRdb->affected_rows();
$this->reNormalize = true;
}
return $c;
}
function buildWhereForUnnormalizedSessions()
{
$this->whereUnnormalized = sprintf(" %s = '0'",$this->normalizedField);
if ($this->stopTimeField) $this->whereUnnormalized .= " and $this->stopTimeField not like '0000-00-00 00:00:00%' ";
if ($this->CDRFields['MediaTimeout']) {
/*
If we use MediaProxy information then eliminate all possible raise conditions
1. Session started and is in progress:
AcctStopTime = '0000-00-00 00:00:00'
AcctSessionTime = 0
MediaInfo is NULL
ConnectInfo_stop is NULL
2. Session closed with a negative response code ([4-6]XX):
AcctSessionTime = 0
AcctStopTime != '0000-00-00 00:00:00'
MediaInfo is NULL
ConnectInfo_stop is NULL
3. Session received a BYE:
ConnectInfo_stop is not NULL
AcctStopTime != '0000-00-00 00:00:00'
4. Media has timed-out:
MediaInfo = 'timeout'
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
5. MediaProxy update before BYE is received:
MediaInfo = ''
ConnectInfo_stop is NULL
AcctStopTime != '0000-00-00 00:00:00'
6. Mofified 5. for the case where the session received a broken BYE
that did not generate a STOP while MediaProxy generated an UPDATE
*/
$this->whereUnnormalized .= " and (ConnectInfo_stop is not NULL or MediaInfo is NULL or MediaInfo != '' or (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(AcctStopTime) > 20)) ";
}
}
function getUnNormalized($where = "", $table)
{
if ($this->skipNormalize) {
return 0;
}
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
$ReNormalize = $_REQUEST["ReNormalize"];
if ($ReNormalize) $this->unNormalize($where, $table);
if (!$this->normalizedField) {
return 0;
}
$this->buildWhereForUnnormalizedSessions();
$query=sprintf(
"select count(*) as c from %s where %s and %s",
addslashes($table),
$where,
$this->whereUnnormalized
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$c = $this->CDRdb->f('c');
}
return $c;
}
function NormalizeCDRS($where = "", $table = "")
{
$this->missing_destinations=array();
$b=time();
if (!$where) $where=" (1=1) ";
if (!$table) $table=$this->table;
if ($this->skipNormalize) {
return 1;
}
if (!$this->normalizedField) {
return 1;
}
$lockName = sprintf("%s:%s", $this->cdr_source, $table);
if (!$this->getNormalizeLock($lockName)) {
//printf("Cannot get obtain lock %s",$lockName);
return true;
}
$this->buildWhereForUnnormalizedSessions();
$this->status['cdr_to_normalize'] = 0;
$this->status['normalized'] = 0;
$this->status['normalize_failures'] = 0;
$query = sprintf(
"select count(*) as c from %s where %s and %s",
addslashes($table),
$where,
$this->whereUnnormalized
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$c=$this->CDRdb->f('c');
}
$this->status['cdr_to_normalize']=$c;
//$this->status['cdr_to_normalize']=$this->CDRdb->num_rows();
//print "<p>$query";
if ($this->status['cdr_to_normalize'] > 0) {
if ($this->ratingEnabled) {
// Load rating tables
$this->RatingTables = new RatingTables();
$this->RatingTables->LoadRatingTables();
}
} else {
return 0;
}
$this->usageKeysForDeletionFromCache = array();
// For loop to process 1k records each time
for ($i = 0; $i <= $this->status['cdr_to_normalize']; $i=$i+1000) {
$query = sprintf(
"select *, UNIX_TIMESTAMP($this->startTimeField) as timestamp
from %s where %s and %s limit 0,1000",
addslashes($table),
$where,
$this->whereUnnormalized
);
if (!$this->CDRdb->query($query)) {
$log = sprintf(
"Database error: %s (%s)\n",
$this->CDRdb->Error,
$this->CDRdb->Errno
);
syslog(LOG_NOTICE, $log);
print $log;
return false;
}
while ($this->CDRdb->next_record()) {
//$Structure=$this->_readCDRNormalizationFieldsFromDB();
$Structure=$this->_readCDRFieldsFromDB('');
if ($this->csv_writter) {
if (!$this->csv_file_cannot_be_opened) {
if (!$this->csv_writter->ready) {
if (!$this->csv_writter->open_file($Structure[$this->CDRNormalizationFields['id']])) {
$this->csv_file_cannot_be_opened = true;
} else {
$this->csv_file_ready = true;
}
}
}
}
$found++;
$CDR = new $this->CDR_class($this, $Structure);
if ($CDR->normalize("Save", $table)) {
$this->status['normalized']++;
if ($this->csv_file_ready) {
if (!$this->csv_writter->write_cdr($CDR)) {
// stop writing future records if we have a failure
$this->csv_file_cannot_be_opened = true;
}
}
if ($CDR->broken_rate) {
$this->brokenRates[$CDR->DestinationId]++;
}
} else {
$this->status['normalize_failures']++;
}
if ($this->reNormalize && !$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]) {
$this->usageKeysForDeletionFromCache[$CDR->BillingPartyId]++;
}
if ($this->status['cdr_to_normalize'] > 1000) {
if ($found > $progress*$this->status['cdr_to_normalize']/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
flush();
}
}
}
}
}
if ($this->ratingEnabled && count($this->brokenRates) > 0) {
if ($this->rating_settings['reportMissingRates']) {
if (count($this->brokenRates)) {
foreach (array_keys($this->brokenRates) as $dest) {
$missingRatesBodytext=$missingRatesBodytext."\nDestination id $dest (".$this->brokenRates[$dest]." calls)";
}
$to = $this->CDRTool['provider']['toEmail'];
$from = $this->CDRTool['provider']['fromEmail'];
$log = sprintf(
"Mailing missing rates for %d destination(s) to %s",
count($this->brokenRates),
$to
);
syslog(LOG_NOTICE, $log);
mail($to, "Missing CDRTool rates",$missingRatesBodytext, "From: $from");
}
}
}
if (count($this->missing_destinations)) {
$to = $this->CDRTool['provider']['toEmail'];
$from = $this->CDRTool['provider']['fromEmail'];
$body = '';
foreach ($this->missing_destinations as $_dest) {
if (!$seen[$_dest]) {
$body .= sprintf("No destination for number %s\n", $_dest);
}
$seen[$_dest]++;
}
mail($to, "Missing CDRTool destinations", $body, "From: $from");
}
if ($this->status['cdr_to_normalize'] > 0) {
$d = time() - $b;
$log = sprintf("Normalization done in %d s, memory usage: %0.2f MB", $d, memory_get_usage() / 1024 / 1024);
syslog(LOG_NOTICE, $log);
}
if ($this->csv_file_ready) {
$this->csv_writter->close_file();
$this->csv_writter->ready = false;
}
if (count($this->usageKeysForDeletionFromCache)) {
$this->resetQuota(array_keys($this->usageKeysForDeletionFromCache));
}
return 1;
}
function NormalizeNumber($Number, $type = "destination", $subscriber = "", $domain = "", $gateway = "", $CountryCode = "", $ENUMtld = "", $reseller_id = 0)
{
$this->CSCODE="";
$Number = strtolower(quoted_printable_decode($Number));
if ($pos = strpos($Number, "@")) {
// this is a SIP URI
$NumberStack['username'] = substr($Number, 0, $pos);
if (strlen($NumberStack['username']) < 1) {
$NumberStack['username'] = "unknown";
}
$NumberStack['domain'] = substr($Number,$pos+1);
$NumberStack['delimiter'] = "@";
$pos = strpos($NumberStack['username'], ":");
if ($pos) {
$NumberStack['protocol'] = substr($NumberStack['username'], 0, $pos+1);
$NumberStack['username'] = substr($NumberStack['username'], $pos+1);
}
if (preg_match("/^(.*)[=:;]/U", $NumberStack['domain'], $p)){
$NumberStack['domain'] = $p[1];
}
} else if (preg_match("/^([a-z0-9]+:)(.*)$/i", $Number, $m)) {
#$oct=preg_split("/\./",$m[2]);
$oct = explode(",", $m[2]);
if(sizeof($oct) == 4) {
// This is a SIP address without username
$NumberStack['username'] = "";
$NumberStack['domain'] = $m[2];
} else {
// This is a SIP address without domain
$NumberStack['username'] = $m[2];
$NumberStack['domain'] = "";
}
$NumberStack['protocol'] = $m[1];
$NumberStack['delimiter'] = "";
} else {
// This is a simple address like a phone number
$NumberStack['protocol'] = "";
$NumberStack['username'] = $Number;
$NumberStack['delimiter'] = "";
$NumberStack['domain'] = "";
}
if (preg_match("/^(.*)[=:;]/U", $NumberStack['domain'], $p)){
$NumberStack['domain'] = $p[1];
}
// Translate the domain
if (is_array($this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'])
&& isset($this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'][$NumberStack['domain']])
) {
$NumberStack['domain'] = $this->DATASOURCES[$this->cdr_source]['domainTranslationDestination'][$NumberStack['domain']];
}
if ($type=="destination" && is_numeric($NumberStack['username'])) {
// strip custom prefix from destination
$usernameLength = strlen($NumberStack['username']);
if (is_array($this->CS_CODES)) {
foreach ($this->CS_CODES as $strip_prefix) {
$prefixLength = strlen($strip_prefix);
$restLength = $usernameLength-$prefixLength;
if ($restLength > 0 and preg_match("/^$strip_prefix(.*)$/", $NumberStack['username'], $m)) {
$NumberStack['username'] = $m[1];
$this->CSCODE = $strip_prefix;
break;
}
}
}
if (!$CountryCode) $CountryCode = $this->CDRTool['normalize']['defaultCountryCode'];
$e164class = $this->E164_class;
$E164 = new $e164class(
$this->intAccessCode,
$this->natAccessCode,
$CountryCode,
$this->ENUMtlds[$ENUMtld]['e164_regexp']
);
$NumberStack['E164'] = $E164->E164Format($NumberStack['username']);
}
if ($type=="destination" && $NumberStack['E164']) {
// lookup destination id for the E164 number
$dst_struct = $this->lookupDestination(
$NumberStack['E164'],
$subscriber,
$domain,
$gateway,$reseller_id
);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = "+".$NumberStack['E164'];
if (!$ENUMtld) {
$NumberStack['Normalized'] = $this->intAccessCode.
$NumberStack['E164'].
$NumberStack['delimiter'].
$NumberStack['domain'];
} else {
$NumberStack['Normalized'] =
$NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
} else {
$dst_struct = $this->lookupDestination(
$Number,
$subscriber,
$domain,
$gateway,
$reseller_id
);
$NumberStack['DestinationId'] = $dst_struct[0];
$NumberStack['destinationName'] = $dst_struct[1];
$NumberStack['NumberPrint'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
$NumberStack['Normalized'] = $NumberStack['username'].
$NumberStack['delimiter'].
$NumberStack['domain'];
}
return $NumberStack;
}
function lookupDestination($destination, $subscriber = "", $domain = "", $gateway = "", $reseller_id = 0)
{
if (!$destination) return;
if (is_numeric($destination)) {
return $this->lookupPSTNDestination($destination, $subscriber, $domain, $gateway, $reseller_id);
} else {
return $this->lookupSipDestination($destination, $subscriber, $domain, $gateway, $reseller_id);
}
}
function lookupSipDestination($destination = '', $subscriber = '', $domain = '', $gateway = '', $reseller_id = 0)
{
if ($this->destinations_sip[$reseller_id][$subscriber]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$subscriber];
$fCustomer = "subscriber=$subscriber";
} else if ($this->destinations_sip[$reseller_id][$domain]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$domain];
$fCustomer = "domain=$domain";
} else if ($this->destinations_sip[$reseller_id][$gateway]) {
$destinations_sip = $this->destinations_sip[$reseller_id][$gateway];
$fCustomer = "gateway=$gateway";
} else if ($this->destinations_sip[$reseller_id]['default']) {
$destinations_sip = $this->destinations_sip[$reseller_id]['default'];
$fCustomer = "default";
} else if ($this->destinations_sip[0][$subscriber]) {
$destinations_sip = $this->destinations_sip[0][$subscriber];
$fCustomer = "subscriber=$subscriber";
} else if ($this->destinations_sip[0][$domain]) {
$destinations_sip = $this->destinations_sip[0][$domain];
$fCustomer = "domain=$domain";
} else if ($this->destinations_sip[0][$gateway]) {
$destinations_sip = $this->destinations_sip[0][$gateway];
$fCustomer = "gateway=$gateway";
} else if ($this->destinations_sip[0]['default']) {
$destinations_sip = $this->destinations_sip[0]['default'];
$fCustomer = "default";
}
$ret = false;
if ($destinations_sip[$destination]) {
$ret = array($destination,$destinations_sip[$destination]['name']);
} else {
list($user,$domain) = explode("@", $destination);
if ($domain) {
$domain = sprintf("@%s", $domain);
if ($destinations_sip[$domain]) {
$ret = array($domain, $destinations_sip[$domain]['name']);
}
}
}
return $ret;
}
function lookupPSTNDestination($destination = '', $subscriber = '', $domain = '',$gateway = '', $reseller_id = 0)
{
if ($this->destinations[$reseller_id][$subscriber]) {
$_destinations = $this->destinations[$reseller_id][$subscriber];
$maxLength = $this->destinations_length[$reseller_id][$subscriber];
$fCustomer="subscriber=$subscriber";
} else if ($this->destinations[$reseller_id][$domain]) {
$_destinations = $this->destinations[$reseller_id][$domain];
$maxLength = $this->destinations_length[$reseller_id][$domain];
$fCustomer="domain=$domain";
} else if ($this->destinations[$reseller_id][$gateway]) {
$_destinations = $this->destinations[$reseller_id][$gateway];
$maxLength = $this->destinations_length[$reseller_id][$gateway];
$fCustomer="gateway=$gateway";
} else if ($this->destinations[$reseller_id]['default']) {
$_destinations = $this->destinations[$reseller_id]['default'];
$maxLength = $this->destinations_length[$reseller_id]['default'];
$fCustomer="default";
} else if ($this->destinations[0][$subscriber]) {
$_destinations = $this->destinations[0][$subscriber];
$maxLength = $this->destinations_length[0][$subscriber];
$fCustomer="subscriber=$subscriber";
} else if ($this->destinations[0][$domain]) {
$_destinations = $this->destinations[0][$domain];
$maxLength = $this->destinations_length[0][$domain];
$fCustomer="domain=$domain";
} else if ($this->destinations[0][$gateway]) {
$_destinations = $this->destinations[0][$gateway];
$maxLength = $this->destinations_length[0][$gateway];
$fCustomer="gateway=$gateway";
} else if ($this->destinations[0]['default']) {
$_destinations = $this->destinations[0]['default'];
$maxLength = $this->destinations_length[0]['default'];
$fCustomer="default";
} else {
$log = sprintf(
"Error: cannot find destinations for subscriber='%s', domain ='%s', gateway='%s', reseller='%s'\n",
$subscriber,
$domain,
$gateway,
$reseller_id
);
syslog(LOG_NOTICE, $log);
}
if (count($_destinations) > 0) {
$length = min(strlen($destination), $maxLength);
for ($i = $length; $i > 0; $i--) {
$buf = substr($destination, 0, $i);
if ($_destinations[$buf]) {
return array($buf, $_destinations[$buf]['name']);
}
}
}
$log = sprintf(
"Error: cannot find destination id for %s of customer = '%s', total destinations = %d\n",
$destination,
$fCustomer,
count($_destinations)
);
syslog(LOG_NOTICE, $log);
$this->missing_destinations[] = $destination;
return false;
}
function import($file)
{
}
function RadiusRecordRead($fp)
{
$keepreading=1;
while ($keepreading) {
$contents = fgets($fp, 8192);
if (preg_match("/^$/", $contents)) {
$keepreading=0;
} else {
$record[]=$contents;
}
}
return $record;
}
function RadiusRecordParse($record)
{
unset($radiusParsed);
if (!is_array($record)) {
return 0;
}
foreach ($record as $line) {
$line=trim($line);
foreach (array_keys($this->radiusAttributes) as $attribute) {
if (preg_match("/$attribute = (.*)$/", $line, $m)) {
$value = preg_replace("/\"/", "", trim($m[1]));
$radiusParsed[$attribute] = $value;
}
}
}
return $radiusParsed;
}
function getCDRtables()
{
if (!is_object($this->CDRdb)) return 0;
$_tables=$this->CDRdb->table_names();
$t=count($_tables);
if ($this->table) $this->tables[]=$this->table;
while ($t <> 0) {
$_table=$_tables[$t-1]["table_name"];
if ($_table=='radacct') $this->tables[]='radacct';
if (preg_match("/^(\w+)(\d{6})$/", $_table, $m)) {
if ($list_t > 24) break;
$this->tables[] = $_table;
$list_t++;
}
$t--;
}
$this->tables=array_unique($this->tables);
}
function rotateTable($sourceTable, $month, $action)
{
// create a new table tableYYYYMM and copy data from the main table into it
// if no month is supplied, the default is the previous month
if (!$month) $month=date('Ym', mktime(0, 0, 0, date("m") - 1, "01", date("Y")));
if (!$sourceTable) $sourceTable = $this->table;
if (preg_match("/^(\w+)\d{6}$/", $sourceTable, $m)) {
$destinationTable = $m[1].$month;
} else {
$destinationTable = $sourceTable.$month;
}
print("rotateTable($sourceTable, $month, $destinationTable)\n");
if ($sourceTable == $destinationTable) {
$log = sprintf("Error: cannot copy records to the same table %s.\n", $destinationTable);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$createTableFile = $this->CDRTool['Path'].$this->createTableFile;
if (!$this->createTableFile || !is_readable($createTableFile)) {
$log = sprintf("Error: cannot locate mysql creation file\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$lockFile="/var/lock/CDRTool_".$this->cdr_source."_rotateTable.lock";
$f = fopen($lockFile, "w");
if (flock($f, LOCK_EX + LOCK_NB, $w)) {
if ($w) {
$log = sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
} else {
$log = sprintf("Another CDRTool rotate table is in progress. Aborting.\n");
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$b=time();
if (!preg_match("/^(\d{4})(\d{2})$/", $month, $m)) {
print "Error: Month $month must be in YYYYMM format\n";
return 0;
} else {
if ($m[2] > 12) {
print "Error: Month must be in YYYYMM format\n";
return 0;
}
$lastMonth = $month;
$startSQL = $m[1]."-".$m[2]."-01";
$stopSQL =date('Y-m-01', mktime(0, 0, 0, $m[2] + 1, "01", $m[1]));
}
$query = sprintf(
"select count(*) as c from %s where %s >='%s' and %s < '%s'\n",
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($startSQL),
addslashes($this->CDRFields['startTime']),
addslashes($stopSQL)
);
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsSourceTable = $this->CDRdb->f('c');
$log=sprintf("Source table %s has %d records in month %s\n", $sourceTable, $rowsSourceTable, $month);
syslog(LOG_NOTICE, $log);
print $log;
if (!$rowsSourceTable) return 1;
} else {
$log = sprintf("Error: %s (%s)\n", $this->table, $this->CDRdb->Error);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
$query = sprintf("select count(*) as c from %s\n", addslashes($destinationTable));
if ($this->CDRdb->query($query)) {
$this->CDRdb->next_record();
$rowsDestinationTable = $this->CDRdb->f('c');
$log = sprintf("Destination table %s has %d records\n", $destinationTable, $rowsDestinationTable);
syslog(LOG_NOTICE, $log);
print $log;
if ($rowsDestinationTable != $rowsSourceTable) {
$log = sprintf(
"Error: source table has %d records and destination table has %d records\n",
$rowsSourceTable,
$rowsDestinationTable
);
syslog(LOG_NOTICE, $log);
print $log;
} else {
$log = sprintf("Tables are in sync\n");
syslog(LOG_NOTICE, $log);
print $log;
}
} else {
$log = sprintf("%s (%s)\n", $this->CDRdb->Error, $this->CDRdb->Errno);
syslog(LOG_NOTICE, $log);
print $log;
if ($this->CDRdb->Errno==1146) {
$destinationTableTmp = $destinationTable."_tmp";
$query=sprintf("drop table if exists %s", addslashes($destinationTableTmp));
print($query);
$this->CDRdb->query($query);
if ($query=file_get_contents($createTableFile)) {
$query=preg_replace("/CREATE TABLE.*/", "CREATE TABLE $destinationTableTmp (", $query);
if (!$this->CDRdb->query($query)) {
$log = sprintf("Error creating table %s: %s, %s\n", $destinationTableTmp, $this->CDRdb->Error,$query);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
} else {
$log = sprintf("Cannot read file %s\n",$createTableFile);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
// if we reached this point we start to copy records
$query = sprintf(
"insert into %s select * from %s where %s >='%s' and %s < '%s'",
addslashes($destinationTableTmp),
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($startSQL),
addslashes($this->CDRFields['startTime']),
addslashes($stopSQL)
);
return;
if ($this->CDRdb->query($query)) {
$e=time();
$d=$e-$b;
$rps=0;
if ($this->CDRdb->affected_rows() && $d) $rps=$this->CDRdb->affected_rows()/$d;
$log = printf("Copied %d CDRs into table %s in %d s @ %.0f rps\n",$this->CDRdb->affected_rows(),$destinationTableTmp,$d,$rps);
syslog(LOG_NOTICE,$log);
print $log;
$query=sprinf("rename table %s to %s", addslashes($destinationTableTmp),addslashes($destinationTableTmp));
if (!$this->CDRdb->query($query)) {
printf ("Error renaming table %s to %s: %s\n",$destinationTableTmp,$destinationTable,$this->CDRdb->Error);
return 0;
}
} else {
printf ("Error copying records in table %s: %s\n",$destinationTable,$this->CDRdb->Error);
return 0;
}
}
}
}
function purgeTable($sourceTable, $month)
{
// delete records for a given month with minimal locking of database
// this function is useful after archive of CDR data using rotate script
$begin=time();
if ($month) {
if (!preg_match("/^(\d{4})(\d{2})$/",$month,$m)) {
print "Error: Month must be in YYYYMM format\n";
return 0;
} else {
$beginDate=$m[1]."-".$m[2]."-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, $m[2]+1, '01', $m[1]));
}
} else if (is_int($this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'])) {
$beginDate="1970-01-01";
$endDate=date('Y-m-d', mktime(0, 0, 0, Date('m'), Date('d')-$this->DATASOURCES[$this->cdr_source]['purgeCDRsAfter'], Date('Y')));
} else {
return 0;
}
if (!$sourceTable) $sourceTable=$this->table;
$query = sprintf(
"select min(%s) as min,max(%s) as max from %s where %s >= '%s' and %s < '%s' ",
addslashes($this->CDRFields['id']),
addslashes($this->CDRFields['id']),
addslashes($sourceTable),
addslashes($this->CDRFields['startTime']),
addslashes($beginDate),
addslashes($this->CDRFields['startTime']),
addslashes($endDate)
);
dprint($query);
if (!$this->CDRdb->query($query)) {
printf ("Error: %s",$this->CDRdb->Error);
return 0;
}
$this->CDRdb->next_record();
$min=$this->CDRdb->f('min');
$max=$this->CDRdb->f('max');
if (!$min || !$max) {
$log=sprintf("No CDRs found in %s between %s and %s\n",$sourceTable,$beginDate,$endDate);
print $log;
syslog(LOG_NOTICE,$log);
return 0;
}
$deleted=0;
$i=$min;
$interval=100;
$rows2delete=$max-$min;
$found = 0;
print "$rows2delete CDRs will be deleted between $min and $max, $interval at a time\n";
while ($i <= $max) {
$found=$found+$interval;
if ($i + $interval < $max) {
$top=$i;
} else {
$top=$max;
}
$query=sprintf("delete low_priority from %s where %s <= '%d' and %s >= '%d'",
addslashes($sourceTable),
addslashes($this->CDRFields['id']),
addslashes($top),
addslashes($this->CDRFields['id']),
addslashes($min)
);
if ($this->CDRdb->query($query)) {
$deleted=$deleted+$this->CDRdb->affected_rows();
} else {
$log=sprintf("Error: %s (%s)",$this->CDRdb->Error,$this->CDRdb->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
}
if ($found > $progress*$rows2delete/100) {
$progress++;
if ($progress%10==0) {
print "$progress% ";
flush();
}
}
print ".";
flush();
$i=$i+$interval;
}
print "\n";
$end = time();
$duration = $end-$begin;
$rps=0;
if ($deleted && $duration) $rps=$deleted/$duration;
$log=sprintf("%s CDRs of month %s deleted from %s in %d s @ %.0f rps\n",$deleted,$month,$sourceTable,$duration,$rps);
syslog(LOG_NOTICE,$log);
print $log;
return 1;
}
function cacheQuotaUsage($accounts=array())
{
if (!$this->quotaEnabled) return true;
$saved_keys=0;
$failed_keys=0;
foreach (array_keys($accounts) as $_key) {
$query=sprintf("select id from quota_usage where datasource = '%s' and account = '%s'",addslashes($this->cdr_source),addslashes($_key));
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
print($log);
return false;
}
if ($this->cdrtool->num_rows()) {
// sync with quota_usage table
$query=sprintf("update quota_usage set
calls = calls + %d,
duration = duration + %d,
cost = cost + '%s',
cost_today = cost_today + '%s',
traffic = traffic + '%s'
where account = '%s'
",
addslashes($accounts[$_key]['usage']['calls']),
addslashes($accounts[$_key]['usage']['duration']),
addslashes($accounts[$_key]['usage']['cost']),
addslashes($accounts[$_key]['usage']['cost_today']),
addslashes($accounts[$_key]['usage']['traffic']),
addslashes($_key)
);
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
$failed_keys++;
} else {
$saved_keys++;
}
} else {
$quota=$this->getQuota($_key);
$blocked=$this->getBlockedByQuotaStatus($_key);
list($_u,$_d)=explode("@",$_key);
$query=sprintf("insert into quota_usage
(datasource,account,domain,quota,calls,duration,cost,cost_today,traffic,blocked,reseller_id)
values
('%s','%s','%s',%d,%d,'%s','%s','%s','%s','%s',%d)
",
addslashes($this->cdr_source),
addslashes($_key),
addslashes($_d),
addslashes($quota),
addslashes($accounts[$_key]['usage']['calls']),
addslashes($accounts[$_key]['usage']['duration']),
addslashes($accounts[$_key]['usage']['cost']),
addslashes($accounts[$_key]['usage']['cost_today']),
addslashes($accounts[$_key]['usage']['traffic']),
intval($blocked),
addslashes($this->localDomains[$_d]['reseller'])
);
if (!$this->cdrtool->query($query)){
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE, $log);
$failed_keys++;
} else {
$saved_keys++;
}
}
}
$this->status['cached_keys']['saved_keys'] = $this->status['cached_keys']['saved_keys'] + $saved_keys;
$this->status['cached_keys']['failed_keys'] = $this->status['cached_keys']['failed_keys'] + $failed_keys;
return 1;
}
function getNormalizeLock($lockname='') {
if (!$locker = new DB_Locker()) {
$log=sprintf("Error: cannot init locker database. ");
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$lockname) {
$log=sprintf("Error: no lockname provided. ");
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
unset($this->lock_connection_id);
register_shutdown_function("unLockNormalization",$locker,$lockname);
$query=sprintf("SELECT GET_LOCK('%s',0)",addslashes($lockname));
if ($locker->query($query)) {
$locker->next_record();
$return = $locker->Record["GET_LOCK('$lockname',0)"];
$query=sprintf("SELECT IS_USED_LOCK('%s')",addslashes($lockname));
if ($locker->query($query)) {
$locker->next_record();
$this->lock_connection_id=$locker->Record["IS_USED_LOCK('$lockname')"];
}
if ($return == 0) {
$log=sprintf("Lock %s already aquired by another process with id %s ",$lockname,$this->lock_connection_id);
syslog(LOG_NOTICE, $log);
print "$log\n";
return 0;
} else {
$log=sprintf("Normalize lock id %s aquired for %s ",$this->lock_connection_id,$lockname);
syslog(LOG_NOTICE, $log);
//print "$log\n";
return 1;
}
} else {
$log=sprintf("Database error: failed to request mysql lock %s (%s)\n",$locker->Error,$locker->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return 0;
}
}
function getQuota($account) {
}
function getBlockedByQuotaStatus($account) {
}
function resetQuota($accounts=array()) {
if (!$this->quotaEnabled) return true;
$_reset_array=array_unique($accounts);
foreach ($_reset_array as $_el) {
if (strlen($_el)) $_accounts[]=$_el;
}
$_reset_array=$_accounts;
$log=sprintf("Next quota check will rebuild the counters for %s accounts",count($_reset_array));
syslog(LOG_NOTICE,$log );
$query=sprintf("delete from memcache where `key` in ('%s','%s')",addslashes($this->quota_init_flag),addslashes($this->quota_reset_flag));
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->cdrtool->Error,$this->cdrtool->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query=sprintf("insert into memcache (`key`,`value`) values ('%s','%s')",addslashes($this->quota_reset_flag),addslashes(json_encode($_reset_array)));
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->cdrtool->Error,$this->cdrtool->Errno);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query="delete from quota_usage where account in (";
$t=0;
foreach ($_reset_array as $_el) {
if ($t) $query.=",";
$query.= sprintf("'%s'",addslashes($_el));
$t++;
}
$query.=")";
if (!$this->cdrtool->query($query)) {
$log=sprintf ("Database error: %s (%s)",$this->cdrtool->Error,$this->cdrtool->Errno);
syslog(LOG_NOTICE,$log);
print $log;
return 0;
} else {
return 1;
}
}
}
class CDRS_unknown extends CDRS {
function searchForm() {
return;
}
}
class E164 {
// Class that helps normalization of a telephone number in E164 format
// Based on this normalization, CDRTool rating engine decides whether
// to consider the session a PSTN destination and rate it according
// to the PSTN rating plan
function E164($intAccessCode='00', $natAccessCode='0',$CountryCode='',$ENUMtldRegexp="") {
$this->regexp_international = "/^".$intAccessCode."([0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
function E164Format($Number) {
//dprint "E164Format($Number,ENUMtldRegexp=$this->ENUMtldRegexp)";
// This function returns the full E164 format for a PSTN number without leading zero or +
// E164 = Country Code + Network Code + Subscriber Number
// Example: 31208015100 is an E164 number from Holland (country code 31)
// If nothing is returned by this function the session is considered an Internet destination
if (preg_match($this->regexp_international,$Number,$m)) {
return $m[1];
} else if (preg_match($this->regexp_national,$Number,$m)) {
// Add default country code
return $this->CountryCode.$m[1];
} else if (strlen($this->ENUMtldRegexp)) {
$_regexp="/^".$this->ENUMtldRegexp."\$/";
if (preg_match($_regexp,$Number,$m)) {
return $m[1];
}
}
return false;
}
}
class E164_Europe extends E164 {
function E164_Europe ($intAccessCode='00', $natAccessCode='0',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([1-9][0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class E164_US extends E164 {
function E164_US($intAccessCode='011', $natAccessCode='[1-9][0-9]{2}',$CountryCode='',$ENUMtldRegexp="([1-9][0-9]{7,})") {
$this->regexp_international = "/^".$intAccessCode."([1-9][0-9]{5,})\$/";
$this->regexp_national = "/^".$natAccessCode."([0-9]{3,})\$/";
$this->CountryCode = trim($CountryCode);
$this->ENUMtldRegexp = trim($ENUMtldRegexp);
}
}
class CDR {
// we need two db descriptors to update a CDR
// within same result set
var $idField = "RadAcctId";
var $callIdField = "AcctSessionId";
var $usernameField = "UserName";
var $domainField = "Realm";
var $gatewayField = "NASIPAddress";
var $gatewayPortField = "CiscoNASPort";
var $timestampField = "timestamp";
var $portIdField = "NASPortId";
var $portTypeField = "NASPortType";
var $startTimeField = "AcctStartTime";
var $stopTimeField = "AcctStopTime";
var $durationField = "AcctSessionTime";
var $inputTrafficField = "AcctInputOctets";
var $outputTrafficField = "AcctOutputOctets";
var $serviceTypeField = "ServiceType";
var $cNumberField = "CalledStationId";
var $aNumberField = "CallingStationId";
var $disconnectField = "H323DisconnectCause";
var $traceIn = "";
var $traceOut = "";
var $defaultApplicationType = "audio";
var $supportedApplicationTypes = array('audio',
'message',
'video',
'chat',
'file-transfer'
);
function CDR() {
}
function NormalizeDisconnect() {
$causePrint=$this->CDRS->disconnectCodesDescription[$this->disconnect]." (".$this->disconnect.")";
return $causePrint;
}
function traceOut () {
}
function traceIn () {
}
function show() {
}
function normalize($save="",$table="") {
if (!$table) $table = $this->CDRS->table;
if ($this->CDRS->CSCODE && $CarrierInfo = $this->CDRS->CDRTool['normalize']['CS_CODES'][$this->CDRS->CSCODE]) {
// We found a carrier so we set the BillingId
$this->BillingId = $CarrierInfo[BillingPartyId];
}
if ($save) {
if (!$this->id) {
return 0;
}
$query ="";
$query1 ="";
$query2 ="";
if ($this->CDRS->normalizedField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s='1' ",addslashes($this->CDRS->normalizedField));
- $mongo_field = array_search($this->CDRS->normalizedField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = 1;
}
if ($this->CDRS->BillingPartyIdField && $this->BillingPartyId) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->BillingPartyIdField),addslashes($this->BillingPartyId));
- $mongo_field = array_search($this->CDRS->BillingPartyIdField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->BillingPartyId;
}
if (strlen($this->durationNormalized) && $this->durationNormalized != $this->duration) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s ='%s' ",addslashes($this->CDRS->durationField),addslashes($this->durationNormalized));
$this->duration=$this->durationNormalized;
- $mongo_field = array_search($this->CDRS->durationField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = intval($this->durationNormalized);
- } else {
- $mongo_field = array_search($this->CDRS->durationField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = intval($this->duration);
}
if ($this->CDRS->DestinationIdField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->DestinationIdField),addslashes($this->DestinationId));
- $mongo_field = array_search($this->CDRS->DestinationIdField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->DestinationId;
}
if ($this->CDRS->ResellerIdField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->ResellerIdField),addslashes($this->ResellerId));
- $mongo_field = array_search($this->CDRS->ResellerIdField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->ResellerId;
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->usernameField),addslashes($this->usernameNormalized));
- $mongo_field = array_search($this->CDRS->usernameField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->usernameNormalized;
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->aNumberField),addslashes($this->aNumberNormalized));
$this->aNumber=$this->aNumberNormalized;
- $mongo_field = array_search($this->CDRS->aNumberField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->aNumberNormalized;
}
if ($this->CDRS->applicationField && $this->applicationNormalized) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->applicationField), addslashes($this->applicationNormalized));
$this->application=$this->applicationNormalized;
- $mongo_field = array_search($this->CDRS->applicationField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->applicationNormalized;
}
if ($this->CDRS->flowField && $this->flow) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->flowField),addslashes($this->flow));
- $mongo_field = array_search($this->CDRS->flowField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->flow;
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->domainField),addslashes($this->domainNormalized));
$this->domainNumber=$this->domainNormalized;
$this->domain=$this->domainNormalized;
- $mongo_field = array_search($this->CDRS->domainField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->cNumberField),addslashes($this->cNumberNormalized));
$this->cNumber=$this->cNumberNormalized;
- $mongo_field = array_search($this->CDRS->cNumberField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->cNumberNormalized;
}
if ($this->CDRS->BillingIdField && $this->BillingId) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->BillingIdField),addslashes($this->BillingId));
- $mongo_field = array_search($this->CDRS->BillingIdField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->BillingId;
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->RemoteAddressField),addslashes($this->RemoteAddressNormalized));
- $mongo_field = array_search($this->CDRS->RemoteAddressField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->RemoteAddressNormalized;
}
if ($this->CDRS->CanonicalURIField && $this->CanonicalURINormalized && $this->CanonicalURINormalized!= $this->CanonicalURI) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->CanonicalURIField),addslashes($this->CanonicalURINormalized));
- $mongo_field = array_search($this->CDRS->CanonicalURIField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->CanonicalURINormalized;
}
if ($this->stopTimeNormalized) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->stopTimeField),addslashes($this->stopTimeNormalized));
- $mongo_field = array_search($this->CDRS->stopTimeField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->stopTimeNormalized;
}
if ($this->CDRS->ratingEnabled && ($this->duration || $this->application == 'message')) {
if ($this->DestinationId) {
$Rate = new Rate($this->CDRS->rating_settings, $this->CDRS->cdrtool);
if ($this->application == 'message') {
$RateDictionary = array(
'callId' => $this->callId,
'timestamp' => $this->timestamp,
'duration' => $this->duration,
'DestinationId' => $this->DestinationId,
'BillingPartyId' => $this->BillingPartyId,
'ResellerId' => $this->ResellerId,
'domain' => $this->domain,
'gateway' => $this->gateway,
'RatingTables' => $this->CDRS->RatingTables,
'aNumber' => $this->aNumber,
'cNumber' => $this->cNumber
);
$Rate->calculateMessage($RateDictionary);
} else {
$RateDictionary = array(
'callId' => $this->callId,
'timestamp' => $this->timestamp,
'duration' => $this->duration,
'DestinationId' => $this->DestinationId,
'inputTraffic' => $this->inputTraffic,
'outputTraffic' => $this->outputTraffic,
'BillingPartyId' => $this->BillingPartyId,
'ResellerId' => $this->ResellerId,
'domain' => $this->domain,
'gateway' => $this->gateway,
'RatingTables' => $this->CDRS->RatingTables,
'aNumber' => $this->aNumber,
'cNumber' => $this->cNumber,
'ENUMtld' => $this->ENUMtld,
'application' => $this->application
);
$Rate->calculateAudio($RateDictionary);
}
$this->pricePrint = $Rate->pricePrint;
$this->price = $Rate->price;
$this->rateInfo = $Rate->rateInfo;
$this->rateDuration = $Rate->duration;
if ($Rate->broken_rate) {
$this->broken_rate = true;
}
} else {
$this->rateInfo = '';
$this->pricePrint = '';
$this->price = '';
}
// strict mysql query fails when price is being set to ''
if ($this->pricePrint === null || $this->pricePrint === '') {
$this->pricePrint = '0.00';
}
if ($this->CDRS->priceField) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query .= sprintf(
" %s = '%s' ",
addslashes($this->CDRS->priceField),
addslashes($this->pricePrint)
);
- $mongo_field = array_search($this->CDRS->priceField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = floatval($this->pricePrint);
if ($this->CDRS->rateField ) {
if ($updatedFields) $query .= ", ";
$updatedFields++;
$query.=sprintf(" %s = '%s' ",addslashes($this->CDRS->rateField),addslashes($this->rateInfo));
- $mongo_field = array_search($this->CDRS->rateField, $this->CDRS->CDRFields);
- $this->mongo_cdr[$mongo_field] = $this->rateInfo;
}
}
}
$query1 = sprintf(
"update %s set %s where %s = '%s'",
addslashes($table),
$query,
addslashes($this->idField),
addslashes($this->id));
dprint_sql($query1);
- // TODO remove me, I am used to temporary sync mysql data with mongo data
- if ($this->CDRS->mongo_table) {
- $mongo_field = array_search($this->idField, $this->CDRS->CDRFields);
- try {
- $this->CDRS->mongo_table->update(array($mongo_field => $this->id), $this->mongo_cdr, array("upsert" => true));
- } catch (MongoException $e) {
- printf("Caught Mongo exception: %s", $e->getMessage());
- } catch (Exception $e) {
- printf("Caught exception: %s", $e->getMessage());
- }
- }
-
if ($updatedFields) {
if ($this->CDRS->CDRdb1->query($query1)) {
if ($this->CDRS->CDRdb1->affected_rows()) {
if ( $this->isBillingPartyLocal() && $table == "radacct".date('Ym')) {
// cache usage only if current month
$_traffic = ($this->inputTraffic + $this->outputTraffic) / 2;
$_usage = array(
'calls' => 1,
'duration' => $this->duration,
'cost' => $this->price,
'cost_today' => $this->price,
'traffic' => $_traffic
);
$this->cacheQuotaUsage($_usage);
}
} else {
if (preg_match("/^(\w+)(\d{4})(\d{2})$/", $table, $m)) {
$previousTable=$m[1].date('Ym', mktime(0, 0, 0, $m[3]-1, "01", $m[2]));
$query2 = sprintf("update %s set %s where %s = '%s'",addslashes($previousTable),$query,addslashes($this->idField),addslashes($this->id));
if ($this->CDRS->CDRdb1->query($query2)) {
if ($this->CDRS->CDRdb1->affected_rows()) {
if ($this->isBillingPartyLocal() && $previousTable == "radacct".date('Ym')) {
// cache usage only if current month
$_traffic = ($this->inputTraffic + $this->outputTraffic) / 2;
$_usage = array(
'calls' => 1,
'duration' => $this->duration,
'cost' => $this->price,
'cost_today' => $this->price,
'traffic' => $_traffic
);
$this->cacheQuotaUsage($_usage);
}
}
} else {
$log = sprintf(
"Database error: %s (%s)",
$this->CDRS->CDRdb1->Error,
$this->CDRS->CDRdb1->Errno
);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
}
return 1;
} else {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query1,
$this->CDRS->CDRdb1->Error,
$this->CDRS->CDRdb1->Errno
);
syslog(LOG_NOTICE, $log);
print($log);
return 0;
}
}
} else {
if ($this->CDRS->BillingPartyIdField && $CarrierInfo['BillingPartyId']) {
$this->domain = $CarrierInfo['BillingDomain'];
}
if ($this->usernameNormalized && $this->usernameNormalized!=$this->username) {
$this->username = $this->usernameNormalized;
}
if ($this->aNumberNormalized && $this->aNumberNormalized!=$this->aNumber) {
$this->aNumber = $this->aNumberNormalized;
}
if ($this->domainNormalized && $this->domainNormalized != $this->domain) {
$this->domainNumber = $this->domainNormalized;
}
if ($this->cNumberNormalized && $this->cNumberNormalized!=$this->cNumber) {
$this->cNumber = $this->cNumberNormalized;
}
if ($this->CDRS->RemoteAddressField && $this->RemoteAddressNormalized && $this->RemoteAddressNormalized!= $this->RemoteAddress) {
$this->RemoteAddress = $this->RemoteAddressNormalized;
}
}
return 1;
}
function cacheQuotaUsage($usage)
{
if (!is_array($usage)) return ;
$accounts[$this->BillingPartyId]['usage'] = $usage;
$this->CDRS->cacheQuotaUsage($accounts);
}
function isCallerLocal()
{
return false;
}
function isCalleeLocal()
{
return false;
}
function isBillingPartyLocal()
{
return false;
}
function obfuscateCallerId()
{
global $obfuscateCallerId;
if ($obfuscateCallerId) {
}
}
function lookupRateFromNetwork($RateDictionary, $fp)
{
$this->rateInfo='';
$this->pricePrint='';
$this->price='';
$countEndofLines=0;
$cmd="ShowPrice";
foreach (array_keys($RateDictionary) as $key) {
$cmd .=" ".$key."=".$RateDictionary[$key]." ";
}
$this->price = 0;
$this->pricePrint = "";
$this->rateInfo = "";
if (fputs($fp,"$cmd\n") !== false) {
$i=0;
while ($i < 100) {
$i++;
$line = fgets($fp,1024);
if (!$line) {
syslog(LOG_NOTICE, "Error: lookupRateFromNetwork(): connection to network socket died");
break;
}
if (preg_match("/^\n/",$line) || preg_match("/^END/",$line)) {
break;
}
if ($i == 1) {
$this->price = trim($line);
$this->pricePrint = number_format($this->price, 4);
continue;
}
$this->rateInfo.=$line;
}
}
}
function lookupGeoLocation($ip)
{
if ($_loc=geoip_record_by_name($ip)) {
return $_loc['country_name'].'/'.$_loc['city'];
} else if ($_loc=geoip_country_name_by_name($ip)) {
return $_loc;
} else {
return '';
}
}
}
function getLocalTime($timezone,$timestamp) {
global $CDRTool;
if (!$timezone || $timezone == $CDRTool['provider']['timezone']) {
return date("Y-m-d H:i:s", $timestamp);
}
putenv("TZ=$timezone");
$startTimeLocal=date("Y-m-d H:i:s", $timestamp);
$timezone=$CDRTool['provider']['timezone'];
putenv("TZ=$timezone");
return $startTimeLocal;
}
function validDay($month,$day,$year) {
if (!$month || !$year) {
return $day;
}
while (1) {
if (!checkdate($month,$day,$year) && $day) {
$day--;
next;
} else {
break;
}
}
return $day;
}
// include CDRTool modules defined in global.inc
if (is_array($CDRToolModules)) {
foreach ($CDRToolModules as $module) {
$module_filename="cdr_".$module.".php";
include($module_filename);
}
}
function unLockNormalization ($dbid,$lockname) {
$query=sprintf("SELECT RELEASE_LOCK('%s')",addslashes($lockname));
$log=sprintf("Unlock %s",$lockname);
syslog(LOG_NOTICE, $log);
if (!$dbid->query($query)) {
$log="Error in unLockNormalization()";
syslog(LOG_NOTICE, $log);
}
}
class SIPonline {
function SIPonline ($datasource='',$database='db',$table='location') {
global $CDRTool;
$expandAll = $_REQUEST['expandAll'];
$domain = $_REQUEST['domain'];
$this->expandAll = $expandAll;
$this->domain = $domain;
$this->datasource = $datasource;
if (strlen($CDRTool['filter']['domain'])) {
$this->allowedDomains=explode(" ",$CDRTool['filter']['domain']);
$allowed_domains_sql="";
$j=0;
foreach ($this->allowedDomains as $_domain) {
if ($j>0) $allowed_domains_sql.=",";
$allowed_domains_sql.="'".addslashes($_domain)."'";
$j++;
}
}
$this->locationDB = new $database;
$this->locationTable = $table;
$this->Registered=array();
$this->countUA=array();
$where = " where (1=1) " ;
if ($allowed_domains_sql) {
$where.= sprintf("and domain in (%s)",addslashes($allowed_domains_sql)) ;
}
$query=sprintf("select count(*) as c, domain from %s %s group by domain order by domain ASC",
addslashes($this->locationTable),
$where
);
$this->locationDB->query($query);
$this->domains=$this->locationDB->num_rows();
while ($this->locationDB->next_record()) {
$this->Registered[$this->locationDB->f('domain')]=$this->locationDB->f('c');
$this->total=$this->total+$this->locationDB->f('c');
}
$query=sprintf("select count(*) as c, user_agent from %s %s",addslashes($this->locationTable),$where);
if ($this->domain) {
$query.=sprintf(" and domain = '%s' ",addslashes($this->domain));
}
$query.="
group by user_agent
order by c DESC";
$this->locationDB->query($query);
while ($this->locationDB->next_record()) {
$this->countUA[$this->locationDB->f('user_agent')]=$this->locationDB->f('c');
}
}
function showHeader() {
print "<table id='opensips_registrar' class='table table-striped table-condensed'>";
print "<thead><tr>
";
if ($this->domain) {
print "
<th></th>
<th width=120 align=right>User@Domain</th>
<th></th>
<th>SIP UA contact</th>
<th>NAT address</th>
<th>User Agent</th>
<th>Expires</th>
<th>Remain</th>
";
} else {
print "
<th></td>
<th align=right>Users@</th>
<th>Domain</th>
";
}
print "
</tr></thead>
";
}
function showFooter() {
print "
<tr>
<th></th>
<th align=right>$this->total users@</td>
<th align=left>$this->domains domains</td>
</tr>
</table>
";
}
function showAll() {
global $found;
$this->showHeader();
foreach (array_keys($this->Registered) as $ld) {
$onlines=$this->Registered[$ld];
if ($this->expandAll || ($this->domain && $this->domain==$ld)) {
$this->show($ld);
} else {
$found++;
$url = sprintf("%s?datasource=%s&domain=%s",
$_SERVER['PHP_SELF'],
urlencode($this->datasource),
urlencode($ld)
);
print "
<tr>
<td valign=top align=right>$found</td>
<td valign=top align=right>$onlines users@</td>
<td valign=top><a href=$url>$ld</a></td>
";
if ($this->domain) {
print "
<td></td>
<td></td>
<td></td>
<td></td>
";
}
print "
</tr>
";
}
}
$this->showfooter();
/*
print "<p>";
$this->showUAdistribution();
*/
}
function show() {
global $found;
$query="SELECT *, SEC_TO_TIME(UNIX_TIMESTAMP(expires)-UNIX_TIMESTAMP(NOW())) AS remain
FROM location
";
if ($this->domain) $query.=sprintf(" where domain = '%s'", addslashes($this->domain));
$query.= " ORDER BY domain ASC, username ASC ";
$this->locationDB->query($query);
while ($this->locationDB->next_record()) {
$found++;
$username = $this->locationDB->f('username');
$domain = $this->locationDB->f('domain');
$contact = $this->locationDB->f('contact');
$received = $this->locationDB->f('received');
$user_agent = $this->locationDB->f('user_agent');
$expires = $this->locationDB->f('expires');
$remain = $this->locationDB->f('remain');
$contact_print=substr($contact,4);
$c_els=explode(";", $contact);
$r_els=explode(";", $received);
$transport="UDP";
if ($c_els[1] && preg_match("/transport=(tcp|tls)/i",$c_els[1],$m)) {
$transport=strtoupper($m[1]);
}
$sip_account=$username."@".$domain;
print "
<tr>
<td valign=top align=right>$found</td>
<td valign=top>$sip_account</td>
<td valign=top>$transport</td>
<td valign=top align=right>$c_els[0]</td>
<td valign=top align=right>$r_els[0]</td>
<td valign=top>$user_agent</td>
<td valign=top>$expires</td>
<td valign=top align=right>$remain</td>
</tr>
";
$seen[$username]++;
$seen[$domain]++;
}
}
function showUAdistribution () {
print "<table border=0 cellspacing=1 class=border>";
print "<tr bgcolor=lightgrey> ";
print "<td></td>";
print "<th>User agent</th>";
print "<th>Users</th>";
print "</tr> ";
while (list($k,$v) = each($this->countUA)) {
$users=$users+$v;
$count++;
print "<tr> ";
print "<td>$count</td>";
print "<td>$k</td>";
print "<td>$v</td>";
print "</tr>";
}
print "<tr bgcolor=lightgrey> ";
print "<td></td>";
print "<td><b>$this->domain</b></td>";
print "<td><b>$users</b></td>";
print "</tr> ";
print "</table>";
}
}
class PrepaidHistory {
function PrepaidHistory() {
$this->db = new DB_cdrtool;
}
function purge($days=7) {
$beforeDate=Date("Y-m-d", time()-$days*3600*24);
$query=sprintf("delete from prepaid_history where date < '%s' and action like 'Debit balance%s'",addslashes($beforeDate),'%');
if (!$this->db->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)\n",$query,$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE,$log);
} else {
$log=sprintf ("Purged %d records from prepaid history before %s\n",$this->db->affected_rows(),$beforeDate);
print $log;
syslog(LOG_NOTICE,$log);
}
}
}
class CSVWritter {
var $csv_directory = '/var/spool/cdrtool/normalize';
var $filename_extension = '.csv';
var $fields = array();
var $ready = false;
var $cdr_type = array();
var $lines = 0;
function CSVWritter($cdr_source='',$csv_directory='') {
if ($cdr_source) {
$this->cdr_source = $cdr_source;
} else {
$this->cdr_source = 'unknown';
}
if ($csv_directory) {
if (is_dir($csv_directory)) {
$this->csv_directory = $csv_directory;
} else {
$log=sprintf ("CSV writter error: %s is not a directory\n",$csv_directory);
syslog(LOG_NOTICE,$log);
return false;
}
}
$this->directory=$this->csv_directory."/".date("Ymd");
if (!is_dir($this->directory)) {
if (!mkdir($this->directory)) {
$log=sprintf ("CSV writter error: cannot create directory %s\n",$this->directory);
syslog(LOG_NOTICE,$log);
return false;
}
chmod($this->directory, 0775);
}
$this->directory_ready = true;
}
function open_file ($filename_suffix='') {
if ($this->ready) return true;
if (!$this->directory_ready) return false;
if (!$filename_suffix) {
$log=sprintf ("CSV writter error: no filename suffix provided\n");
syslog(LOG_NOTICE,$log);
return false;
}
$this->filename_prefix = strtolower($this->cdr_source).'-'.date('YmdHi');
$this->full_path=rtrim($this->directory,'/').'/'.$this->filename_prefix.'-'.$filename_suffix.$this->filename_extension;
$this->full_path_tmp=$this->full_path.'.tmp';
if (!$this->fp = fopen($this->full_path_tmp, 'w')) {
$log=sprintf ("CSV writter error: cannot open %s for writing\n",$this->full_path_tmp);
syslog(LOG_NOTICE,$log);
return false;
}
$this->ready = true;
return true;
}
function close_file () {
if (!$this->ready) return false;
fclose($this->fp);
if (!rename($this->full_path_tmp, $this->full_path)) {
$log=sprintf ("CSV writter error: cannot rename %s to %s\n",$this->full_path_tmp,$this->full_path);
syslog(LOG_NOTICE,$log);
} else {
$log=sprintf ("%d normalized CDRs written to %s\n",$this->lines, $this->full_path);
syslog(LOG_NOTICE,$log);
}
}
function write_cdr ($CDR) {
if (!$this->ready) return false;
$line = sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
$CDR->id,
$CDR->callId,
$CDR->flow,
$CDR->application,
$CDR->username,
$CDR->CanonicalURI,
$CDR->startTime,
$CDR->stopTime,
$CDR->duration,
$CDR->DestinationId,
$CDR->BillingPartyId,
$CDR->ResellerId,
$CDR->price
);
if (!fputs($this->fp,$line)) {
$this->ready = false;
return false;
}
$this->lines++;
return true;
}
}
class MaxRate extends CSVWritter {
var $skip_prefixes = array();
var $skip_numbers = array();
var $skip_domains = array();
var $rpid_cache = array();
var $translate_uris = array();
function MaxRate ($cdr_source='', $csv_directory='', $db_subscribers='') {
global $MaxRateSettings; // set in global.inc
/*
$MaxRateSettings= array(
'translate_uris'=> array( '1233@10.0.0.2'=>'+1233',
'[1-9][0-9]{4}.*@10.0.0.2'=>'+1233'),
'skip_domains' => array('example.net','10.0.0.1'),
'skip_numbers' => array('1233'), // skip CDRs that has the username part in this array
'skip_prefixes' => array('0031901') // skip CDRs that begin with any of this prefixes
);
*/
if (is_array($MaxRateSettings['skip_domains'])) {
$this->skip_domains=$MaxRateSettings['skip_domains'];
}
if (is_array($MaxRateSettings['skip_numbers'])) {
$this->skip_numbers=$MaxRateSettings['skip_numbers'];
}
if (is_array($MaxRateSettings['skip_prefixes'])) {
$this->skip_prefixes=$MaxRateSettings['skip_prefixes'];
}
if (is_array($MaxRateSettings['translate_uris'])) {
$this->translate_uris=$MaxRateSettings['translate_uris'];
}
$this->AccountsDB = new $db_subscribers();
$this->CSVWritter($cdr_source, $csv_directory);
}
function write_cdr($CDR) {
if (!$this->ready) return false;
# skip if no audio
if ($CDR->application != 'audio') return true;
# skip if no duration
if (!$CDR->duration && ($CDR->disconnect != 200)) return true;
# normalize destination
if ($CDR->CanonicalURIE164) {
$cdr['destination'] = '+'.$CDR->CanonicalURIE164;
} else {
$cdr['destination'] = $CDR->CanonicalURI;
}
list($canonical_username, $canonical_domain)=explode("@",$cdr['destination']);
# skip domains
if ($canonical_domain && in_array($canonical_domain,$this->skip_domains)) return true;
# skip numbers
if ($canonical_username && in_array($canonical_username,$this->skip_numbers)) return true;
# skip prefixes
if ($canonical_username && count($this->skip_prefixes)) {
foreach ($this->skip_prefixes as $prefix) {
if (preg_match("/^$prefix/",$canonical_username)) return true;
}
}
# get RPID if caller is local
if ($CDR->flow != 'incoming') {
$CallerRPID=$this->getRPIDforAccount($CDR->aNumberPrint);
}
if ($CallerRPID) {
# normalize RPID
$cdr['origin'] = '0031'.ltrim($CallerRPID,'0');
} else {
# normalize caller id numbers from PSTN gateway to 00format
if (preg_match("/^\+?0([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+?00([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+([1-9][0-9]+)@(.*)$/",$CDR->aNumberPrint,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^anonymous@(.*)$/",$CDR->aNumberPrint) && $CDR->SipRPID) {
if (preg_match("/^\+?0([1-9][0-9]+)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031".$m[1];
} else if (preg_match("/^\+?00([1-9][0-9]+)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^([1-9][0-9]+)@(.*)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = $m[1];
} else if (preg_match("/^\+([1-9][0-9]+)@(.*)$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "00".$m[1];
} else if (preg_match("/^\+?0[0-9]?+@?(.*)?$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else if (preg_match("/^.*[a-zA-Z].*$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else if (preg_match("/^ims.imscore.net.*$/",$CDR->SipRPID,$m)) {
$cdr['origin'] = "0031123456789";
} else {
$cdr['origin'] = $CDR->SipRPID;
}
} else {
$cdr['origin'] = "0031123456789";
//$cdr['origin'] = $CDR->aNumberPrint;
}
}
# normalize short origins
if (preg_match("/^\d{1,3}@.*$/",$cdr['origin'])) {
$cdr['origin']='+31000000000';
}
# normalize anonymous origins
if (preg_match("/^anonymous@.*$/",$cdr['origin'])) {
$cdr['origin']='+31000000000';
}
#translate destination URIs to desired format
if ($CDR->CanonicalURINormalized && count($this->translate_uris)) {
foreach ($this->translate_uris as $key => $uri) {
if ( preg_match("/^$key/", $CDR->CanonicalURINormalized)) {
$cdr['destination']=$uri;
break;
}
}
}
preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2})$/",$CDR->startTime,$m);
$cdr['start_date'] = sprintf ("%s/%s/%s %s",$m[3],$m[2],$m[1],$m[4]);
$cdr['diversion'] = '';
preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2})$/",$CDR->stopTime,$m);
$cdr['stop_date'] = sprintf ("%s/%s/%s %s",$m[3],$m[2],$m[1],$m[4]);
$cdr['product'] = $this->product;
# normalize duration based on billed duration
if ($CDR->rateDuration) {
$cdr['duration'] = $CDR->rateDuration;
} else {
$cdr['duration'] = $CDR->duration;
}
$rate_info = explode("\n", $CDR->rateInfo);
for ($i = 0; $i < sizeof($rate_info); ++$i)
{
//dprint_r($rate_info[$i]);
if (strpos($rate_info[$i], "ProfileId:") !== false)
{
$cdr['profile'] = ltrim(str_replace("ProfileId: ", '', $rate_info[$i]));
}
}
//$cdr['extra']="$CDR->callId";
list($cdr['username'],$cdr['domain'])= explode('@',$CDR->username);
$cdr['charge_info'] = sprintf('"%s","%s","%s"',$CDR->price,$cdr['profile'],$CDR->destinationName);
if ($CDR->flow == 'on-net') {
# RFP 4.2.1
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['destination'] = '0031'.ltrim($CalleeRPID,'0');
}
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'outgoing') {
# RFP 4.2.2
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'incoming') {
# RFP 4.2.3
if ($this->inbound_trunks[$CDR->SourceIP]) {
$inbound_trunk = $this->inbound_trunks[$CDR->SourceIP];
} else {
$inbound_trunk = 'unknown';
}
$cdr['username'] = $canonical_username;
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['destination'] = '0031'.ltrim($CalleeRPID,'0');
}
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'diverted-on-net') {
# RFP 4.2.4
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
if ($CalleeRPID) {
$cdr['c_num'] = '0031'.ltrim($CalleeRPID,'0');
}
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."incoming-diverted-on-net";
} else if ($CDR->flow == 'diverted-off-net') {
# RFP 4.2.5
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$cdr['c_num'] = $cdr['destination'];
# Set destination to B-Number
$cdr['destination']=$diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."incoming-diverted-off-net";
} else if ($CDR->flow == 'on-net-diverted-on-net') {
# RFP 4.2.6
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$CalleeRPID=$this->getRPIDforAccount($CDR->CanonicalURI);
if ($CalleeRPID) {
$cdr['c_num'] = '0031'.ltrim($CalleeRPID,'0');
}
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."$CDR->flow";
} else if ($CDR->flow == 'on-net-diverted-off-net') {
# RFP 4.2.7
$DiverterRPID=$this->getRPIDforAccount($CDR->username);
if ($DiverterRPID) {
$diverter_origin = '0031'.ltrim($DiverterRPID,'0');
} else {
$diverter_origin = $CDR->username;
}
$cdr['c_num']= $cdr['destination'];
# Set destination to B-Number
$cdr['destination'] = $diverter_origin;
$cdr['diversion'] = $cdr['c_num'];
$cdr['extra'] = $cdr['extra']."$CDR->flow";
}
$cdr['username'] = preg_replace('/caiw0+|test0+/', "", $cdr['username']);
$cdr['origin'] = str_replace('+','00',$cdr['origin']);
$cdr['destination'] = str_replace('+','00',$cdr['destination']);
$cdr['diversion'] = str_replace('+','00',$cdr['diversion']);
$line = sprintf('"%s","%s","%s","%s","%s","%s","%s","%s","%s",%s'."\n",
$CDR->callId,
$cdr['origin'],
$cdr['username'],
$cdr['destination'],
$cdr['diversion'],
$cdr['start_date'],
$cdr['stop_date'],
$cdr['duration'],
$cdr['extra'],
$cdr['charge_info']
);
if (!fputs($this->fp,$line)) {
$log=sprintf ("CSV writter error: cannot append to file %s\n",$this->full_path_tmp);
syslog(LOG_NOTICE,$log);
$this->close_file();
$this->ready = false;
return false;
}
$this->lines++;
return true;
}
function getRPIDforAccount($account) {
if (!$account) return false;
if ($this->rpid_cache[$account]) {
return $this->rpid_cache[$account];
}
list($username,$domain) = explode('@',$account);
$query=sprintf("select * from sip_accounts where username = '%s' and domain = '%s'",addslashes($username),addslashes($domain));
if (!$this->AccountsDB->query($query)) {
$log=sprintf ("Database error for query %s: %s (%s)",$query,$this->AccountsDB->Error,$this->AccountsDB->Errno);
syslog(LOG_NOTICE,$log);
return false;
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
$this->rpid_cache[$account]=$_profile->rpid;
return $_profile->rpid;
} else {
return false;
}
}
}
?>
diff --git a/library/cdr_opensips.php b/library/cdr_opensips.php
index 3a643b8..e5e5469 100644
--- a/library/cdr_opensips.php
+++ b/library/cdr_opensips.php
@@ -1,5988 +1,5124 @@
<?php
class CDRS_opensips extends CDRS
{
public $table = "radacct";
public $CDR_class = "CDR_opensips";
public $subscriber_table = "subscriber";
public $ENUMtld = '';
public $maxCDRsNormalizeWeb = 500;
public $sipTrace = 'sip_trace';
public $mediaTrace = 'media_trace';
public $missed_calls_group = 'missed-calls';
public $rate_on_net_group = 'rate-on-net';
public $callerid_cache = array();
public $CDRFields = array(
'id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'flow' => 'ServiceType',
'aNumber' => 'CallingStationId',
'username' => 'UserName',
'domain' => 'Realm',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'SipMethod' => 'SipMethod',
'disconnect' => 'SipResponseCode',
'disconnectOrig' => 'AcctTerminateCause',
'SipFromTag' => 'SipFromTag',
'SipToTag' => 'SipToTag',
'RemoteAddress' => 'SipTranslatedRequestURI',
'SipCodec' => 'SipCodecs',
'SipUserAgents' => 'SipUserAgents',
'application' => 'SipApplicationType',
'BillingPartyId' => 'UserName',
'SipRPID' => 'SipRPID',
'SipProxyServer' => 'NASIPAddress',
'MediaRelay' => 'FramedIPAddress',
'gateway' => 'SourceIP',
'SourceIP' => 'SourceIP',
'SourcePort' => 'SourcePort',
'CanonicalURI' => 'CanonicalURI',
'normalized' => 'Normalized',
'rate' => 'Rate',
'price' => 'Price',
'DestinationId' => 'DestinationId',
'ResellerId' => 'BillingId',
'MediaInfo' => 'MediaInfo',
'RTPStatistics' => 'RTPStatistics',
'ENUMtld' => 'ENUMtld',
'UserAgent' => 'UserAgent',
'FromHeader' => 'FromHeader'
);
public $CDRNormalizationFields = array(
'id' => 'RadAcctId',
'callId' => 'AcctSessionId',
'username' => 'UserName',
'domain' => 'Realm',
'gateway' => 'SourceIP',
'duration' => 'AcctSessionTime',
'startTime' => 'AcctStartTime',
'stopTime' => 'AcctStopTime',
'inputTraffic' => 'AcctInputOctets',
'outputTraffic' => 'AcctOutputOctets',
'aNumber' => 'CallingStationId',
'cNumber' => 'CalledStationId',
'timestamp' => 'timestamp',
'disconnect' => 'SipResponseCode',
'RemoteAddress' => 'SipTranslatedRequestURI',
'CanonicalURI' => 'CanonicalURI',
'SipRPID' => 'SipRPID',
'SipMethod' => 'SipMethod',
'application' => 'SipApplicationType',
'flow' => 'ServiceType',
'BillingPartyId' => 'UserName',
'ResellerId' => 'BillingId',
'price' => 'Price',
'DestinationId' => 'DestinationId',
'ENUMtld' => 'ENUMtld'
);
public $GROUPBY = array(
'UserName' => 'SIP Billing Party',
'CallingStationId' => 'SIP Caller Party',
'SipRPID' => 'SIP Remote Party Id',
'CanonicalURI' => 'SIP Canonical URI',
'DestinationId' => 'SIP Destination Id',
'NASIPAddress' => 'SIP Proxy',
'FramedIPAddress' => 'Media Relay',
'MediaInfo' => 'Media Information',
'SourceIP' => 'Source IP',
'Realm' => 'SIP Billing domain',
'UserAgent' => 'User Agent',
'SipCodecs' => 'Codec type',
'SipApplicationType' => 'Application',
'SipResponseCode' => 'SIP status code',
'BillingId' => 'Tech prefix',
'ServiceType' => 'Call Flow',
' ' => '-------------',
'hour' => 'Hour of day',
'DAYOFWEEK' => 'Day of Week',
'DAYOFMONTH' => 'Day of Month',
'DAYOFYEAR' => 'Day of Year',
'BYMONTH' => 'Month',
'BYYEAR' => 'Year'
);
public $FormElements = array(
"begin_hour","begin_min","begin_month","begin_day","begin_year","begin_datetime","begin_time","end_time",
"end_hour","end_min","end_month","end_day","end_year","end_datetime","end_date","begin_date",
"call_id","sip_proxy", "media_relay",
"a_number","a_number_comp","UserName","UserName_comp","BillingId",
"c_number","c_number_comp","DestinationId","ExcludeDestinations",
"NASPortId","Realm","Realms",
"SipMethod","SipCodec","SipRPID","UserAgent",
"application","sip_status","sip_status_class","gateway",
"duration","action","MONTHYEAR",
"order_by","order_type","group_by",
"cdr_source","trace",
"ReNormalize","media_info","cdr_table","maxrowsperpage", "flow"
);
function initCDRFields()
{
// init names of CDR fields
foreach (array_keys($this->CDRFields) as $field) {
$mysqlField=$this->CDRFields[$field];
$_field=$field."Field";
$this->$_field=$mysqlField;
}
}
function LoadDisconnectCodes()
{
$query="select * from sip_status order by code";
$this->disconnectCodesElements[]=array("label"=>"Any Status","value"=>"");
$this->disconnectCodesElements[]=array("label"=>"Undefined (0)","value"=>"0");
$this->disconnectCodesClassElements[]=array("label"=>"Any Status Class","value"=>"");
if ($this->cdrtool->query($query)) {
while ($this->cdrtool->next_record()) {
$key = $this->cdrtool->f('code');
$value = $this->cdrtool->f('description');
$value_print = $this->cdrtool->f('description')." (".$this->cdrtool->f('code').")";
if (preg_match("/^[^2-6]/", $key)) {
continue;
}
$this->disconnectCodesElements[]=array("label"=>$value_print,"value"=>$key);
$this->disconnectCodesDescription[$key]=$value;
$class = substr($key, 0, 1);
$class_text = substr($key, 0, 1)."XX (".$this->cdrtool->f('code_type').")";
if (!$seen[$class]) {
$this->disconnectCodesClassElements[]=array("label"=>$class_text,"value"=>substr($key, 0, 1));
$this->disconnectCodesClassDescription[substr($key, 0, 1)]=$class_text;
$seen[$class]++;
}
$i++;
}
}
}
function showTableHeader()
{
print "
<table class='table table-hover table-condensed'>
<thead>
<tr>
<th>Id</th>
<th>Start Time</th>
<th>Media/Flow</th>
<th>SIP Caller</th>
<th>Caller Location</th>
<th>Sip Proxy</th>
<th>Media Relay</th>
<th>SIP Destination</th>
<th>Dur</th>
<th>Price</th>
<th>KBIn</th>
<th>KBOut</th>
<th class='pull-right'>Status</th>
</tr>
</thead>
";
}
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 "
<table class='table table-striped table-condensed'>
<thead>
<tr>
<th>Id</th>
<th>Start Time</th>
<th>SIP Caller</th>
<th>Caller Location</th>
<th>Sip Proxy</th>
<th>SIP Destination</th>
<th>Duration</th>
<th>Price</th>
<th>KBIn</th>
<th>KBOut</th>
</tr>
</thead>
";
} 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 "
<table class='table table-striped table-condensed'>
<thead>
<tr>
<th></th>
<th>Calls</th>
<th>Seconds</th>
<th>Minutes</th>
<th>Hours</th>
<th>Price</th>
<th>TrafficIn(MB)</th>
<th>TrafficOut(MB)</th>
<th colspan=2>Success</th>
<th colspan=2>Failure</th>
<th>$group_byPrint</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
";
} 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"=>"more than 2 minutes","value"=>"> 120"),
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"=>"media_relay",
"type"=>"text",
"size"=>"25",
"maxlength"=>"255",
"value"=>$media_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 "<table id='search' class='table table-bordered table-condensed' cellpadding=5 width=100% align=center>";
$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 "
<tr>
<td align=left>
<b>SIP Call Id / Source IP</b>
</td>
<td>
<div class=\"input-prepend\">
<div class=\"input-append\">";
$this->f->show_element("call_id", "");
print "<span class=\"add-on\">/</span></div>";
$this->f->show_element("gateway", "");
print "</div>
Sip Proxy ";
$this->f->show_element("sip_proxy", "");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>User Agent / Media Codecs</b>
</td>
<td >
";
$this->f->show_element("UserAgent", "");
print " Codec: ";
$this->f->show_element("SipCodec", "");
print " Relay:";
$this->f->show_element("media_relay", "");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>SIP Billing Party (Username)</b>
</td>
<td>
";
$this->f->show_element("UserName_comp", "");
print "
<div class=\"input-prepend\">
<div class=\"input-append\">
";
$this->f->show_element("UserName", "");
print "<span class=\"add-on\">@</span></div>";
$this->f->show_element("Realm", "");
print "</div> Tech prefix: ";
$this->f->show_element("BillingId", "");
print "</div>
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
SIP Caller Party (From URI)
</b>
</td>
<td valign=top>
";
$this->f->show_element("a_number_comp", "");
print "&nbsp;";
$this->f->show_element("a_number");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>SIP Destination (Canonical URI)
</b>
</td>
<td valign=top> ";
$this->f->show_element("c_number_comp", "");
print "&nbsp;";
$this->f->show_element("c_number", "");
print " Exclude: ";
$this->f->show_element("ExcludeDestinations_comp");
$this->f->show_element("ExcludeDestinations", "");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>Application / Call Flow</b>
</td>
<td valign=top> ";
$this->f->show_element("flow", "");
print "&nbsp;";
$this->f->show_element("application", "");
print " Media Info: ";
$this->f->show_element("media_info", "");
print "
</td>
</tr>
";
print "
<tr>
<td align=left>
<b>Duration / Status</b>
</td>
<td valign=top> ";
$this->f->show_element("duration", "");
print "&nbsp;";
$this->f->show_element("sip_status", "");
print "&nbsp;";
$this->f->show_element("sip_status_class", "");
print "
</td>
</tr>
";
print "
<tr>
<td align=left>
<b>Order by / Group by</b>
</td>
<td valign=top>
";
$this->f->show_element("order_by", "");
print "&nbsp;";
$this->f->show_element("order_type", "");
if ($perm->have_perm("statistics")) {
print " Group by ";
$this->f->show_element("group_by", "");
}
print " Max results per page ";
$this->f->show_element("maxrowsperpage", "");
print "</nobr>&nbsp";
if (!$perm->have_perm('readonly')) {
print ";&nbsp;&nbsp; <nobr>ReNormalize ";
print "<input type=checkbox name=ReNormalize value=1>
";
}
print "
</td>
</tr>
";
print "
</table>
<p>
<center>
";
$this->f->show_element("submit", "");
$this->f->finish();
print "
</center>
";
}
function searchFormSubscriber()
{
global $perm;
$this->initForm();
$this->f->start("", "POST", "", "", "datasource");
print "
<table id='search' class='table table-bordered table-condensed' cellpadding=5 width=100% align=center>
";
$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 "
<tr>
<td align=left>
<b>
SIP Caller Party
</b>
</td>
<td valign=top>
";
$this->f->show_element("a_number", "");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
SIP Billing Party
</b>
</td>
<td valign=top>
";
$this->f->show_element("UserName", "");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>
SIP Destination
</b>
</td>
<td valign=top> ";
$this->f->show_element("c_number_comp", "");
$this->f->show_element("c_number", "");
//$this->f->show_element("DestinationId","");
print "
</td>
</tr>
<tr>
</tr>
";
print "
<tr>
<td align=left>
<b>SIP Session duration</b>
</td>
<td valign=top> ";
$this->f->show_element("duration", "");
print " Application ";
$this->f->show_element("application", "");
print "
</td>
</tr>
";
print "
<tr>
<td align=left>
<b>Order by</b>
</td>
<td valign=top>
";
$this->f->show_element("order_by", "");
$this->f->show_element("order_type", "");
if ($perm->have_perm("statistics")) {
print " Group by ";
$this->f->show_element("group_by", "");
}
print " Max results per page ";
$this->f->show_element("maxrowsperpage", "");
print "
</td>
</tr>
";
print "
</table>
<p>
<center>
";
$this->f->show_element("submit", "");
$this->f->finish();
print "
</center>
";
}
function 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']);
} elseif ($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));
} elseif (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));
} elseif (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));
} elseif (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 (");
$count_realms = count($Realms);
$j = 1;
foreach ($Realms as $realm) {
$where .= sprintf(" ( %s like '%%%s' or %s like '%%%s' ) ", $this->domainField, addslashes($realm), $this->CanonicalURIField, addslashes($realm));
if ($j < $count_realms) {
$where .= " or ";
}
$j = $j + 1;
}
$where .= ") ";
} elseif ($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 ($media_relay) {
$media_relay = urldecode($media_relay);
$where .= " and $this->MediaRelayField = '".addslashes($media_relay)."'";
$this->url.=sprintf("&media_relay=%s", urlencode($media_relay));
}
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)."'";
} elseif ($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)";
} elseif (preg_match("/^DAY/", $group_by)) {
$group_by="$group_by(AcctStartTime)";
} elseif (preg_match("/BYMONTH/", $group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y-%m')";
} elseif (preg_match("/BYYEAR/", $group_by)) {
$group_by="DATE_FORMAT(AcctStartTime,'%Y')";
} elseif ($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_sql($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 "<div class=\"alert alert-info\">";
print "<i class='icon-info-sign icon-large'></i>&nbsp;&nbsp;";
printf("<b><span class=\"alert-heading\">%d</span></b> CDRs normalized. ", $this->status['normalized']);
if ($this->status['cached_keys']['saved_keys']) {
printf("Quota usage updated for <b><span class=\"alert-heading\">%d</span></b> accounts. ", $this->status['cached_keys']['saved_keys']);
}
print "</div>";
}
}
}
}
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_sql($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";
}
} elseif ($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);
} elseif ($this->group_byOrig==$this->CanonicalURIField) {
$traceField="c_number";
$traceValue = urlencode($mygroup);
} elseif ($this->group_byOrig==$this->SipProxyServerField) {
$traceField="sip_proxy";
$traceValue = urlencode($mygroup);
} elseif ($this->group_byOrig==$this->MediaRelayField) {
$traceField="media_relay";
$traceValue = urlencode($mygroup);
} elseif ($this->group_byOrig==$this->SipCodecField) {
$traceField="SipCodec";
} elseif (preg_match("/UserAgent/", $this->group_byOrig)) {
$traceField="UserAgent";
} elseif (preg_match("/^BY/", $this->group_byOrig)) {
$traceField="MONTHYEAR";
} elseif ($this->group_byOrig==$this->callIdField) {
$traceField="call_id";
} elseif ($this->group_byOrig=="DAYOFWEEK") {
if ($mygroup == "1") {
$description="Sunday";
} elseif ($mygroup == "2") {
$description="Monday";
} elseif ($mygroup == "3") {
$description="Tuesday";
} elseif ($mygroup == "4") {
$description="Wednesday";
} elseif ($mygroup == "5") {
$description="Thursday";
} elseif ($mygroup == "6") {
$description="Friday";
} elseif ($mygroup == "7") {
$description="Saturday";
}
} elseif ($this->group_byOrig=="DAYOFMONTH") {
$description =$this->CDRdb->f('day');
} elseif ($this->group_byOrig=="DAYOFYEAR") {
$description =$this->CDRdb->f('day');
} elseif ($this->group_byOrig=="SourceIP") {
$traceField="gateway";
} elseif ($this->group_byOrig=="SipResponseCode") {
$description =$this->disconnectCodesDescription[$mygroup];
$traceField="sip_status";
} elseif ($this->group_byOrig=="SipApplicationType") {
$traceField="application";
} elseif ($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 "
<tr>
<td><b>$found</b></td>
<td align=right>$calls</td>
<td align=right>$seconds_print</td>
<td align=right>$minutes_print</td>
<td align=right>$hours</td>
";
if ($perm->have_perm("showPrice")) {
$pricePrint = number_format($price, 4, ".", "");
} else {
$pricePrint = 'x.xxx';
}
print "
<td align=right>$pricePrint</td>
<td align=right>$AcctInputOctets</td>
<td align=right>$AcctOutputOctets</td>
<td align=right>$success%</td>
<td align=right>($nonzero calls)</td>
<td align=right>$failure%</td>
<td align=right>($zero calls)</td>
<td>$mygroup_print</td>
<td>$description</td>
<td>";
printf(
"<a href=%s&%s=%s&%s_comp=%s target=_new>Display calls</a></td>",
$url_calls,
$traceField,
$traceValue_enc,
$traceField,
$comp_type
);
print "</tr>";
} 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 "</table>";
}
} else {
if (!$this->export) {
// printf ("<div class='alert alert-info'><i style='font-size:13px' class='icon-info-sign'></i> For more information about each call click on its Id column.</div>");
}
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 "</table>";
}
}
$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]));
} elseif ($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("<h2>Missed Calls</h2>
<p>
<table border=0>
<tr>
<th>
</th>
<th>Date and Time
</th>
<th>Caller
</th>
</tr>
");
$i=0;
foreach ($sessions['missed'] as $_session) {
$i++;
if ($i >= $count) {
break;
}
$htmlBody .= sprintf(
"
<tr>
<td>%s</td>
<td>%s</td>
<td><a href=sip:%s>sip:%s</a></td>
</tr>
",
$i,
$_session['date'],
$_session['from'],
$_session['from']
);
$txtBody.=sprintf(
"%s,%s,%s,%s,%s\n",
$i,
$_session['date'],
$_session['from'],
$_session['to']
);
}
$htmlBody.="</table>";
}
if (count($sessions['diverted'])) {
// diverted sessions
$textBody .= sprintf("Diverted Calls\n\n
Id,Date,From,Diverted to\n
");
$htmlBody .= sprintf("<h2>Diverted Calls</h2>
<p>
<table border=0>
<tr>
<th>
</th>
<th>Date and Time
</th>
<th>Caller
</th>
<th>Diverted to
</th>
</tr>
");
$i=0;
foreach ($sessions['diverted'] as $_session) {
$i++;
if ($i >= $count) break;
$htmlBody.=sprintf(
"
<tr>
<td>%s</td>
<td>%s</td>
<td><a href=sip:%s>sip:%s</a></td>
<td>%s</td>
</tr>
",
$i,
$_session['date'],
$_session['from'],
$_session['from'],
$_session['canonical']
);
$txtBody .= sprintf(
"%s,%s,%s,%s\n",
$i,
$_session['date'],
$_session['from'],
$_session['canonical']
);
}
$htmlBody.="</table>";
}
if (count($sessions['received'])) {
// received sessions
$textBody .= sprintf("Received Calls\n\nId,Date,From,Duration\n");
$htmlBody .= sprintf(
"<h2>Received Calls</h2>
<p>
<table border=0>
<tr>
<th></th>
<th>Date and Time</th>
<th>Caller</th>
<th>Duration</th>
</tr>"
);
$i=1;
foreach ($sessions['received'] as $_session) {
if ($i >= $count) {
break;
}
$htmlBody .= sprintf(
"<tr><td>%s</td><td>%s</td><td><a href=sip:%s>sip:%s</a></td><td>%s</td></tr>",
$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.="</table>";
}
$htmlBody.="<p>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'];
} elseif ($this->CDRS->trustedPeers[$_billing_party_els[1]]['reseller']) {
$this->ResellerId = $this->CDRS->trustedPeers[$_billing_party_els[1]]['reseller'];
}
} elseif (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];
} elseif (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;
} elseif ($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';
}
} elseif ($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_sql($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 = "
<div class=\"alert alert-info\" style='color: black'>
<div class='row-fluid'>
<div class='span4'>
<h5>SIP Signalling</h5>
";
$this->cdr_details .= sprintf(
"<a href=%s&call_id=%s><font color=orange>Click here to show only this call id</font></a>",
$this->CDRS->url_run,
urlencode($this->callId)
);
if ($this->CDRS->sipTrace) {
$trace_query = array(
'cdr_source' => $this->CDRS->sipTrace,
'callid' => quoted_printable_decode($this->callId),
'fromtag' => quoted_printable_decode($this->SipFromTag),
'totag' => quoted_printable_decode($this->SipToTag),
'proxyIP' => $this->SipProxyServer
);
$this->traceLink = sprintf(
"<a href=\"javascript:void(null);\" onClick=\"return window.open('sip_trace.phtml?%s', '_blank','toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=1300px,height=600')\">
<font color=red>Click here for the SIP trace</font></a> &nbsp;",
http_build_query($trace_query)
);
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Call id:</div>
<div class=\"span9\">$this->callId </div>
</div>
";
}
$this->cdr_details .= sprintf(
"
<div class=\"row-fluid\">
<div class=\"span12\">%s</div>
</div>
",
$this->traceLink
);
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">From tag: </div>
<div class=\"span9\">$this->SipFromTag</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">To tag: </div>
<div class=\"span9\">$this->SipToTag</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">Start Time:</div>
<div class=\"span9\">$this->startTime $providerTimezone</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">Stop Time:</div>
<div class=\"span9\">$this->stopTime</div>
</div>
";
$this->cdr_details .= sprintf(
"
<div class=\"row-fluid\">
<div class=\"span3\">Country:</div>
<div class=\"span9\">%s</div>
</div>
",
$this->geo_location
);
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Method:</div>
<div class=\"span9\">$this->SipMethod from <i>$this->SourceIP:$this->SourcePort</i></div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">From:</div>
<div class=\"span9\">$this->aNumberPrint</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">From Header:</div>
<div class=\"span9\">$this->FromHeaderPrint</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">User Agent:</div>
<div class=\"span9\">$this->UserAgentPrint</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">Domain:</div>
<div class=\"span9\">$this->domain</div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">To (dialed URI):</div>
<div class=\"span9\">$this->cNumberPrint</div>
</div>
";
if ($this->CanonicalURI) {
$this->cdr_details .= sprintf(
"
<div class=\"row-fluid\">
<div class=\"span3\">Canonical URI: </div>
<div class=\"span9\">%s</div>
</div>
",
htmlentities($this->CanonicalURI)
);
}
$this->cdr_details .= sprintf(
"
<div class=\"row-fluid\">
<div class=\"span3\">Next Hop URI:</div>
<div class=\"span9\">%s</div>
</div>
",
htmlentities($this->RemoteAddress)
);
if ($this->DestinationId) {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Destination: </div>
<div class=\"span9\">$this->destinationName ($this->DestinationId)</div>
</div>
";
}
if ($this->ENUMtld && $this->ENUMtld != 'none' && $this->ENUMtld != 'N/A') {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">ENUM TLD: </div>
<div class=\"span9\">$this->ENUMtld</div>
</div>
";
}
if ($this->SipRPID) {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Caller ID: </div>
<div class=\"span9\">$this->SipRPIDPrint</div>
</div>
";
}
if ($this->CalleeCallerId) {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Called ID: </div>
<div class=\"span9\">$this->CalleeCallerId</div>
</div>
";
}
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span3\">Billing Party:</div>
<div class=\"span9\"><font color=brown>$this->BillingPartyIdPrint</font></div>
</div>
<div class=\"row-fluid\">
<div class=\"span3\">Reseller:</div>
<div class=\"span9\"><font color=brown>$this->ResellerId</font></div>
</div>
</div>
";
$this->cdr_details .= "<div class='span3'>";
if ($this->application != 'message') {
$this->cdr_details .= "<h5>Media Streams</h5>";
if ($this->CDRS->mediaTrace) {
$media_query = array(
'cdr_source' => $this->CDRS->mediaTrace,
'callid' => quoted_printable_decode($this->callId),
'fromtag' => quoted_printable_decode($this->SipFromTag),
'totag' => quoted_printable_decode($this->SipToTag),
'proxyIP' => $this->SipProxyServer
);
$this->mediaTraceLink = sprintf(
"<a href=\"javascript:void(null);\" onClick=\"return window.open('media_trace.phtml?%s', '_blank',
'toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=800,height=730')\">Click here for media information</a> &nbsp;",
http_build_query($media_query)
);
$this->cdr_details .= sprintf(
"
<div class=\"row-fluid\">
<div class='span12'>%s</div>
</div>
",
$this->mediaTraceLink
);
}
$sessionId = rtrim(base64_encode(hash('md5', $this->callId, true)), "=");
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span5\">Session ID: </div>
<div class=\"span7\">$sessionId</div>
</div>
";
$this->SipCodec = quoted_printable_decode($this->SipCodec);
if ($this->SipCodec) {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span5\">Codecs: </div>
<div class=\"span7\">$this->SipCodec</div>
</div>
";
}
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span5\">Caller RTP: </div>
<div class=\"span7\">$this->inputTrafficPrint KB</div>
</div>
<div class=\"row-fluid\">
<div class=\"span5\">Called RTP: </div>
<div class=\"span7\">$this->outputTrafficPrint KB</div>
</div>
";
if ($this->MediaInfo) {
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span5\">Media Info:</div>
<div class=\"span7\"><font color=red>$this->MediaInfo</font></div>
</div>
";
}
$this->cdr_details .= "
<div class=\"row-fluid\">
<div class=\"span5\">Applications: </div>
<div class=\"span7\">$this->application_print</div>
</div>
";
}
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.= "
<div class=\"row-fluid\">
<div class=\"span5\">Caller SIP UA: </div>
<div class=\"span7\">$callerUA</div>
</div>
<div class=\"row-fluid\">
<div class=\"span5\">Called SIP UA: </div>
<div class=\"span7\">$calledUA</div>
</div>
";
}
$this->cdr_details.= "
</div>";
if ($perm->have_perm("showPrice") && $this->normalized) {
$this->cdr_details.= "
<div class=\"span3\">
<h5>Rating</h5>
";
if ($this->price > 0 || $this->rate) {
$this->ratePrint=nl2br($this->rate);
$this->cdr_details.= "
<div class=\"row-fluid\">
$this->ratePrint
</div>
";
} else {
$this->cdr_details.= "
<div class=\"row-fluid\">
Free call
</div>
";
}
$this->cdr_details.= "
</div>
";
}
$this->cdr_details.= "
</div>
</div>
";
}
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 =
"<a href=callsearch.phtml".
"?cdr_source=$datasource".
"&cdr_table=$cdr_table".
"&trace=1".
"&action=search".
"&c_number=$c_number".
"&c_number_comp=begins".
"&begin_datetime=$tmin".
"&end_datetime=$tplus".
" target=bottom>".
"In".
"</a>";
}
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=
"<a href=callsearch.phtml".
"?cdr_source=$datasource".
"&cdr_table=$cdr_table".
"&trace=1".
"&action=search".
"&c_number=$c_number".
"&c_number_comp=contain".
"&begin_datetime=$tmin".
"&end_datetime=$tplus".
" target=bottom>".
"Out".
"</a>";
}
function 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 "
<tr rel=tooltip data-placement='bottom' data-original-title='For more information about this call click the row.'>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><a href=#>$found_print</a></td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->startTime</nobr></td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->application $this->flow</nobr></td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->aNumberPrint</td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->geo_location</td>
<td valign=top onClick=\"return toggleVisibility('row$found')\">$this->SipProxyServer</td>
<td valign=top onClick=\"return toggleVisibility('row$found')\">$this->MediaRelay</td>
<td valign=top><nobr>$this->destinationPrint</nobr>
";
if ($this->DestinationId) {
if ($this->DestinationId != $this->CanonicalURI) {
print " ($this->destinationName $this->DestinationId)";
} else {
print " ($this->destinationName)";
}
}
print "</td>";
if (!$this->normalized) {
if ($this->duration > 0) {
print "<td valign=top align=left colspan=4><font color=red>$this->duration(s)</a></td>";
} else {
print "<td valign=top align=left colspan=4><font color=red>in progress</a></td>";
}
} else {
print "
<td valign=top align=right>$this->durationPrint</td>
<td valign=top align=right>$this->pricePrint</td>
<td valign=top align=right>$this->inputTrafficPrint </td>
<td valign=top align=right>$this->outputTrafficPrint</td>
";
}
$SIPclass=substr($this->disconnect, 0, 1);
if ($SIPclass=="6") {
$status_color="<span class=\"pull-right label label-important\">";
} elseif ($SIPclass == "5") {
$status_color="<span class=\"pull-right label label-important\">";
} elseif ($SIPclass == "4") {
$status_color="<span class=\"pull-right label label-info\">";
} elseif ($SIPclass == "3") {
$status_color="<span class=\"pull-right label label-success\">";
} elseif ($SIPclass == "2") {
$status_color="<span class=\"pull-right label label-success\">";
} else {
$status_color="<span class=\"pull-right label\">";
}
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="<span class=\"pull-right label label-important\">";
} elseif ($disclass == "4") {
$status1_color="<span class=\"pull-right label label-info\">";
} elseif ($disclass == "3") {
$status1_color="<span class=\"pull-right label label-success\">";
} elseif ($disclass == "2") {
$status1_color="<span class=\"pull-right label label-success\">";
} else {
$status1_color="<span class=\"pull-right label\">";
}
}
print "
<td valign=top align=right>$status_color $this->disconnectPrint</span>";
if ($this->disconnectOrig != $this->disconnect
&& $this->CDRS->rating_settings['rate_on_net_diverted_calls']) {
print "$status1_color $this->disconnectOrigPrint</span>";
}
print "</td>
</tr>
<tr class=extrainfo id='row$found'>
<td></td>
<td colspan=13>$this->cdr_details</td>
</tr>
";
}
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 ",$this->MediaRelay";
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 "
<tr rel=tooltip data-placement='bottom' data-original-title='For more information about this call click the row.'>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><a href=#>$found_print</a></td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->startTime $timezone_print</nobr></td>
<td valign=top><nobr>$this->aNumberPrint</nobr></td>
<td valign=top onClick=\"return toggleVisibility('row$found')\"><nobr>$this->geo_location</td>
<td valign=top onClick=\"return toggleVisibility('row$found')\">$this->SipProxyServer</td>
<td valign=top><nobr>$this->destinationPrint $this->destinationName</td>
<td valign=top align=right>$this->durationPrint</td>
";
if ($this->CDRS->rating) {
print "<td valign=top align=right>$this->pricePrint</td>";
}
print "
<td valign=top align=right>$this->inputTrafficPrint </td>
<td valign=top align=right>$this->outputTrafficPrint</td>
</tr>
";
print "
<tr class=extrainfo id='row$found'>
<td></td>
<td colspan=11>$this->cdr_details</td>
</tr>
";
} 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
-{
- public $CDR_class = "CDR_opensips_mongo";
- public $mongo_db_ro = null;
- public $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("<p>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("<p>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("<p>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']);
- } elseif ($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));
- } elseif (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));
- } elseif (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));
- } elseif (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;
- } elseif ($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 ($media_relay) {
- $media_relay=urldecode($media_relay);
- $mongo_where[$this->MediaRelayField] = $media_relay;
- $this->url.=sprintf("&media_relay=%s", urlencode($media_relay));
- }
-
- 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"];
- } elseif ($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)";
- } elseif (preg_match("/^DAY/", $group_by)) {
- $group_by = "$group_by(AcctStartTime)";
- } elseif (preg_match("/BYMONTH/", $group_by)) {
- $group_by = "DATE_FORMAT(AcctStartTime,'%Y-%m')";
- } elseif (preg_match("/BYYEAR/", $group_by)) {
- $group_by = "DATE_FORMAT(AcctStartTime,'%Y')";
- } elseif ($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("<p>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("<p>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 "<div class=\"alert alert-info\">";
- printf("<b><span class=\"alert-heading\">%d</span></b> CDRs normalized. ", $this->status['normalized']);
- if ($this->status['cached_keys']['saved_keys']) {
- printf("Quota usage updated for <b><span class=\"alert-heading\">%d</span></b> accounts. ", $this->status['cached_keys']['saved_keys']);
- }
- print "</div>";
- }
- }
- }
- }
-
- 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("<p>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";
- }
- } elseif ($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);
- } elseif ($this->group_byOrig == $this->CanonicalURIField) {
- $traceField = "c_number";
- $traceValue = urlencode($mygroup);
- } elseif ($this->group_byOrig == $this->SipProxyServerField) {
- $traceField="sip_proxy";
- $traceValue=urlencode($mygroup);
- } elseif ($this->group_byOrig == $this->MediaRelayField) {
- $traceField="media_relay";
- $traceValue=urlencode($mygroup);
- } elseif ($this->group_byOrig == $this->SipCodecField) {
- $traceField="SipCodec";
- } elseif (preg_match("/UserAgent/", $this->group_byOrig)) {
- $traceField="UserAgent";
- } elseif (preg_match("/^BY/", $this->group_byOrig)) {
- $traceField="MONTHYEAR";
- } elseif ($this->group_byOrig == $this->callIdField) {
- $traceField="call_id";
- } elseif ($this->group_byOrig == "SourceIP") {
- $traceField = "gateway";
- } elseif ($this->group_byOrig == "SipResponseCode") {
- $description = $this->disconnectCodesDescription[$mygroup];
- $traceField="sip_status";
- } elseif ($this->group_byOrig == "SipApplicationType") {
- $traceField="application";
- } elseif ($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 "
- <tr>
- <td><b>$found</b></td>
- <td align=right>$calls</td>
- <td align=right>$seconds_print</td>
- <td align=right>$minutes_print</td>
- <td align=right>$hours</td>
- ";
- if ($perm->have_perm("showPrice")) {
- $pricePrint=number_format($price, 4, ".", "");
- } else {
- $pricePrint='x.xxx';
- }
- print "
- <td align=right>$pricePrint</td>
- <td align=right>$AcctInputOctets</td>
- <td align=right>$AcctOutputOctets</td>
- <td align=right>$success%</td>
- <td align=right>($nonzero calls)</td>
- <td align=right>$failure%</td>
- <td align=right>($zero calls)</td>
- <td>$mygroup_print</td>
- <td>$description</td>
- <td>";
- printf("<a href=%s&%s=%s&%s_comp=%s target=_new>Display calls</a></td>", $url_calls, $traceField, $traceValue_enc, $traceField, $comp_type);
- print "
- </tr>
- ";
- } 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 "
- </table>
- ";
- }
- } else {
- if (!$this->export) {
- // printf ("<div class='alert alert-info'><i style='font-size:13px' class='icon-info-sign'></i> For more information about each call click on its Id column.</div>");
- }
-
- if ($order_by=="zeroP" || $order_by=="nonzeroP") {
- $order_by="timestamp";
- }
-
- if ($mongo_table_ro) {
- $cursor = $mongo_table_ro->find($mongo_where)->sort(array($mongo_order_by=>$mongo_order_type))->skip($i)->limit($this->maxrowsperpage)->slaveOkay();
- } else {
- $cursor = array();
- }
-
- if ($this->CDRTool['filter']['aNumber']) {
- $this->showTableHeaderSubscriber();
- } else {
- if (!$this->export) {
- $this->showTableHeader();
- } else {
- $this->showExportHeader();
- }
- }
-
- foreach ($cursor as $result) {
- global $found;
- $found=$i+1;
-
- $Structure=$this->_readCDRFieldsFromDB($result);
- $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 "</table>";
- }
- }
- $this->showPagination($this->next, $maxrows);
- }
- }
-}
-
-class CDR_opensips_mongo extends CDR_opensips {
-}
-
class SIP_trace
{
public $enableThor = false;
public $trace_array = array();
public $traced_ip = array();
public $SIPProxies = array();
public $mediaTrace = false;
public $thor_nodes = array();
public $hostnames = array();
public function SIP_trace($cdr_source)
{
global $DATASOURCES, $auth;
$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 (strlen($DATASOURCES[$this->cdr_source]['mediaTrace'])) {
$this->mediaTrace = $DATASOURCES[$this->cdr_source]['mediaTrace'];
}
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);
if (is_array($soapEngines[$this->soapEngineId]['hostnames'])) {
$this->hostnames=$soapEngines[$this->soapEngineId]['hostnames'];
}
} else {
printf("<p><font color=red>Error: soapEngineID not defined in datasource %s</font>", $this->cdr_source);
return false;
}
} else {
$this->table = $DATASOURCES[$this->cdr_source]['table'];
$db_class = $DATASOURCES[$this->cdr_source]['db_class'];
$this->purgeRecordsAfter = $DATASOURCES[$this->cdr_source]['purgeRecordsAfter'];
if (class_exists($db_class)) {
$this->db = new $db_class;
} else {
printf("<p><font color=red>Error: database class '%s' is not defined</font>", $db_class);
return false;
}
}
if (is_object($auth)) {
$this->isAuthorized=1;
}
if (is_array($DATASOURCES[$this->cdr_source]['SIPProxies'])) {
$this->SIPProxies = $DATASOURCES[$this->cdr_source]['SIPProxies'];
}
}
private function isProxy($ip, $sip_proxy = '')
{
if (!$ip) {
return false;
}
if (!$this->enableThor) {
if (!is_array($this->SIPProxies)) {
return false;
}
if (in_array($ip, array_keys($this->SIPProxies))) {
return true;
}
} elseif ($sip_proxy) {
if (isset($this->thor_nodes[$ip])) {
return true;
} else {
if (isThorNode($ip, $sip_proxy)) {
$this->thor_nodes[$ip]=1;
return true;
} else {
return false;
}
}
}
return false;
}
private function getTrace($proxyIP, $callid, $fromtag, $totag)
{
if ($this->enableThor) {
// get trace using soap request
if (!$proxyIP || !$callid || !$fromtag) {
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->getSipTrace($filter);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
printf(
"
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<div class='alert alert-danger'><h4>Error from %s</h4><br/>%s (%s)</div>
</div>
</div>
",
$this->SOAPurl,
$error_fault->detail->exception->errorstring,
$error_fault->detail->exception->errorcode
);
return false;
}
$columns = 0;
$traces = json_decode($result);
$trace_array = array();
foreach ($traces as $_trace) {
if (preg_match("/^(udp|tcp|tls):(.*):(.*)$/", $_trace->to_ip, $m)) {
$toip = $m[2];
$transport = $m[1];
$toport = $m[3];
} elseif (preg_match("/^(.*):(.*)$/", $_trace->to_ip, $m)) {
$toip = $m[1];
$transport = 'udp';
$toport = $m[2];
} else {
$toip = $_trace->to_ip;
$transport = $_trace->to_proto;
$toport = $_trace->to_port;
}
if (preg_match("/^(udp|tcp|tls):(.*):(.*)$/", $_trace->from_ip, $m)) {
$fromip = $m[2];
$fromport = $m[3];
} elseif (preg_match("/^(.*):(.*)$/", $_trace->from_ip, $m)) {
$fromip = $m[1];
$fromport = $m[2];
} else {
$fromip = $_trace->from_ip;
$fromport = $_trace->from_port;
}
if (!isset($this->column[$fromip])) {
$this->column[$fromip] = $columns + 1;
$this->column_port[$fromip] = $fromport;
$columns++;
}
if (!isset($this->column[$toip])) {
$this->column[$toip] = $columns+1;
$this->column_port[$toip] = $toport;
$columns++;
}
preg_match("/^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$/", $_trace->time_stamp, $m);
$timestamp = mktime($m[4], $m[5], $m[6], $m[2], $m[3], $m[1]);
$idx=$proxyIP.'_'.$_trace->id;
$trace_array[$idx] = array (
'id' => $idx,
'direction' => $_trace->direction,
'fromip' => $fromip,
'toip' => $toip,
'fromport' => $fromport,
'toport' => $toport,
'method' => $_trace->method,
'transport' => $transport,
'date' => $_trace->time_stamp,
'status' => $_trace->status,
'timestamp' => $timestamp,
'msg' => $_trace->message,
'md5' => md5($_trace->message)
);
}
$this->trace_array=$trace_array;
$this->rows = count($this->trace_array);
} else {
// get trace from SQL
if (!is_object($this->db)) {
print "<p><font color=red>Error: no database connection defined</font>";
return false;
}
$query = sprintf(
"
select
*,
UNIX_TIMESTAMP(time_stamp) as timestamp
from
%s
where
callid = '%s'
order by id asc
",
addslashes($this->table),
addslashes($callid)
);
if (!$this->db->query($query)) {
printf("Database error for query %s: %s (%s)", $query, $this->db->Error, $this->db->Errno);
return false;
}
$this->rows = $this->db->num_rows();
$columns = 0;
while ($this->db->next_record()) {
if (preg_match("/^(udp|tcp|tls):(.*):(.*)$/", $this->db->f('toip'), $m)) {
$toip = $m[2];
$transport = $m[1];
$toport = $m[3];
} elseif (preg_match("/^(.*):(.*)$/", $this->db->f('toip'), $m)) {
$toip = $m[1];
$transport = 'udp';
$toport = $m[2];
} else {
$toip = $this->db->f('toip');
$toport = '5060';
}
if (preg_match("/^(udp|tcp|tls):(.*):(.*)$/", $this->db->f('fromip'), $m)) {
$fromip = $m[2];
$fromport = $m[3];
} elseif (preg_match("/^(.*):(.*)$/", $this->db->f('fromip'), $m)) {
$fromip = $m[1];
$fromport = $m[2];
} else {
$fromip = $this->db->f('fromip');
$transport = 'udp';
$fromport = '5060';
}
if (!$this->column[$fromip]) {
$this->column[$fromip]=$columns+1;
$this->column_port[$fromip]=$fromport;
$columns++;
}
if (!$this->column[$toip]) {
$this->column[$toip] = $columns + 1;
$this->column_port[$toip]=$toport;
$columns++;
}
$this->trace_array[$this->db->f('id')] =
array (
'id' => $this->db->f('id'),
'direction' => $this->db->f('direction'),
'fromip' => $fromip,
'toip' => $toip,
'method' => $this->db->f('method'),
'fromport' => $fromport,
'toport' => $toport,
'transport' => $transport,
'date' => $this->db->f('time_stamp'),
'status' => $this->db->f('status'),
'timestamp' => $this->db->f('timestamp'),
'msg' => $this->db->f('msg'),
'md5' => md5($this->db->f('msg'))
);
}
}
}
private function printLabelProtocolPort($transport, $port)
{
echo '<span class="label">';
if ($transport == 'tls') {
echo "<span><i class='icon-lock'></i></span>&nbsp;";
}
printf('%s: %d', strtoupper($transport), $port);
echo '</span>';
}
public function show($proxyIP, $callid, $fromtag, $totag)
{
$action = $_REQUEST['action'];
$toggleVisibility = $_REQUEST['toggleVisibility'];
if ($action == 'toggleVisibility') {
$this->togglePublicVisibility($callid, $fromtag, $toggleVisibility);
}
if ($_SERVER['HTTPS'] == "on") {
$protocolURL = "https://";
} else {
$protocolURL = "http://";
}
$this->getTrace($proxyIP, $callid, $fromtag, $totag);
/* No trace can be found */
if (!count($this->trace_array)) {
echo "
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<p class='alert'>SIP trace for session id <strong>$callid</strong> is not available.</p>
</div>
</div>
";
return;
}
echo "
<div class=container-fluid>
<div id=trace class=main>
<h1 class='page-header'>CDRTool SIP trace<br /><small>Call ID: $callid $authorize</small></h1>
<div class=row-fluid>
<div class=span9>
";
$basicURL = $protocolURL.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$fullURL = $basicURL;
print "URLs for this trace: <a href=$fullURL>HTML</a> | <a href=$fullURL&format=text>TEXT</a></td>";
if ($this->mediaTrace) {
$media_query = array(
'cdr_source' => $this->mediaTrace,
'callid' => $callid,
'fromtag' => $fromtag,
'totag' => $totag,
'proxyIP' => $proxyIP
);
$this->mediaTraceLink = sprintf(
"<p class=pull-right>
<a href=\"javascript:void(null);\" onClick=\"return window.open('media_trace.phtml?%s', 'mediatrace','toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=800,height=730')\">
Click here for RTP media information
</a>
</p>",
http_build_query($media_query)
);
}
print "
</div>
<div class='span3'>
<p class='pull-right'>Click on each packet to expand its body content</p>
$this->mediaTraceLink
</div>
</div>
";
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 "
<table class='table siptrace'>
<thead>
<tr>
<th>Packet</th>
<th>Time</th>
";
$_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 "<th style='text-align: center' colspan=\"2\">";
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(
"<a href=\"javascript:void(null);\" onClick=\"return window.open('sip_trace.phtml?%s', '_self',
'toolbar=0,status=1,menubar=1,scrollbars=1,resizable=1,width=1000,height=600')\">%s:%s</a>",
http_build_query($trace_query),
$_hostname,
$this->column_port[$_key]
);
printf("%s", $trace_link);
} else {
printf("%s", $_hostname);
}
print "</th>";
}
print "</tr>
</thead>";
/* 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 = "<div id=\"packet$i\"><span>$_els[0]</span>";
if ($status) {
$cell_content .= " <font color=black>for ".$status_for_method."</font>";
}
if (is_array($diversions)) {
foreach ($diversions as $_diversion) {
$cell_content.="<br><em class='gray'>$_diversion</em>";
}
}
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.="<br><em class='gray'>$_stream</em>";
} else {
$cell_content.="<br><em style='text-decoration: line-through'>$_stream</em>";
}
}
}
$cell_content.="
</div>
";
print "
<tr onClick=\"return toggleVisibility('row$i')\">
";
$packet_length = strlen($msg);
print "
<td><span>$i/$this->rows&nbsp;</span></td>
<td><span><nobr>$date</nobr></span>";
if ($timeline && !isset($_seen_timeline[$timeline])) {
printf("&nbsp;&nbsp;<span class='badge badge-info'>+%ds</span>", $timeline);
$_seen_timeline[$timeline] = 1;
}
print "<br /><nobr>$packet_length bytes</nobr></td>
";
$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 "<td style='text-align: right' class='span2'>";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo "</td>";
}
$arrowColor = $status_color;
if ($arrow_direction == 'loop') {
print "<td><i style='font-size: 2.4em' class=\"icon-refresh pull-right\"></i></td>";
}
if ($arrow_possition >= 2 * $msg_possition) {
$arrow_span = ($arrow_possition * 2) - 4;
echo "<td colspan='$arrow_span' style='border-left: 2px solid #95b3d0; border-right: 2px solid #95b3d0; width:66%'>";
} else {
echo "<td colspan='2' style='border-left: 2px solid #95b3d0; border-right: 2px solid #95b3d0; width:33%'>";
}
if ($arrow_direction != 'loop') {
print "<div class='sarrow $arrowColor $arrow_direction'></div>";
}
if ($arrow_direction == "left") {
print "<div style='text-align: right; padding-right:16px;'>$cell_content</div>";
} else {
print "<div style='float:left; padding-left:16px;'>$cell_content</div>";
}
echo "</td>";
if ($column_current < count($this->column) && $column_current > $msg_possition) {
print "<td class='span2'>";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo "</td>";
}
} else {
if ($msg_possition == $column_current) {
if ($msg_possition < $arrow_possition) {
print "<td style='width: 17%;text-align: right'>";
if ($direction == 'out') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
} else {
print "<td style='width: 17%'>";
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 "<td style='width: 17%; border-right: 2px solid #95b3d0'>";
print "</td><td>";
print "&nbsp;";
} elseif ($arrow_possition == $msg_possition) {
echo "<td></td>";
}
echo "</td>";
}
if ($arrow_possition == $column_current && $column_current == count($this->column)) {
echo "<td style='width:17%'>";
if ($direction == 'in') {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['fromport']);
} else {
$this->printLabelProtocolPort($transport, $this->trace_array[$key]['toport']);
}
echo "</td>";
}
$column_current++;
if ($arrow_direction == 'loop') {
$seen_msg[$md5]++;
}
}
echo "</tr>";
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 "
<tr class='extrainfo $status_color' id=row$i>
<td colspan=$trace_span>
<div class='row-fluid'>
<div class='span2' style='max-width: 120px; padding-left: 15px;'>
";
if ($direction == "out") {
print "<nobr><h1>SIP Proxy</h1></nobr>";
} else {
if ($sip_phone_img && $sip_phone_img!='unknown.png') {
print "<img style='max-width:none' src=images/$sip_phone_img>";
} else {
print "<i style=\"font-size:28px\" class=\"icon-question\"></i>";
}
}
print "<br />";
if ($timeline > 0) {
printf("<p>+%s s<br>(%s)</p>", $timeline, sec2hms($timeline));
}
print "</div><div class=span10 style='font-family: monospace; color: #333333;'>";
$msg = nl2br(htmlentities($msg));
print "<span>$msg</span>
</div>
</div>";
echo "
</td>
</tr>
";
}
print "
</table>
";
}
public function showText($proxyIP, $callid, $fromtag, $totag)
{
$this->getTrace($proxyIP, $callid, $fromtag, $totag);
print "<pre>";
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 "</pre>";
}
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("<p><font color=red>Error: database class %s is not defined in datasource %s</font>", $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 "
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<p class='alert alert-danger'><strong>Error</strong>: proxyIP or callid or fromtag are not defined</p>
</div>
</div>
";
return false;
}
if (!is_object($this->soapclient)) {
print "<p><font color=red>Error: soap client is not defined</font>";
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(
"
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<div class='alert alert-danger'><h4>Error from %s</h4><br/>%s (%s)</div>
</div>
</div>
",
$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 "<p><font color=red>Error: no database connection defined</font>";
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(
"<p><font color=red>Database error for query %s: %s (%s)</font>",
$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 "
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<div class='alert'>No information available</div>
</div>
</div>
";
return false;
}
if (!count($this->info->streams)) {
echo "
<div style='display: flex; align-items: center; justify-content: center;'>
<div class='span10' style='padding-top:40px;'>
<div class='alert alert-info'>No RTP media streams have been established</div>
</div>
</div>
";
return;
}
print "<div class='container-fluid'><div id=trace class='main'>";
$sessionId = rtrim(base64_encode(hash('md5', $callid, true)), "=");
print "<h1 class=page-header>CDRTool Media Trace<br/><small>Call ID: $callid</small><br /><small>Media Session ID: $sessionId</small></h1>";
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 "<h2>Media Information</h2>";
print "<table border=0>";
printf("<tr><td class=border>Call duration</td><td class=border>%s</td></tr>", $this->info->duration);
list($relay_ip, $relay_port)=explode(":", $this->info->streams[0]->caller_local);
printf("<tr><td class=border>Media relay</td><td class=border>%s</td></tr>", $relay_ip);
print "</table>";
print "<h2>Media Streams</h2>";
print "<table class='table table-condensed table-striped' style='width:600px' border=0>";
print "<thead><tr><th></th>";
foreach (array_values($media_types) as $_type) {
printf("<th>%s</th>", ucfirst($_type));
}
print "</tr></thead>";
foreach ($this->info->streams[0] as $_val => $_value) {
printf("<tr><td class=border>%s</td>", ucfirst(preg_replace("/_/", " ", $_val)));
$j=0;
while ($j < count($media_types)) {
printf("<td class=border>%s</td>", $this->info->streams[$j]->$_val);
$j++;
}
printf("</tr>\n");
}
print "</table>";
print "<br><h2>Stream Succession</h2>";
$w_legend_bar = 500;
$w_text = 30;
$stamps = array_keys($seen_stamp);
sort($stamps);
$w_table = $w_legend_bar + $w_text;
print "<table border=0 cellpadding=1 cellspacing=1 width=$w_table>";
$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<br>\n",$w_start_p,$w_duration_p,$w_timeout_p,$w_rest);
if ($_val->caller_packets != '0' && $_val->callee_packets != '0') {
print "<tr><td width=$w_text class=border>$_val->media_type</td>";
print "<td width=$w_legend_bar>\n";
//print "<table width=100% border=0 cellpadding=0 cellspacing=0><tr>\n";
print "<div class='progress progress-striped'>";
print "<div class=bar style='width:$w_start_p%'></div>\n";
print "<div class='bar bar-success' style='width:$w_duration_p% ; text-align:center'><font color=white>$duration_print</font></div>\n";
if ($_val->timeout_wait) {
print "<div class='bar bar-danger' style='width:$w_timeout%; text-align:center'><font color=white>$_timeout</font></div>\n";
} else {
print "<div class='bar bar-warning' style='width:$w_timeout%; text-align:center'></div>\n";
}
//print "<td width=$w_rest bgcolor=white align=center></td>\n";
//print "</table>\n";
print "</td></tr>";
} elseif ($_val->status == 'unselected ICE candidate') {
print "<tr><td>ICE session</td></tr>";
} else {
print "<tr><td>No stream data found</td></tr>";
}
}
print "</table>";
print "<br><strong>Legend</strong>";
print "<p><table border=0>
<tr><td width=50><div class='progress progress-striped progress-success'><div class='bar' style='width:100%'></div></div></td><td>Session data</td></tr>
<tr><td><div class='progress progress-striped progress-danger'><div class='bar' style='width:100%'></div></div></td><td>Timeout period</td></tr>
</table></p></div></div>
";
}
}
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;
}
}
?>
diff --git a/library/rating.php b/library/rating.php
index b2dd7fa..dca8414 100644
--- a/library/rating.php
+++ b/library/rating.php
@@ -1,10709 +1,9574 @@
<?php
/**
* Copyright (c) 2007-2020 AG Project
* https://ag-projects.com
*
* This library contains classes and functions for rating functionality
*/
class Rate
{
var $priceDenominator = 10000; // allow sub cents
var $priceDecimalDigits = 4; // web display
var $durationPeriodRated = 60; // how the prices are indicated in the billing_rates, default is per minute
var $trafficSizeRated = 1024; // in KBytes, default 1MByte
var $rate_longer_than = 0; // minimum duration considered to apply rates for a call, if call is shorter the price is zero
var $ENUMtld = '';
var $ENUMdiscount = 0; // how much percentage to substract from the final price
var $price = 0;
var $spans = 0; // number of spans we looped through
var $connectCost = 0;
var $increment = 0; // used to consider the duration of the call in increments (default 1 second)
var $min_duration = 0; // minimum duration considered for calculating the price
var $max_duration = 0; // maximum duration considered for calculating the price
var $max_price = 0; // maximum price for the call
var $discount_connect = 0;
var $discount_duration = 0;
var $rateValuesCache = array(); // used to speed up prepaid apoplication
var $broken_rate = false;
- var $mongo_db = null;
var $db = null;
var $database_backend = "mysql";
public function Rate($settings, $db)
{
$this->db = $db;
$this->settings = $settings;
if ($this->database_backend == "mysql") {
$this->db->Halt_On_Error="no";
}
if ($this->settings['priceDenominator']) {
$this->priceDenominator = $this->settings['priceDenominator'];
}
if ($this->settings['priceDecimalDigits']) {
$this->priceDecimalDigits = $this->settings['priceDecimalDigits'];
}
if ($this->settings['durationPeriodRated']) {
$this->durationPeriodRated = $this->settings['durationPeriodRated'];
}
if ($this->settings['trafficSizeRated']) {
$this->trafficSizeRated = $this->settings['trafficSizeRated'];
}
if ($this->settings['rate_longer_than']) {
// if call is shorter than this, it has zero cost
$this->rate_longer_than = $this->settings['rate_longer_than'];
}
if ($this->settings['min_duration']) {
// if call is shorter than this, it has zero cost
$this->min_duration = $this->settings['min_duration'];
}
if ($this->settings['increment']) {
$this->increment = $this->settings['increment'];
}
if ($this->settings['database_backend']) {
$this->database_backend = $this->settings['database_backend'];
}
- if ($this->database_backend == "mongo") {
- if (is_array($this->settings['mongo_db'])) {
- $mongo_uri = $this->settings['mongo_db']['uri'];
- $mongo_replicaSet = $this->settings['mongo_db']['replicaSet'];
- $mongo_database = $this->settings['mongo_db']['database'];
- try {
- $mongo_connection = new Mongo("mongodb://$mongo_uri?readPreference=secondaryPreferred", array("replicaSet" => $mongo_replicaSet));
- $this->mongo_db = $mongo_connection->selectDB($mongo_database);
- } catch (Exception $e) {
- $log = sprintf("Error: cannot connect to mongo database %s: %s", $mongo_uri, $e->getMessage());
- syslog(LOG_NOTICE, $log);
- $this->mongo_db = null;
- }
- }
- }
}
public function calculateAudio($dictionary)
{
// used for calculate rate for audio application
$this->RatingTables = $dictionary['RatingTables'];
$this->callId = $dictionary['callId'];
$this->timestamp = $dictionary['timestamp'];
$this->duration = $dictionary['duration'];
$this->traffic = 2 * ($dictionary['inputTraffic'] + $dictionary['outputTraffic']);
$this->DestinationId = $dictionary['DestinationId'];
$this->BillingPartyId = $dictionary['BillingPartyId'];
$this->domain = $dictionary['domain'];
$this->gateway = $dictionary['gateway'];
$this->ResellerId = $dictionary['ResellerId'];
$this->aNumber = $dictionary['aNumber'];
$this->cNumber = $dictionary['cNumber'];
$this->ENUMtld = $dictionary['ENUMtld'];
if ($this->rate_longer_than && $this->duration < $this->rate_longer_than) {
//syslog(LOG_NOTICE, "Duration less than minimum $this->rate_longer_than");
$this->rateInfo .= " Duration < $this->rate_longer_than s\n";
return true;
}
if ($this->ENUMtld && $this->ENUMtld != 'n/a' && $this->ENUMtld != 'none' && $this->RatingTables->ENUMtlds[$this->ENUMtld]) {
$this->ENUMdiscount = $this->RatingTables->ENUMtlds[$this->ENUMtld]['discount'];
if (!is_numeric($this->ENUMdiscount) || $this->ENUMdiscount < 0 || $this->ENUMdiscount > 100) {
syslog(LOG_NOTICE, "Error: ENUM discount for tld $this->ENUMtld must be between 0 and 100");
}
}
if (!$this->gateway) {
$this->gateway = "0.0.0.0";
}
if (!$this->duration) {
$this->duration = 0;
}
if (!$this->traffic) {
$this->traffic = 0;
}
$this->application=$dictionary['application'];
if (!$this->application) {
$this->application = 'audio';
}
$durationRate = 0;
$foundRates = array();
if (!$this->DestinationId) {
syslog(LOG_NOTICE, "Error: Cannot calculate rate without destination id for callid=$this->callId");
return false;
}
if (!$this->lookupDestinationDetails()) {
// get region, increment and other per destination details
syslog(LOG_NOTICE, "Error: Cannot find destination details for call_id=$this->callId, dest_id=$this->DestinationId)");
return false;
}
if (!$this->lookupProfiles()) {
// get profiles for the billing party
syslog(LOG_NOTICE, "Error: Cannot find any profiles for call_id=$this->callId, dest_id=$this->DestinationId)");
return false;
}
// lookup discounts if any
$this->lookupDiscounts();
$this->startTimeBilling = getLocalTime($this->billingTimezone, $this->timestamp);
list($dateText,$timeText) = explode(" ", trim($this->startTimeBilling));
$Bdate = explode("-", $dateText);
$Btime = explode(":", $timeText);
$this->timestampBilling = mktime($Btime[0], $Btime[1], $Btime[2], $Bdate[1], $Bdate[2], $Bdate[0]);
$this->startTimeBilling = Date("Y-m-d H:i:s", $this->timestampBilling);
$this->trafficKB = number_format($this->traffic/1024, 0, "", "");
// check min_duration and increment per destination
if ($this->increment >= 1) {
// increase the billed duration to the next increment
$this->duration = $this->increment * ceil($this->duration / $this->increment);
}
if ($this->max_duration && $this->duration > $this->max_duration) {
// limit the maximum duration for rating
$this->duration = $this->max_duration;
}
$this->rateSyslog = "";
if ($this->duration) {
if ($this->increment >= 1) {
$this->rateInfo .=
" Increment: $this->increment s\n";
$this->rateSyslog .= sprintf("Increment=%s ", $this->increment);
}
if ($this->min_duration) {
$this->rateInfo .=
" Min duration: $this->min_duration s\n";
$this->rateSyslog .= sprintf("MinDuration=%s ", $this->min_duration);
}
if ($this->max_duration) {
$this->rateInfo .=
" Max duration: $this->max_duration s\n";
$this->rateSyslog .= sprintf("MaxDuration=%s ", $this->max_duration);
}
if ($this->max_price) {
$this->rateInfo .=
" Max price: $this->max_price\n";
$this->rateSyslog .= sprintf("MaxPrice=%s ", $this->max_price);
}
unset($IntervalsForPricing);
$this->rateInfo .=
" Duration: $this->duration s\n".
" App: $this->application\n".
" Destination: $this->DestinationId\n".
" Customer: $this->CustomerProfile\n";
if ($this->region) {
$this->rateInfo .=
" Region: $this->region\n";
}
if ($this->discount_duration || $this->discount_connect) {
$this->rateInfo .=
" Discount: ";
}
if ($this->discount_connect) {
$this->rateInfo .= " connect $this->discount_connect% ";
}
if ($this->discount_duration) {
$this->rateInfo .= " duration $this->discount_duration% ";
}
if ($this->discount_duration || $this->discount_connect) {
$this->rateInfo .= "\n";
}
if ($this->ENUMtld && $this->ENUMtld != 'none' && $this->ENUMtld != 'n/a') {
$this->rateInfo .=
" ENUM tld: $this->ENUMtld\n".
" ENUM discount: $this->ENUMdiscount%\n";
}
$i=0;
$durationRatedTotal=0;
// get recursively a set of arrays with rates
// until we billed the whole duration
while ($durationRatedTotal < $this->duration) {
if ($i == "0") {
$dayofweek = date("w", $this->timestampBilling);
$hourofday = date("G", $this->timestampBilling);
$dayofyear = date("Y-m-d", $this->timestampBilling);
} else {
$dayofweek = date("w", $this->timestampBilling+$durationRatedTotal);
$hourofday = $foundRate['nextHourOfDay'];
$dayofyear = date("Y-m-d", $this->timestampBilling+$durationRatedTotal);
}
$foundRate = $this->lookupRateAudio($dayofyear, $dayofweek, $hourofday, $durationRatedTotal);
$durationRatedTotal = $durationRatedTotal + $foundRate['duration'];
if (!$foundRate['rate']) {
$this->broken_rate=true;
return false;
}
$foundRates[] = $foundRate;
$i++;
if ($i > 10) {
// possible loop because of wrong coding make sure we end this loop somehow
$body="Rating of call $this->callId (DestId=$this->DestinationId) has more than 10 spans. It could be a serious bug.\n";
mail($this->toEmail, "CDRTool rating problem", $body, $this->extraHeaders);
syslog(LOG_NOTICE, "Error: Rating of call $this->callId (DestId=$this->DestinationId) has more than 10 spans.");
break;
}
}
}
$j = 0;
$span = 0;
foreach ($foundRates as $thisRate) {
$spanPrice = 0;
$span++;
if ($j > 0) {
$payConnect = 0;
$durationForRating = $thisRate['duration'];
} else {
$payConnect=1;
if ($this->min_duration && $this->duration < $this->min_duration) {
$durationForRating = $this->min_duration;
} else {
$durationForRating = $thisRate['duration'];
}
}
$connectCost = $thisRate['values']['connectCost'];
$durationRate = $thisRate['values']['durationRate'];
// apply discounts for connect
if ($this->discount_connect) {
$connectCost = $connectCost - $connectCost * $this->discount_connect / 100;
}
// apply discounts for duration
if ($this->discount_duration) {
$durationRate = $durationRate - $durationRate * $this->discount_duration / 100;
}
$connectCostIn = $thisRate['values']['connectCostIn'];
$durationRateIn = $thisRate['values']['durationRateIn'];
if ($span=="1") {
$connectCostSpan = $connectCost;
$this->connectCost = number_format($connectCost/$this->priceDenominator, $this->priceDecimalDigits);
$connectCostSpanIn = $connectCostIn;
$this->connectCostIn = number_format($connectCostIn/$this->priceDenominator, $this->priceDecimalDigits);
} else {
$connectCostSpan=0;
$connectCostSpanIn=0;
}
$connectCostPrint = number_format($connectCostSpan/$this->priceDenominator, $this->priceDecimalDigits);
$durationRatePrint = number_format($durationRate/$this->priceDenominator, $this->priceDecimalDigits);
$connectCostPrintIn = number_format($connectCostSpanIn/$this->priceDenominator, $this->priceDecimalDigits);
$durationRatePrintIn = number_format($durationRateIn/$this->priceDenominator, $this->priceDecimalDigits);
if (!$connectCostSpan) $connectCostSpan=0;
if (!$durationRate) $durationRate=0;
if (!$connectCostSpanIn) $connectCostSpanIn=0;
if (!$durationRateIn) $durationRateIn=0;
if (!$this->inputTraffic) $this->inputTraffic=0;
if (!$this->outputTraffic) $this->outputTraffic=0;
if ($span>1) $this->rateInfo .= "--\n";
/*
durationRate*durationForRating/durationPeriodRated/priceDenominator+
trafficRate/priceDenominator/trafficSizeRated*(inputTraffic+outputTraffic)/8");
$durationRate*$durationForRating/$this->durationPeriodRated/$this->priceDenominator+
$trafficRate/$this->priceDenominator/$this->trafficSizeRated*($this->inputTraffic+$this->outputTraffic)/8");
*/
$spanPrice = $durationRate * $durationForRating / $this->durationPeriodRated / $this->priceDenominator;
$this->price = $this->price+$spanPrice;
$spanPricePrint = number_format($spanPrice, $this->priceDecimalDigits);
$spanPriceIn = $durationRateIn * $durationForRating / $this->durationPeriodRated / $this->priceDenominator;
$this->priceIn = $this->priceIn+$spanPriceIn;
$spanPricePrintIn = number_format($spanPriceIn, $this->priceDecimalDigits);
if ($span=="1" && $thisRate['profile']) {
if ($connectCostIn) {
$this->rateInfo .=
" Connect in: $connectCostPrintIn\n";
}
$this->rateInfo .=
" Connect: $connectCostPrint\n".
" StartTime: $this->startTimeBilling\n".
"--\n";
$this->rateSyslog .= "ConnectFee=$connectCostPrint ";
$this->price = $this->price + $connectCostSpan / $this->priceDenominator * $payConnect;
$this->priceIn = $this->priceIn + $connectCostSpanIn / $this->priceDenominator * $payConnect;
}
$this->rateInfo .=
" Span: $span\n".
" Duration: $durationForRating s\n";
$this->rateSyslog .= sprintf(
"CallId=%s Span=%s Duration=%s DestId=%s %s",
$this->callId,
$span,
$durationForRating,
$this->DestinationId,
$thisRate['customer']
);
if ($thisRate['profile']) {
$this->rateInfo .=
" ProfileId: $thisRate[profile] / $thisRate[day]\n".
" RateId: $thisRate[rate] / $thisRate[interval]h\n".
" Rate: $durationRatePrint / $this->durationPeriodRated s\n".
" Price: $spanPricePrint\n";
if ($spanPriceIn) {
$this->rateInfo .=
" Price in: $spanPricePrintIn\n";
}
$this->rateSyslog .= sprintf(
" Profile=%s Period=%s Rate=%s Interval=%s Cost=%s/%s",
$thisRate['profile'],
$thisRate['day'],
$thisRate['rate'],
$thisRate['interval'],
$durationRatePrint,
$this->durationPeriodRated
);
} else {
$this->rateInfo .=
" ProfileId: none\n".
" RateId: none\n";
$this->rateSyslog .= " Profile=none, Rate=none";
}
$this->rateSyslog .= " Price=".sprintf("%.4f", $spanPrice);
$this->rateSyslog .= " PriceIn=".sprintf("%.4f", $spanPriceIn);
if ($this->discount_connect) {
$this->rateSyslog .= sprintf(" DisCon=%s", $this->discount_connect);
}
if ($this->discount_duration) {
$this->rateSyslog .= sprintf(" DisDur=%s", $this->discount_duration);
}
syslog(LOG_NOTICE, $this->rateSyslog);
$j++;
}
if ($this->priceIn) {
$this->rateInfo .= "--\n".
" Price out: ".sprintf("%.4f", $this->price)."\n".
" Price in: ".sprintf("%.4f", $this->priceIn)."\n".
" Margin: ".sprintf("%.4f", $this->price-$this->priceIn)."\n";
}
$this->rateInfo=trim($this->rateInfo);
if ($this->max_price && $this->price > $this->max_price) {
$this->price = $this->max_price;
}
if ($this->ENUMdiscount) {
$this->priceBeforeDiscount = sprintf("%.4f", $this->price);
$this->price = $this->price - $this->price * $this->ENUMdiscount / 100;
$this->price = sprintf("%.4f", $this->price);
$this->rateInfo .=
"\n--\n".
" Total: $this->priceBeforeDiscount\n".
" Total after discount: $this->price\n";
}
$this->price = sprintf("%.4f", $this->price);
$this->pricePrint = number_format($this->price, $this->priceDecimalDigits);
return true;
}
public function calculateMessage($dictionary)
{
// used for calculate rate for SMS application
$this->RatingTables = $dictionary['RatingTables'];
$this->callId = $dictionary['callId'];
$this->timestamp = $dictionary['timestamp'];
$this->DestinationId = $dictionary['DestinationId'];
$this->BillingPartyId = $dictionary['BillingPartyId'];
$this->domain = $dictionary['domain'];
$this->gateway = $dictionary['gateway'];
$this->ResellerId = $dictionary['ResellerId'];
$this->aNumber = $dictionary['aNumber'];
$this->cNumber = $dictionary['cNumber'];
if (!$this->gateway) {
$this->gateway = "0.0.0.0";
}
$this->application = 'sms';
$foundRates=array();
if (!$this->DestinationId) {
syslog(LOG_NOTICE, "Error calculateMessage(): Cannot calculate rate without destination id");
return false;
}
if (!$this->lookupProfiles()) {
// get profiles for the billing party
syslog(LOG_NOTICE, "Error: calculateMessage() Cannot find any profiles for call_id=$this->callId, dest_id=$this->DestinationId)");
return false;
}
// lookup discounts if any
$this->lookupDiscounts();
$this->startTimeBilling = getLocalTime($this->billingTimezone, $this->timestamp);
list($dateText,$timeText) = explode(" ", trim($this->startTimeBilling));
$Bdate = explode("-", $dateText);
$Btime = explode(":", $timeText);
$this->timestampBilling = mktime($Btime[0], $Btime[1], $Btime[2], $Bdate[1], $Bdate[2], $Bdate[0]);
$dayofweek = date("w", $this->timestampBilling);
$hourofday = date("G", $this->timestampBilling);
$dayofyear = date("Y-m-d", $this->timestampBilling);
$this->rateInfo .=
" App: sms\n".
" Destination: $this->DestinationId\n".
" Customer: $this->CustomerProfile\n";
if ($this->region) {
$this->rateInfo .=
" Region: $this->region\n";
}
if ($this->discount_duration || $this->discount_connect) {
$this->rateInfo .=
" Discount: ";
}
if ($this->discount_connect) {
$this->rateInfo .= " connect $this->discount_connect% ";
}
if ($this->discount_duration || $this->discount_connect) {
$this->rateInfo .= "\n";
}
$foundRate = $this->lookupRateMessage($dayofyear, $dayofweek, $hourofday);
if (is_array($foundRate)) {
$this->price = number_format($foundRate['values']['connectCost'] / $this->priceDenominator, $this->priceDecimalDigits);
$this->price = sprintf("%.4f", $this->price);
$this->pricePrint = $this->price;
$this->rateInfo .=
" ProfileId: $foundRate[profile] / $foundRate[day]\n".
" RateId: $foundRate[rate]\n".
" Price: $this->price\n";
return true;
} else {
return false;
}
}
private function lookupDiscounts()
{
// get discounts for customer per region if set otherwise per destination id
if (!$this->CustomerProfile) {
return false;
}
if ($this->region) {
$_field = 'region';
$_value = $this->region;
} else {
$_field = 'destination';
$_value = $this->DestinationId;
}
- if ($this->mongo_db != null) {
- // mongo backend
- if ($this->CustomerProfile == 'default') {
- $mongo_where['subscriber'] = '';
- $mongo_where['domain'] = '';
- $mongo_where['domain'] = '';
- $mongo_where['domain'] = '';
- $mongo_where['application'] = $this->application;
- $mongo_where[$_field] = $_value;
- } else {
- $els = explode("=", $this->CustomerProfile);
- $mongo_where[$els[0]] = $els[1];
- $mongo_where['application'] = $this->application;
- $mongo_where[$_field] = $_value;
- }
-
- try {
- $table = $this->mongo_db->selectCollection('billing_discounts');
- $cursor = $table->find($mongo_where)->limit(1)->slaveOkay();
- $result = $cursor->getNext();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in lookupDiscounts(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if ($result) {
- if ($result['connect'] > 0 && $result['connect'] <=100) {
- $this->discount_connect = $result['connect'];
- }
-
- if ($result['duration'] > 0 && $result['duration'] <=100) {
- $this->discount_duration = $result['duration'];
- }
- return true;
- }
- }
-
if ($this->CustomerProfile == 'default') {
$query = sprintf(
"select * from billing_discounts
where subscriber = ''
and domain = ''
and gateway = ''
and application = '%s'
and %s = '%s'
",
addslashes($this->application),
addslashes($_field),
addslashes($_value)
);
} else {
$els = explode("=", $this->CustomerProfile);
$query = sprintf(
"select * from billing_discounts
where %s = '%s'
and application = '%s'
and %s = '%s'
",
addslashes($els[0]),
addslashes($els[1]),
addslashes($this->application),
addslashes($_field),
addslashes($_value)
);
}
// mysql backend
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$this->db->next_record();
if ($this->db->f('connect') > 0 && $this->db->f('connect') <=100) {
$this->discount_connect = $this->db->f('connect');
}
if ($this->db->f('duration') > 0 && $this->db->f('duration') <=100) {
$this->discount_duration = $this->db->f('duration');
}
}
return true;
}
private function lookupDestinationDetails()
{
// get rating related details for the destination id
if (!$this->DestinationId) {
syslog(LOG_NOTICE, "Error: Cannot lookup destination details without a destination id");
return false;
}
- if ($this->mongo_db != null) {
- // mongo backend
- $mongo_where['dest_id'] = $this->DestinationId;
- $mongo_where['$or'] = array(
- array(
- 'reseller_id' => intval($this->ResellerId)
- ),
- array('reseller_id' => 0)
- );
-
- try {
- $table = $this->mongo_db->selectCollection('destinations');
- $cursor = $table->find($mongo_where)->sort(array('reseller_id'=>-1))->limit(1)->slaveOkay();
- $result = $cursor->getNext();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in lookupProfiles(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if (!$result) {
- $log = sprintf("Error: cannot find mongo destination details for dest id %s", $this->DestinationId);
- syslog(LOG_NOTICE, $log);
- //return false;
- }
-
- if ($result) {
- $this->region = $result['region'];
- $this->max_duration = $result['max_duration'];
- $this->max_price = $result['max_price'];
-
- if ($result['increment']) {
- $this->increment = $result['increment'];
- }
-
- if ($result['min_duration']) {
- $this->min_duration = $result['min_duration'];
- }
- return true;
- }
- }
-
// mysql backend
$query = sprintf(
"select * from destinations
where dest_id = '%s'
and (reseller_id = %d or reseller_id = 0) order by reseller_id desc limit 1
",
addslashes($this->DestinationId),
addslashes($this->ResellerId)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$this->db->next_record();
$this->region = $this->db->Record['region'];
$this->max_duration = $this->db->Record['max_duration'];
$this->max_price = $this->db->Record['max_price'];
if ($this->db->Record['increment']) {
$this->increment = $this->db->Record['increment'];
}
if ($this->db->Record['min_duration']) {
$this->min_duration = $this->db->Record['min_duration'];
}
}
return true;
}
private function lookupProfiles()
{
unset($this->allProfiles);
/*
lookup the profile_name in billing_customers in the following order:
subscriber, domain, gateway (based on $dayofweek):
- profile_workday matches days [1-5] (Work-day)
- profile_weekend matches days [6-0] (Week-end)
- week starts with 0 Sunday and ends with 6 Saturday
Alternatively look for profile_workday_alt and profile_weekend_alt
If no rates are found for destination in the profileX,
than lookup rates in profileX_alt
*/
- if ($this->mongo_db != null) {
- // mongo backend
-
- $mongo_where['$or'] = array(
- array('subscriber' => $this->BillingPartyId),
- array('domain' => $this->domain),
- array('gateway' => $this->gateway),
- array(
- 'gateway' => '',
- 'domain' => '',
- 'subscriber' => ''
- )
- );
-
- try {
- $table = $this->mongo_db->selectCollection('billing_customers');
- $cursor = $table->find($mongo_where)->sort(array('subscriber'=>-1, 'domain'=>-1, 'gateway'=>-1))->limit(1)->slaveOkay();
- $result = $cursor->getNext();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in lookupProfiles(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if (!$result) {
- $log = sprintf(
- "Error: no customer found in mongo billing_customers table for billing party=%s, domain=%s, gateway=%s",
- $this->BillingPartyId,
- $this->domain,
- $this->gateway
- );
- syslog(LOG_NOTICE, $log);
- //return false;
- }
-
- if ($result) {
- if ($result['subscriber']) {
- $this->CustomerProfile = sprintf("subscriber=%s", $result['subscriber']);
- } elseif ($result['domain']) {
- $this->CustomerProfile = sprintf("domain=%s", $result['domain']);
- } elseif ($result['gateway']) {
- $this->CustomerProfile = sprintf("gateway=%s", $result['gateway']);
- } else {
- $this->CustomerProfile = "default";
- }
-
- if (!$result['profile_name1']) {
- $log = sprintf(
- "Error: customer %s (id=%d) has no weekday profile assigned in profiles table",
- $this->CustomerProfile,
- $result['id']
- );
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if (!$result['profile_name2']) {
- $log = sprintf(
- "Error: customer %s (id=%d) has no weekend profile assigned in profiles table",
- $this->CustomerProfile,
- $result['id']
- );
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
-
- if (!$result['timezone']) {
- $log = sprintf(
- "Error: missing timezone for customer %s",
- $this->CustomerProfile
- );
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- $this->billingTimezone = $result['timezone'];
-
- $this->allProfiles = array(
- "profile_workday" => $result['profile_name1'],
- "profile_weekend" => $result['profile_name2'],
- "profile_workday_alt" => $result['profile_name1_alt'],
- "profile_weekend_alt" => $result['profile_name2_alt'],
- "timezone" => $result['timezone']
- );
- if ($result['increment']) {
- $this->increment = $result['increment'];
- }
-
- if ($result['min_duration']) {
- $this->min_duration = $result['min_duration'];
- }
- return true;
- }
- }
-
// mysql backend
$query = sprintf(
"select * from billing_customers
where
(subscriber = '%s' and domain = '' and gateway = '' )
or (domain = '%s' and subscriber = '' and gateway = '' )
or (gateway = '%s' and subscriber = '' and domain = '' )
or (subscriber = '' and domain = '' and gateway = '' )
order by subscriber desc, domain desc, gateway desc limit 1
",
addslashes($this->BillingPartyId),
addslashes($this->domain),
addslashes($this->gateway)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$this->db->next_record();
if ($this->db->Record['subscriber']) {
$this->CustomerProfile = sprintf("subscriber=%s", $this->db->Record['subscriber']);
} elseif ($this->db->Record['domain']) {
$this->CustomerProfile = sprintf("domain=%s", $this->db->Record['domain']);
} elseif ($this->db->Record['gateway']) {
$this->CustomerProfile = sprintf("gateway=%s", $this->db->Record['gateway']);
} else {
$this->CustomerProfile = "default";
}
if (!$this->db->Record['profile_name1']) {
$log = sprintf(
"Error: customer %s (id=%d) has no weekday profile assigned in profiles table",
$this->CustomerProfile,
$this->db->Record['id']
);
syslog(LOG_NOTICE, $log);
return false;
}
if (!$this->db->Record['profile_name2']) {
$log = sprintf(
"Error: customer %s (id=%d) has no weekend profile assigned in profiles table",
$this->CustomerProfile,
$this->db->Record['id']
);
syslog(LOG_NOTICE, $log);
return false;
}
if (!$this->db->Record['timezone']) {
$log = sprintf(
"Error: missing timezone for customer %s",
$this->CustomerProfile
);
syslog(LOG_NOTICE, $log);
return false;
}
$this->billingTimezone = $this->db->Record['timezone'];
$this->allProfiles = array(
"profile_workday" => $this->db->Record['profile_name1'],
"profile_weekend" => $this->db->Record['profile_name2'],
"profile_workday_alt" => $this->db->Record['profile_name1_alt'],
"profile_weekend_alt" => $this->db->Record['profile_name2_alt'],
"timezone" => $this->db->Record['timezone']
);
if ($this->db->Record['increment']) {
$this->increment = $this->db->Record['increment'];
}
if ($this->db->Record['min_duration']) {
$this->min_duration = $this->db->Record['min_duration'];
}
return true;
} else {
$log = sprintf(
"Error: no customer found in billing_customers table for billing party=%s, domain=%s, gateway=%s",
$this->BillingPartyId,
$this->domain,
$this->gateway
);
syslog(LOG_NOTICE, $log);
return false;
}
}
private function lookupRateAudio($dayofyear, $dayofweek, $hourofday, $durationRatedAlready)
{
/*
// Required information from CDR structure
$this->BillingPartyId # calling subscriber
$this->domain # multiple callers may belong to same domain
$this->gateway # multiple callers may belong to the same gateway
$this->cNumber # E164 destination prefixed with 00 (e.g. 0041 CH)
$this->DestinationId # longest matched DestinationId
$this->region # region the destination belongs to
// pertinent to the curent rating SPAN (a span = same profile like evening hours)
$hourofday # which hour of teh day started for peak/ofpeak rates
$dayofweek # which day of the week for matching profiles
$dayofyear # which day of the year for matching holidays
$durationRatedAlready= the full duration for which a profile is defined (e.g. 0800-1800)
// the call is called recursively until the $durationRatedAlready = $CDR->duration
// when a call spans multiple profiles. If we span multiple profiles we must call
// the function again to lookup the corect rates
Rating logic
------------
1. using the profile_name found, lookup the rate_name based
on $hourofday in billing_profiles
- the day may be split in maximum 4 periods
- each day starts with hour 0 and ends with hour 24
- rate_name1 defines the first interval after hour 0
- rate_name2 defines the first interval after rate_name1
- rate_name3 defines the first interval after rate_name2
- rate_name4 defines the first interval after rate_name3
When the hour matches an interval use the rate_nameX found
to lookup the rate in billing_rates
- if no record is found use the rate called 'default'
2. lookup in billing_rates the record having same name found above
and billing_rates.destination = $this->DestinationId
- return an array with all the values to
$this->calculateAudio() function that called us
*/
// get work-day or weekend profile
if ($this->RatingTables->holidays[$dayofyear]) {
$this->profileName = $this->allProfiles['profile_weekend'];
$this->profileNameAlt = $this->allProfiles['profile_weekend_alt'];
$this->PeriodOfProfile = "weekend";
} else {
if ($dayofweek >=1 && $dayofweek <=5) {
$this->profileName = $this->allProfiles['profile_workday'];
$this->profileNameAlt = $this->allProfiles['profile_workday_alt'];
$this->PeriodOfProfile = "weekday";
} else {
$this->profileName = $this->allProfiles['profile_weekend'];
$this->profileNameAlt = $this->allProfiles['profile_weekend_alt'];
$this->PeriodOfProfile = "weekend";
}
}
// get rate for the time of the day
$timestampNextProfile = $this->timestampBilling + $durationRatedAlready;
$profileValues = $this->RatingTables->profiles[$this->profileName];
if (is_array($profileValues)) {
$this->profileNameLog = $this->profileName;
if ($hourofday < $profileValues['hour1']) {
$this->rateName = $profileValues['rate_name1'];
$this->timeInterval = "0-".$profileValues['hour1'];
$foundProfile = $profileValues['hour1'];
$this->nextProfile = $profileValues['hour1'];
} elseif ($hourofday < $profileValues['hour2']) {
$this->rateName = $profileValues['rate_name2'];
$this->timeInterval = $profileValues['hour1']."-".$profileValues['hour2'];
$foundProfile = $profileValues['hour2'];
$this->nextProfile = $profileValues['hour2'];
} elseif ($hourofday < $profileValues['hour3']) {
$this->rateName = $profileValues['rate_name3'];
$this->timeInterval = $profileValues['hour2']."-".$profileValues['hour3'];
$foundProfile = $profileValues['hour3'];
$this->nextProfile = $profileValues['hour3'];
} elseif ($hourofday < $profileValues['hour4']) {
$this->rateName = $profileValues['rate_name4'];
$this->timeInterval = $profileValues['hour3']."-".$profileValues['hour4'];
$foundProfile = $profileValues['hour4'];
$this->nextProfile = 0;
}
if ($this->rateName) {
$found_history=false;
//get historical rating if exists
if (is_array($this->RatingTables->ratesHistory[$this->rateName][$this->DestinationId][$this->application])) {
$h=0;
foreach (($this->RatingTables->ratesHistory[$this->rateName][$this->DestinationId][$this->application]) as $_idx) {
$h++;
if ($_idx['startDate'] <= $this->timestamp) {
if ($_idx['endDate'] > $this->timestamp) {
// found historical rate
$found_history=true;
$this->rateValues=$_idx;
break;
} else {
$_log = sprintf("Interval missmatch %s < %s", $_idx['endDate'], $this->timestamp);
continue;
}
} else {
$_log = sprintf("Interval missmatch %s > %s", $_idx['startDate'], $this->timestamp);
continue;
}
}
}
if (!$found_history) {
if ($this->region) {
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->region);
if (!$this->rateValues) {
// try the destination as last resort
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->DestinationId);
}
} else {
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->DestinationId);
}
}
}
}
$profileValuesAlt = $this->RatingTables->profiles[$this->profileNameAlt];
if (!$this->rateValues && is_array($profileValuesAlt)) {
$this->profileNameLog = $this->profileNameAlt;
if ($hourofday < $profileValuesAlt['hour1']) {
$this->rateName = $profileValuesAlt['rate_name1'];
$this->timeInterval = "0-".$profileValuesAlt['hour1'];
$foundProfile = $profileValuesAlt['hour1'];
$this->nextProfile = $profileValuesAlt['hour1'];
} elseif ($hourofday < $profileValuesAlt['hour2']) {
$this->rateName = $profileValuesAlt['rate_name2'];
$this->timeInterval = $profileValuesAlt['hour1']."-".$profileValuesAlt['hour2'];
$foundProfile = $profileValuesAlt['hour2'];
$this->nextProfile = $profileValuesAlt['hour2'];
} elseif ($hourofday < $profileValuesAlt['hour3']) {
$this->rateName = $profileValuesAlt['rate_name3'];
$this->timeInterval = $profileValuesAlt['hour2']."-".$profileValuesAlt['hour3'];
$foundProfile = $profileValuesAlt['hour3'];
$this->nextProfile = $profileValuesAlt['hour3'];
} elseif ($hourofday < $profileValuesAlt['hour4']) {
$this->rateName = $profileValuesAlt['rate_name4'];
$this->timeInterval = $profileValuesAlt['hour3']."-".$profileValuesAlt['hour4'];
$foundProfile = $profileValuesAlt['hour4'];
$this->nextProfile = 0;
}
if ($this->rateName) {
$found_history=false;
//get historical rating if exists
if (is_array($this->RatingTables->ratesHistory[$this->rateName][$this->DestinationId][$this->application])) {
$h=0;
foreach (($this->RatingTables->ratesHistory[$this->rateName][$this->DestinationId][$this->application]) as $_idx) {
$h++;
if ($_idx['startDate'] <= $this->timestamp) {
if ($_idx['endDate'] > $this->timestamp) {
// found historical rate
$found_history=true;
$this->rateValues=$_idx;
break;
} else {
$_log = sprintf("Interval missmatch %s < %s", $_idx['endDate'], $this->timestamp);
continue;
}
} else {
$_log = sprintf("Interval missmatch %s > %s", $_idx['startDate'], $this->timestamp);
continue;
}
}
}
if (!$found_history) {
if ($this->region) {
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->region);
// try destination as last resort
if (!$this->rateValues) {
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->DestinationId);
}
} else {
$this->rateValues = $this->lookupRateValuesAudio($this->rateName, $this->DestinationId);
}
}
}
}
if (!$this->rateValues) {
$this->rateNotFound=true;
$log = sprintf(
"Error: Cannot find rates for callid=%s, billing party=%s, customer %s, gateway=%s, destination=%s, profile=%s, app=%s",
$this->callId,
$this->BillingPartyId,
$this->CustomerProfile,
$this->gateway,
$this->DestinationId,
$this->profileName,
$this->application
);
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->nextProfile == "24") $this->nextProfile = 0;
$DST = Date("I", $timestampNextProfile);
if (!$this->nextProfile) {
// check it we change daylight saving time tomorrow
// yes this cann happen and we must apply a different rate
$timestampNextProfile =$timestampNextProfile+24*3600;
$DSTNext = Date("I", $timestampNextProfile);
if ($DST != $DSTNext) {
if ($DSTNext==0) {
$timestampNextProfile = $timestampNextProfile+3600;
} elseif ($DSTNext==1) {
$timestampNextProfile = $timestampNextProfile-3600;
}
}
}
// see if we have minimum duration or increment
if ($this->rateValues['increment']) {
// increase the billed duration to the next increment
$this->duration = $this->rateValues['increment'] * ceil($this->duration / $this->rateValues['increment']);
}
$durationToRate=$this->duration-$durationRatedAlready;
$month = Date("m", $timestampNextProfile);
$day = Date("d", $timestampNextProfile);
$year = Date("Y", $timestampNextProfile);
$nextProfileTimestamp = mktime($this->nextProfile, 0, 0, $month, $day, $year);
$npdt=Date("Y-m-d H:i", $nextProfileTimestamp);
$timeTillNextProfile = $nextProfileTimestamp - $this->timestampBilling;
if ($durationToRate > $timeTillNextProfile) {
$diff = $durationToRate - $timeTillNextProfile;
$this->durationRated = $timeTillNextProfile;
} else {
$this->durationRated = $durationToRate;
}
$rate = array(
"customer" => $this->CustomerProfile,
"application" => $this->application,
"profile" => $this->profileNameLog,
"day" => $this->PeriodOfProfile,
"destinationId" => $this->DestinationId,
"duration" => $this->durationRated,
"rate" => $this->rateName,
"values" => $this->rateValues,
"interval" => $this->timeInterval,
"nextHourOfDay" => $this->nextProfile
);
return $rate;
}
private function lookupRateMessage($dayofyear, $dayofweek, $hourofday)
{
/*
// Required information from CDR structure
$this->BillingPartyId # calling subscriber
$this->domain # multiple callers may belong to same domain
$this->gateway # multiple callers may belong to the same gateway
$this->cNumber # E164 destination prefixed with 00 (e.g. 0041 CH)
$this->DestinationId # longest matched DestinationId
$this->region # region the destination belongs to
// pertinent to the curent rating SPAN (a span = same profile like evening hours)
$hourofday # which hour of teh day started for peak/ofpeak rates
$dayofweek # which day of the week for matching profiles
$dayofyear # which day of the year for matching holidays
$durationRatedAlready= the full duration for which a profile is defined (e.g. 0800-1800)
// the call is called recursively until the $durationRatedAlready = $CDR->duration
// when a call spans multiple profiles. If we span multiple profiles we must call
// the function again to lookup the corect rates
Rating logic
------------
1. using the profile_name found, lookup the rate_name based
on $hourofday in billing_profiles
- the day may be split in maximum 4 periods
- each day starts with hour 0 and ends with hour 24
- rate_name1 defines the first interval after hour 0
- rate_name2 defines the first interval after rate_name1
- rate_name3 defines the first interval after rate_name2
- rate_name4 defines the first interval after rate_name3
When the hour matches an interval use the rate_nameX found
to lookup the rate in billing_rates
- if no record is found use the rate called 'default'
2. lookup in billing_rates the record having same name found above
and billing_rates.destination = $this->DestinationId
- return an array with all the values to
$this->calculateAudio() function that called us
*/
// get work-day or weekend profile
if ($this->RatingTables->holidays[$dayofyear]) {
$this->profileName = $this->allProfiles['profile_weekend'];
$this->profileNameAlt = $this->allProfiles['profile_weekend_alt'];
$this->PeriodOfProfile = "weekend";
} else {
if ($dayofweek >=1 && $dayofweek <=5) {
$this->profileName = $this->allProfiles['profile_workday'];
$this->profileNameAlt = $this->allProfiles['profile_workday_alt'];
$this->PeriodOfProfile = "weekday";
} else {
$this->profileName = $this->allProfiles['profile_weekend'];
$this->profileNameAlt = $this->allProfiles['profile_weekend_alt'];
$this->PeriodOfProfile = "weekend";
}
}
// get rate for the time of the day
$timestampNextProfile = $this->timestampBilling + $durationRatedAlready;
$profileValues = $this->RatingTables->profiles[$this->profileName];
if (is_array($profileValues)) {
$this->profileNameLog = $this->profileName;
if ($hourofday < $profileValues['hour1']) {
$this->rateName = $profileValues['rate_name1'];
$this->timeInterval = "0-".$profileValues['hour1'];
$foundProfile = $profileValues['hour1'];
} elseif ($hourofday < $profileValues['hour2']) {
$this->rateName = $profileValues['rate_name2'];
$this->timeInterval = $profileValues['hour1']."-".$profileValues['hour2'];
$foundProfile = $profileValues['hour2'];
} elseif ($hourofday < $profileValues['hour3']) {
$this->rateName = $profileValues['rate_name3'];
$this->timeInterval = $profileValues['hour2']."-".$profileValues['hour3'];
$foundProfile = $profileValues['hour3'];
} elseif ($hourofday < $profileValues['hour4']) {
$this->rateName = $profileValues['rate_name4'];
$this->timeInterval = $profileValues['hour3']."-".$profileValues['hour4'];
$foundProfile = $profileValues['hour4'];
}
if ($this->rateName) {
if ($this->region) {
$this->rateValues=$this->lookupRateValuesMessage($this->rateName, $this->region);
if (!$this->rateValues) {
// try the destination as last resort
$this->rateValues=$this->lookupRateValuesMessage($this->rateName, $this->DestinationId);
}
} else {
$this->rateValues=$this->lookupRateValuesMessage($this->rateName, $this->DestinationId);
}
}
}
$profileValuesAlt = $this->RatingTables->profiles[$this->profileNameAlt];
if (!$this->rateValues && is_array($profileValuesAlt)) {
$this->profileNameLog = $this->profileNameAlt;
if ($hourofday < $profileValuesAlt['hour1']) {
$this->rateName = $profileValuesAlt['rate_name1'];
$this->timeInterval = "0-".$profileValuesAlt['hour1'];
$foundProfile = $profileValuesAlt['hour1'];
} elseif ($hourofday < $profileValuesAlt['hour2']) {
$this->rateName = $profileValuesAlt['rate_name2'];
$this->timeInterval = $profileValuesAlt['hour1']."-".$profileValuesAlt['hour2'];
$foundProfile = $profileValuesAlt['hour2'];
} elseif ($hourofday < $profileValuesAlt['hour3']) {
$this->rateName = $profileValuesAlt['rate_name3'];
$this->timeInterval = $profileValuesAlt['hour2']."-".$profileValuesAlt['hour3'];
$foundProfile = $profileValuesAlt['hour3'];
} elseif ($hourofday < $profileValuesAlt['hour4']) {
$this->rateName = $profileValuesAlt['rate_name4'];
$this->timeInterval = $profileValuesAlt['hour3']."-".$profileValuesAlt['hour4'];
$foundProfile = $profileValuesAlt['hour4'];
}
if ($this->rateName) {
if ($this->region) {
$this->rateValues = $this->lookupRateValuesMessage($this->rateName, $this->region);
// try destination as last resort
if (!$this->rateValues) {
$this->rateValues = $this->lookupRateValuesMessage($this->rateName, $this->DestinationId);
}
} else {
$this->rateValues = $this->lookupRateValuesMessage($this->rateName, $this->DestinationId);
}
}
}
if (!$this->rateValues) {
$this->rateNotFound=true;
$log=sprintf(
"Error: Cannot find rates for callid=%s, billing party=%s, customer %s, gateway=%s, destination=%s, profile=%s, app=sms",
$this->callId,
$this->BillingPartyId,
$this->CustomerProfile,
$this->gateway,
$this->DestinationId,
$this->profileName
);
syslog(LOG_NOTICE, $log);
return false;
}
$rate = array(
"customer" => $this->CustomerProfile,
"application" => $this->application,
"profile" => $this->profileNameLog,
"day" => $this->PeriodOfProfile,
"destinationId" => $this->DestinationId,
"rate" => $this->rateName,
"values" => $this->rateValues,
);
return $rate;
}
public function MaxSessionTime($dictionary)
{
// Used for prepaid application to return maximum session time based on a prepaid balance
$this->rateValuesCache = array();
$this->MaxSessionTimeSpans = 0;
$durationRate = 0;
/////////////////////////////////////////////////////
// required fields passed from the CDR structure
//
$this->timestamp = time();
$this->callId = $dictionary['callId'];
$this->DestinationId = $dictionary['DestinationId'];
$this->BillingPartyId = $dictionary['BillingPartyId'];
$this->domain = $dictionary['domain'];
$this->duration = $dictionary['duration'];
$this->aNumber = $dictionary['aNumber'];
$this->cNumber = $dictionary['cNumber'];
$this->gateway = $dictionary['gateway'];
$this->RatingTables = $dictionary['RatingTables'];
$this->application = $dictionary['application'];
$this->ResellerId = $dictionary['ResellerId'];
$Balance = $dictionary['Balance'];
if (!$this->application) $this->application='audio';
if (!$this->DestinationId) {
$log = sprintf("Error: no DestinationId supplied in MaxSessionTime()");
syslog(LOG_NOTICE, $log);
return false;
}
if (!$this->lookupDestinationDetails()) {
return false;
}
if (!$this->lookupProfiles()) {
return false;
}
$this->startTimeBilling = getLocalTime($this->billingTimezone, $this->timestamp);
list($dateText,$timeText) = explode(" ", trim($this->startTimeBilling));
$Bdate = explode("-", $dateText);
$Btime = explode(":", $timeText);
$this->timestampBilling = mktime($Btime[0], $Btime[1], $Btime[2], $Bdate[1], $Bdate[2], $Bdate[0]);
$this->startTimeBilling = Date("Y-m-d H:i:s", $this->timestampBilling);
$i=0;
$durationRatedTotal=0;
while ($Balance > 0) {
$span++;
$this->MaxSessionTimeSpans++;
if ($i == "0") {
$dayofweek = date("w", $this->timestampBilling);
$hourofday = date("G", $this->timestampBilling);
$dayofyear = date("Y-m-d", $this->timestampBilling);
} else {
$dayofweek = date("w", $this->timestampBilling+$durationRatedTotal);
$hourofday = $foundRate['nextHourOfDay'];
$dayofyear = date("Y-m-d", $this->timestampBilling+$durationRatedTotal);
}
$foundRate = $this->lookupRateAudio($dayofyear, $dayofweek, $hourofday, $durationRatedTotal);
if ($this->rateNotFound) {
// break here to avoid loops
break;
}
$thisRate=$foundRate;
if ($j > 0) {
$payConnect=0;
$durationForRating = $thisRate['duration'];
} else {
$payConnect=1;
if ($this->min_duration && $this->duration < $this->min_duration) {
$durationForRating=$this->min_duration;
} else {
$durationForRating=$thisRate['duration'];
}
}
$j++;
$connectCost = $thisRate['values']['connectCost'];
$durationRate = $thisRate['values']['durationRate'];
if ($span=="1" && !$dictionary['skipConnectCost']) {
$this->connectCost=number_format($connectCost/$this->priceDenominator, $this->priceDecimalDigits);
$connectCostSpan=$connectCost;
$setupBalanceRequired=$connectCost/$this->priceDenominator;
if ($connectCost && $Balance <= $setupBalanceRequired) {
syslog(LOG_NOTICE, "Balance too small: $Balance <= $setupBalanceRequired");
return false;
}
$Balance = $Balance-$setupBalanceRequired;
} else {
$connectCostSpan=0;
$setupBalanceRequired=0;
}
$connectCostPrint = number_format($connectCostSpan/$this->priceDenominator, $this->priceDecimalDigits);
$durationRatePrint = number_format($durationRate/$this->priceDenominator, $this->priceDecimalDigits);
$spanPrice = $this->price+$setupBalanceRequired*$payConnect+
$durationRate*$durationForRating/$this->durationPeriodRated/$this->priceDenominator;
if ($Balance > $spanPrice) {
$Balance = $Balance-$spanPrice;
$durationRatedTotal = $durationRatedTotal+ $foundRate['duration'];
} else {
$durationAllowedinThisSpan = $Balance /
$durationRate * $this->durationPeriodRated * $this->priceDenominator;
$rateOfThisSpan=$durationRate/$this->priceDenominator;
$durationRatedTotal=$durationRatedTotal + $durationAllowedinThisSpan;
$Balance=$Balance-$spanPrice;
return $durationRatedTotal;
}
if ($durationRatedTotal >= $this->duration) {
return sprintf("%f", $durationRatedTotal);
}
$i++;
if ($i>10) {
return sprintf("%f", $durationRatedTotal);
break;
}
}
return false;
}
private function lookupRateValuesAudio($rateName, $DestinationId)
{
if (is_array($this->rateValuesCache[$rateName][$DestinationId][$this->application])) {
return $this->rateValuesCache[$rateName][$DestinationId][$this->application];
}
- if ($this->mongo_db != null) {
- // mongo backend
- $mongo_where['destination'] = $DestinationId;
- $mongo_where['application'] = $this->application;
- $mongo_where['$or'] = array(
- array('reseller_id' => intval($this->ResellerId)),
- array('reseller_id' => 0)
- );
-
- try {
- $table = $this->mongo_db->selectCollection('billing_rates');
- $cursor = $table->find($mongo_where)->sort(array('reseller_id'=>-1))->limit(1)->slaveOkay();
- $result = $cursor->getNext();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in lookupRateValuesAudio(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if (!$result) {
- $log = sprintf("Error: cannot find mongo rate values for dest id %s", $DestinationId);
- syslog(LOG_NOTICE, $log);
- //return false;
- }
-
- if ($result) {
- $values=array(
- "connectCost" => $result['connectCost'],
- "durationRate" => $result['durationRate'],
- "connectCostIn" => $result['connectCostIn'],
- "durationRateIn" => $result['durationRateIn']
- );
-
- // cache values
- $this->rateValuesCache[$rateName][$DestinationId][$this->application]=$values;
- return $values;
- }
- }
-
if ($this->settings['split_rating_table']) {
if ($rateName) {
$table="billing_rates_".$rateName;
} else {
$table="billing_rates_default";
}
$query = sprintf(
"select * from %s where destination = '%s' and application = '%s'",
addslashes($table),
addslashes($DestinationId),
addslashes($this->application)
);
} else {
$table = "billing_rates";
$query = sprintf(
"select * from %s where name = '%s' and destination = '%s' and application = '%s'",
addslashes($table),
addslashes($rateName),
addslashes($DestinationId),
addslashes($this->application)
);
}
// mysql backend
if (!$this->db->query($query)) {
if ($this->db->Errno != 1146) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
// try the main table
$query = sprintf(
"select * from billing_rates where name = '%s' and destination = '%s' and application = '%s'",
addslashes($rateName),
addslashes($DestinationId),
addslashes($this->application)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
}
if ($this->db->num_rows()) {
$this->db->next_record();
$values = array(
"connectCost" => $this->db->Record['connectCost'],
"durationRate" => $this->db->Record['durationRate'],
"connectCostIn" => $this->db->Record['connectCostIn'],
"durationRateIn" => $this->db->Record['durationRateIn']
);
// cache values
$this->rateValuesCache[$rateName][$DestinationId][$this->application] = $values;
return $values;
} else {
return false;
}
}
private function lookupRateValuesMessage($rateName, $DestinationId)
{
if (is_array($this->rateValuesCache[$rateName][$DestinationId]['sms'])) {
return $this->rateValuesCache[$rateName][$DestinationId]['sms'];
}
- if ($this->mongo_db != null) {
- // mongo backend
- $mongo_where['application'] = 'sms';
- $mongo_where['$or'] = array(
- array('reseller_id' => intval($this->ResellerId)),
- array('reseller_id' => 0)
- );
- $mongo_where['$or'] = array(
- array('destination' => $DestinationId),
- array('destination' => '')
- );
-
- try {
- $table = $this->mongo_db->selectCollection('billing_rates');
- $cursor = $table->find($mongo_where)->sort(array('destination'=>-1))->limit(1)->slaveOkay();
- $result = $cursor->getNext();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in lookupRateValuesMessage(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return false;
- }
-
- if (!$result) {
- $log = sprintf(
- "Error: cannot find mongo rate sms values for dest id %s",
- $DestinationId
- );
- syslog(LOG_NOTICE, $log);
- //return false;
- }
-
- if ($result) {
- $values = array(
- "connectCost" => $result['connectCost']
- );
-
- // cache values
- $this->rateValuesCache[$rateName][$DestinationId]['sms'] = $values;
- return $values;
- }
- }
-
if ($this->settings['split_rating_table']) {
if ($rateName) {
$table = "billing_rates_".$rateName;
} else {
$table = "billing_rates_default";
}
$query = sprintf(
"select * from %s where (destination = '%s' or destination = '') and application = 'sms' order by destination desc limit 1",
addslashes($table),
addslashes($DestinationId)
);
} else {
$table = "billing_rates";
$query = sprintf(
"select * from %s where name = '%s' and (destination = '%s' or destination = '') and application = 'sms' order by destination desc limit 1",
addslashes($table),
addslashes($rateName),
addslashes($DestinationId)
);
}
// mysql backend
if (!$this->db->query($query)) {
if ($this->db->Errno != 1146) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
// try the main table
// lookup rate from MySQL
$query = sprintf(
"select * from billing_rates where name = '%s' and (destination = '%s' or destination = '') and application = 'sms' order by destination desc limit 1",
addslashes($rateName),
addslashes($DestinationId)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
}
if ($this->db->num_rows()) {
$this->db->next_record();
$values = array(
"connectCost" => $this->db->Record['connectCost']
);
// cache values
$this->rateValuesCache[$rateName][$DestinationId]['sms']=$values;
return $values;
} else {
return false;
}
}
}
class RatingTables
{
- var $database_backend = 'mysql'; // mongo or mysql
+ var $database_backend = 'mysql';
var $csv_export=array(
"destinations" => "destinations.csv",
"billing_customers" => "customers.csv",
"billing_profiles" => "profiles.csv",
"billing_rates" => "rates.csv",
"billing_rates_history" => "ratesHistory.csv",
"billing_discounts" => "discounts.csv",
"billing_enum_tlds" => "enumtld.csv",
"prepaid" => "prepaid.csv",
"quota_usage" => "quotausage.csv"
);
var $csv_import = array(
"destinations" => "destinations.csv",
"billing_customers" => "customers.csv",
"billing_profiles" => "profiles.csv",
"billing_rates" => "rates.csv",
"billing_rates_history" => "ratesHistory.csv",
"billing_discounts" => "discounts.csv"
);
var $previously_imported_files = 0;
var $maxrowsperpage = 15;
var $insertDomainOption = array();
var $delimiter = ",";
var $filesToImport = array();
var $importFilesPatterns = array(
'ratesHistory',
'rates',
'profiles',
'destinations',
'discounts',
'customers'
);
var $mustReload = false;
var $web_elements = array(
'table',
'export',
'web_task',
'subweb_task',
'confirmDelete',
'confirmCopy',
'next',
'id',
'search_text',
'ReloadRatingTables',
'account',
'balance',
'fromRate',
'toRate',
'sessionId'
);
var $requireReload = array('destinations');
var $whereResellerFilter = " (1=1) ";
var $cvs_import_dir = "/var/spool/cdrtool";
var $tables = array(
"destinations" => array(
"name" => "Destinations",
"skip_math" => true,
"keys" => array(
"id"
),
"exceptions" => array(),
"order" => "dest_id ASC",
"domainFilterColumn" => "domain",
"fields" => array(
"gateway" => array(
"size" => 15,
"checkType" => 'ip',
"name" => "Trusted peer"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"domain" => array(
"size" => 15,
"name" => "Domain",
"checkType" => 'domain',
"class" => "span2"
),
"subscriber" => array(
"size" => 15,
"checkType" => 'sip_account',
"name" => "Subscriber",
"class" => "span2"
),
"dest_id" => array(
"size" => 12,
"name" => "Destination",
),
"region" => array(
"size" => 10,
"name" => "Region"
),
"dest_name" => array(
"size" => 20,
"name" => "Description",
"class" => "span2"
),
"increment" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "Incr"
),
"min_duration" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "Min Dur"
),
"max_duration" => array(
"size" => 5,
"checkType" => 'numeric',
"name" => "Max Dur"
),
"max_price" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Max Price"
)
)
),
"billing_customers" => array(
"name" => "Customers",
"skip_math" => true,
"keys" => array("id"),
"domainFilterColumn" => "domain",
"fields" => array(
"gateway" => array(
"size" => 15,
"checkType" => 'ip',
"name" => "Trusted Peer"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"domain" => array(
"size" => 15,
"checkType" => 'domain',
"name" => "Domain",
"class" => "span2"
),
"subscriber" => array(
"size" => 25,
"checkType" => 'sip_account',
"name" => "Subscriber",
"class" => "span2"
),
"profile_name1" => array(
"size" => 10,
"name" => "Profile WD"
),
"profile_name1_alt" => array(
"size" => 8,
"name" => "Fallback"
),
"profile_name2" => array(
"size" => 10,
"name" => "Profile WE"
),
"profile_name2_alt" => array(
"size" => 8,
"name" => "Fallback"
),
"timezone" => array(
"size" => 16,
"name" => "Timezone",
"class" => "span2"
),
"increment" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "Incr"
),
"min_duration" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "Min Dur"
)
)
),
"billing_discounts" => array(
"name" => "Discounts",
"keys" => array("id"),
"domainFilterColumn" => "domain",
"fields" => array(
"gateway" => array(
"size" => 15,
"checkType" => 'ip',
"name" => "Trusted Peer"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"domain" => array(
"size" => 15,
"checkType" => 'domain',
"name" => "Domain",
"class" => "span2"
),
"subscriber" => array(
"size" => 25,
"checkType" => 'sip_account',
"name" => "Subscriber",
"class" => "span2"
),
"application" => array(
"size" => 6,
"name" => "App"
),
"destination" => array(
"size" => 10,
"name" => "Destination"
),
"region" => array(
"size" => 8,
"name" => "Region"
),
"connect" => array(
"size" => 5,
"name" => "Connect"
),
"duration" => array(
"size" => 5,
"name" => "Duration"
)
)
),
"billing_profiles" => array(
"name" => "Profiles",
"skip_math" => true,
"keys" => array("id"),
"exceptions" => array(),
"size" => 6,
"fields" => array(
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"name" => array(
"size" => 12,
"name" => "Profile",
"class" => "span2"
),
"rate_name1" => array(
"size" => 12,
"name" => "Rate 1"
),
"hour1" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "00-H1"
),
"rate_name2" => array(
"size" => 12,
"name" => "Rate 2"
),
"hour2" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "H1-H2"
),
"rate_name3" => array(
"size" => 12,
"name" => "Rate 3"
),
"hour3" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "H2-H3"
),
"rate_name4" => array(
"size" => 12,
"name" => "Rate 4"
),
"hour4" => array(
"size" => 3,
"checkType" => 'numeric',
"name" => "H3-24"
),
)
),
"billing_rates" => array(
"name" => "Rates",
"keys" => array("id"),
"size" => 10,
"exceptions" => array('maxPrice'),
"order" => "durationRate desc",
"fields" => array(
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"name" => array(
"size" => 12,
"name" => "Rate",
"class" => "span2"
),
"destination" => array(
"size" => 12,
"name" => "Destination"
),
"application" => array(
"size" => 6,
"name" => "App"
),
"connectCost" => array(
"size" => 8,
"checkType" => 'numeric',
"name"=>"Connect"
),
"durationRate" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Duration"
),
"connectCostIn" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Conn In"
),
"durationRateIn" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Duration In"
)
)
),
"billing_rates_history" => array(
"name" => "Rates history",
"keys" => array("id"),
"size" => 10,
"order" => "destination ASC, name ASC",
"fields" => array(
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"name" => array(
"size" => 10,
"name" => "Rate",
"class" => "span2"
),
"destination" => array(
"size" => 12,
"name" => "Destination"
),
"application" => array(
"size" => 6,
"name" => "App"
),
"connectCost" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Conn"
),
"durationRate" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Price"
),
"connectCostIn" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Conn In"
),
"durationRateIn" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Price In"
),
"startDate" => array(
"size" => 11,
"name" => "Start Date",
"class" => "span2"
),
"endDate" => array(
"size" => 11,
"name" => "End Date",
"class" => "span2"
)
)
),
"billing_enum_tlds" => array(
"name" => "ENUM discounts",
"skip_math" => true,
"keys" => array("id"),
"exceptions" => array(),
"size" => 6,
"fields" => array(
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"enum_tld" => array(
"size" => 35,
"mustExist" => true,
"checkType" => 'domain',
"name" => "ENUM TLD",
"class" => "span2"
),
"e164_regexp" => array(
"size" => 35,
"mustExist" => true,
"name" => "E164 Regexp",
"class" => "span2"
),
"discount" => array(
"size" => 10,
"mustExist" => true,
"checkType" => 'numeric',
"name" => "Discount"
)
)
),
"prepaid" => array(
"name" => "Prepaid accounts",
"keys" => array("id"),
"size" => 15,
"exceptions" => array('change_date','active_sessions','domain'),
"order" => "change_date DESC",
"fields" => array(
"account" => array(
"size" => 35,
"name" => "Subscriber",
"checkType" => 'sip_account',
"mustExist" => true,
"class" => "span2"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"balance" => array(
"size" => 10,
"name" => "Balance"
),
"change_date" => array(
"size" => 19,
"name" => "Last Change",
"readonly" => 1
),
"session_counter" => array(
"size" => 3,
"name" => "Active Sessions",
"readonly" => 1
),
"max_sessions" => array(
"size" => 3,
"name" => "Max Sessions"
)
)
),
"prepaid_cards" => array(
"name" => "Prepaid cards",
"keys" => array("id"),
"size" => 15,
"exceptions" => array('service'),
"fields" => array(
"batch" => array(
"size" => 40,
"name" => "Batch name",
"readonly" => 1,
"class" => "span3"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller"
),
"date_batch" => array(
"size" => 11,
"name" => "Batch Date",
"class" => "span2"
),
"number" => array(
"size" => 20,
"checkType" => 'numeric',
"mustExist" => true,
"name" => "Card Number",
"class" => "span2"
),
"id" => array(
"size" => 20,
"checkType" => 'numeric',
"mustExist" => true,
"name" => "Card Id",
),
"value" => array(
"size" => 8,
"checkType" => 'numeric',
"mustExist" => true,
"name" => "Card Value"
),
"blocked" => array(
"size" => 1,
"name" => "Lock"
),
"date_active" => array(
"size" => 18,
"name" => "Activation Date",
"class" => "span2"
)
)
),
"prepaid_history" => array(
"name" => "Prepaid history",
"order" => "id DESC",
"skip_math" => true,
"keys" => array("id"),
"size" => 15,
"exceptions" => array('session','destination'),
"fields" => array(
"username" => array(
"size" => 15,
"readonly" => 1,
"class" => "span2"
),
"domain" => array(
"size" => 15,
"readonly" => 1,
"class" => "span2"
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller",
"readonly" => 1
),
"action" => array(
"size" => 15,
"readonly" => 1,
"class" => "span2"
),
"duration" => array(
"size" => 5
),
"destination" => array(
"size" => 15
),
"session" => array(
"size" => 30,
"readonly" => 1
),
"description" => array(
"size" => 30,
"class" => "span3"
),
"value" => array(
"size" => 10
),
"balance" => array(
"size" => 10
),
"date" => array(
"size" => 18,
"class" => "span2"
)
)
),
"quota_usage" => array(
"name" => "Quota usage",
"keys" => array("id"),
"size" => 15,
"readonly" => 1,
"exceptions" => array(
"change_date",
"traffic",
"duration",
"calls"
),
"domainFilterColumn" => "domain",
"fields" => array(
"datasource" => array(
"size" => 15,
"readonly" => 1
),
"reseller_id" => array(
"size" => 8,
"checkType" => 'numeric',
"name" => "Reseller",
"readonly" => true
),
"account" => array(
"size" => 30,
"readonly" => 1,
"name" => "Subscriber",
"class" => "span2"
),
"domain" => array(
"size" => 15,
"readonly" => 1,
"class" => "span2"
),
"blocked" => array(
"size" => 2,
"readonly" => 1
),
"notified" => array(
"size" => 20,
"readonly" => 1
),
"quota" => array(
"size" => 5,
"readonly" => 1
),
"cost" => array(
"size" => 10,
"readonly" => 1,
"name" => "This Month"
),
"cost_today" => array(
"size" => 10,
"readonly" => 1,
"name" => "Today"
),
"duration" => array(
"size" => 10,
"readonly" => 1
),
"calls" => array(
"size" => 10,
"readonly" => 1
),
"traffic" => array(
"size" => 20,
"readonly" => 1
)
)
)
);
public function RatingTables($readonly = false)
{
global $CDRTool;
global $RatingEngine;
- $this->mongo_db_ro = null;
- $this->mongo_db_rw = null;
-
$this->settings = $RatingEngine;
$this->CDRTool = $CDRTool;
$this->table = $_REQUEST['table'];
if (!$this->table || !in_array($this->table, array_keys($this->tables))) {
$this->table="destinations";
}
$this->readonly=$readonly;
if ($this->settings['csv_delimiter']) {
$this->delimiter=$this->settings['csv_delimiter'];
}
if (!strlen($this->CDRTool['filter']['customer'])) {
$this->whereResellerFilter = sprintf("reseller_id = %d", '99999999');
} else {
if ($this->CDRTool['filter']['customer'] && $this->tables[$this->table]['fields']['reseller_id']) {
$this->whereResellerFilter = sprintf("reseller_id = %d", addslashes($this->CDRTool['filter']['customer']));
$this->tables[$this->table]['fields']['reseller_id']['readonly']=true;
}
}
if ($this->settings['split_rating_table']) {
$this->tables['billing_rates']['fields']['name']['readonly'] = 1;
}
if (strlen($this->settings['socketIP'])) {
if ($this->settings['socketIP'] == '0.0.0.0' || $this->settings['socketIP'] == '0') {
$this->settings['socketIPforClients'] = '127.0.0.1';
} else {
$this->settings['socketIPforClients'] = $this->settings['socketIP'];
}
}
if ($this->settings['database_backend']) {
$this->database_backend = $this->settings['database_backend'];
}
$this->db = new DB_cdrtool;
$this->db1 = new DB_cdrtool;
$this->db->Halt_On_Error="no";
$this->db1->Halt_On_Error="no";
- if ($this->database_backend == "mysql") {
- # TODO
- } elseif ($this->database_backend == "mongo") {
- $this->mongo_safe = 1;
- if (is_array($this->settings['mongo_db'])) {
- $mongo_uri = $this->settings['mongo_db']['uri'];
- $mongo_replicaSet = $this->settings['mongo_db']['replicaSet'];
- $mongo_database = $this->settings['mongo_db']['database'];
- if ($this->settings['mongo_db']['safe']) {
- $this->mongo_safe = $this->settings['mongo_db']['safe'];
- }
- try {
- $mongo_connection_rw = new Mongo(
- "mongodb://$mongo_uri?readPreference=primaryPreferred",
- array(
- "replicaSet" => $mongo_replicaSet
- )
- );
- $mongo_connection_ro = new Mongo(
- "mongodb://$mongo_uri?readPreference=secondaryPreferred",
- array(
- "replicaSet" => $mongo_replicaSet
- )
- );
- $this->mongo_db_rw = $mongo_connection_rw->selectDB($mongo_database);
- $this->mongo_db_ro = $mongo_connection_ro->selectDB($mongo_database);
- } catch (Exception $e) {
- $log = sprintf("Error: mongo exception in RatingTables(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- }
-
- $existing_rating_tables=array();
- try {
- $_tables=$this->mongo_db_ro->listCollections();
- foreach ($_tables as $_table) {
- list($collection, $table) = explode(".", strval($_table));
- $existing_rating_tables[]=$table;
- }
- } catch (Exception $e) {
- $log = sprintf("<p>Caught exception in RatingTables(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- }
-
- foreach (array_keys($this->csv_export) as $table) {
- if (!in_array($table, $existing_rating_tables)) {
- try {
- $this->mongo_db_rw->command(array("create" => $table));
- $log=sprintf("Created mongo collection %s", $table);
- syslog(LOG_NOTICE, $log);
- } catch (Exception $e) {
- $log=sprintf("Error creating mongo collection %s: %s", $table, $e->getMessage());
- syslog(LOG_NOTICE, $log);
- }
- }
- }
- }
- }
}
public function ImportCSVFiles($dir = false)
{
$results = 0;
if (!$dir) $dir = "/var/spool/cdrtool";
$this->scanFilesForImport($dir);
if ($this->previously_imported_files) {
printf("Skipping %d previously imported files\n", $this->previously_imported_files);
}
$results=0;
foreach (array_keys($this->filesToImport) as $file) {
$importFunction = "Import".ucfirst($this->filesToImport[$file]['type']);
printf("Reading file %s\n", $this->filesToImport[$file]['path']);
$results = $this->$importFunction($this->filesToImport[$file]['path'],$this->filesToImport[$file]['reseller']);
$this->logImport(
$dir,
$this->filesToImport[$file]['path'],
$this->filesToImport[$file]['watermark'],
$results,
$this->filesToImport[$file]['reseller']
);
}
return $results;
}
private function ImportRates($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
printf("Importing rates from %s for reseller %s:\n", $file, $reseller);
while ($buffer = fgets($fp, 1024)) {
$buffer = trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$name = trim($p[2]);
$destination = trim($p[3]);
$application = trim($p[4]);
$connectCost = trim($p[5]);
$durationRate = trim($p[6]);
$connectCostIn = trim($p[7]);
$durationRateIn = trim($p[8]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (!is_numeric($destination) && !strstr($destination, '@')) {
// skip invalid destinations
$skipped++;
continue;
}
if (strlen($connectCost) && !is_numeric($connectCost)) {
$skipped++;
continue;
}
if (strlen($durationRate) && !is_numeric($durationRate)) {
$skipped++;
continue;
}
if (!$application) $application='audio';
if ($ops=="1") {
$query = sprintf(
"insert into billing_rates
(
reseller_id,
name,
destination,
application,
connectCost,
durationRate,
connectCostIn,
durationRateIn
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn)
);
// mysql backend
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
if ($this->db->affected_rows()) {
if ($this->settings['split_rating_table']) {
if ($name) {
$_table = 'billing_rates_'.$name;
} else {
$_table = 'billing_rates_default';
}
if (!$this->createRatingTable($name)) {
$query = sprintf(
"insert into %s
(
id,
reseller_id,
name,
destination,
application,
connectCost,
durationRate,
connectCostIn,
durationRateIn
) values (
LAST_INSERT_ID(),
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($_table),
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
}
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in billing_rates: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "3") {
$query = sprintf(
"delete from billing_rates
where
reseller_id = '%s'
and name = '%s'
and destination = '%s'
and application = '%s'",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application)
);
// mysql backend
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
if ($this->settings['split_rating_table']) {
if ($name) {
$_table = 'billing_rates_'.$name;
} else {
$_table = 'billing_rates_default';
}
$query = sprintf(
"delete from %s
where reseller_id = '%s'
and name = '%s'
and destination = '%s'
and application = '%s'",
addslashes($_table),
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates');
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array(
- "safe" => $self->mongo_safe
- )
- );
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when deleting from billing_rates: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
- } elseif ($ops == "2") {
- $query = sprintf(
- "select * from billing_rates
- where name = '%s'
- and destination = '%s'
- and reseller_id = '%s'
- and application = '%s'
- ",
- addslashes($name),
- addslashes($destination),
- addslashes($reseller_id),
- addslashes($application)
- );
-
// mysql backend
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update billing_rates set
connectCost = '%s',
durationRate = '%s',
connectCostIn = '%s',
durationRateIn = '%s'
where name = '%s'
and destination = '%s'
and reseller_id = '%s'
and application = '%s'
",
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn),
addslashes($name),
addslashes($destination),
addslashes($reseller_id),
addslashes($application)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
if ($this->settings['split_rating_table']) {
if ($name) {
$_table = 'billing_rates_'.$name;
} else {
$_table = 'billing_rates_default';
}
$query = sprintf(
"update %s set
connectCost = '%s',
durationRate = '%s',
connectCostIn = '%s',
durationRateIn = '%s'
where name = '%s'
and destination = '%s'
and reseller_id = '%s'
and application = '%s'
",
addslashes($_table),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn),
addslashes($name),
addslashes($destination),
addslashes($reseller_id),
addslashes($application)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
$updated++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application
- );
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn)
- );
- $mongo_options = array(
- "upsert" => true,
- "safe" => $self->mongo_safe
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when updating billing_rates: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into billing_rates
(
reseller_id,
name,
destination,
application,
connectCost,
durationRate,
connectCostIn,
durationRateIn
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
if ($this->settings['split_rating_table']) {
if ($name) {
$_table = 'billing_rates_'.$name;
} else {
$_table = 'billing_rates_default';
}
if (!$this->createRatingTable($name)) {
$query = sprintf(
"insert into %s
(
id,
reseller_id,
name,
destination,
application
connectCost,
durationRate,
connectCostIn,
durationRateIn
) values (
LAST_INSERT_ID(),
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($_table),
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
}
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when inserting in billing_rates: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
}
} else {
$skipped++;
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($skipped) print "Skipped $skipped records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results = $inserted+$updated+$deleted;
return $results;
}
private function ImportRatesHistory($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$this->mustReload=true;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
printf("Importing rates history from %s for reseller %s:\n", $file, $reseller);
while ($buffer = fgets($fp, 1024)) {
$buffer=trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$name = trim($p[2]);
$destination = trim($p[3]);
$application = trim($p[4]);
$connectCost = trim($p[5]);
$durationRate = trim($p[6]);
$connectCostIn = trim($p[7]);
$durationRateIn = trim($p[8]);
$startDate = trim($p[9]);
$endDate = trim($p[10]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (!is_numeric($destination) && !strstr($destination, '@')) {
// skip invalid destinations
$skipped++;
continue;
}
if (strlen($connectCost) && !is_numeric($connectCost)) {
$skipped++;
continue;
}
if (strlen($durationRate) && !is_numeric($durationRate)) {
$skipped++;
continue;
}
if (preg_match("/^\d{4}\-{\d{2}\-\d{2}$/", $startDate)) {
$skipped++;
continue;
}
if (preg_match("/^\d{4}\-{\d{2}\-\d{2}$/", $endDate)) {
$skipped++;
continue;
}
if ($ops=="1") {
$query = sprintf(
"insert into billing_rates_history
(
reseller_id,
name,
destination,
application,
connectCost,
durationRate,
connectCostIn,
durationRateIn,
startDate,
endDate
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn),
addslashes($startDate),
addslashes($endDate)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn),
- 'startDate' => $startDate,
- 'endDate' => $endDate
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates_history');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in billing_rates_history: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
} elseif ($ops=="3") {
$query = sprintf(
"delete from billing_rates_history
where reseller_id = '%s'
and name = '%s'
and destination = '%s'
and startDate = '%s'
and endDate = '%s'",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($startDate),
addslashes($endDate)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates_history');
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'startDate' => $startDate,
- 'endDate' => $endDate
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array("safe" => $self->mongo_safe)
- );
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when deleting from billing_rates_history: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops=="2") {
$query = sprintf(
"select * from billing_rates_history
where name = '%s'
and destination = '%s'
and reseller_id = '%s'
and startDate = '%s'
and endDate = '%s'
",
addslashes($name),
addslashes($destination),
addslashes($reseller_id),
addslashes($startDate),
addslashes($endDate)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update billing_rates_history set
application = '%s',
connectCost = '%s',
durationRate = '%s',
connectCostIn = '%s',
connectCostIn = '%s'
where name = '%s'
and destination = '%s'
and reseller_id = '%s'
and startDate = '%s'
and endDate = '%s'
",
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn),
addslashes($name),
addslashes($destination),
addslashes($reseller_id),
addslashes($startDate),
addslashes($endDate)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$updated++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'startDate' => $startDate,
- 'endDate' => $endDate
- );
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn),
- 'startDate' => $startDate,
- 'endDate' => $endDate
- );
- $mongo_options = array(
- "upsert" => true,
- "safe" => $self->mongo_safe
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates_history');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when updating billing_rates_history: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into billing_rates_history
(
reseller_id,
name,
destination,
application,
connectCost,
durationRate,
connectCostIn,
durationRateIn,
startDate,
endDate
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($name),
addslashes($destination),
addslashes($application),
addslashes($connectCost),
addslashes($durationRate),
addslashes($connectCostIn),
addslashes($durationRateIn),
addslashes($startDate),
addslashes($endDate)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data=array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name,
- 'destination' => $destination,
- 'application' => $application,
- 'connectCost' => intval($connectCost),
- 'durationRate' => intval($durationRate),
- 'connectCostIn' => intval($connectCostIn),
- 'durationRateIn' => intval($durationRateIn),
- 'startDate' => $startDate,
- 'endDate' => $endDate
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_rates_history');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when inserting in billing_rates_history: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
}
} else {
$skipped++;
}
$j++;
if ($j=="10000") {
flush();
$j=0;
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($skipped) print "Skipped $skipped records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results = $inserted + $updated + $deleted;
return $results;
}
private function ImportCustomers($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$this->mustReload = true;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
printf("Importing customers from %s for reseller %s:\n", $file, $reseller);
while ($buffer = fgets($fp, 1024)) {
$buffer=trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$gateway = trim($p[2]);
$domain = trim($p[3]);
$subscriber = trim($p[4]);
$profile_name1 = trim($p[5]);
$profile_name1_alt = trim($p[6]);
$profile_name2 = trim($p[7]);
$profile_name2_alt = trim($p[8]);
$timezone = trim($p[9]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (strlen($reseller_id) && !is_integer($reseller_id)) {
$skipped++;
continue;
}
if ($ops=="1") {
$query = sprintf(
"insert into billing_customers
(
reseller_id,
gateway,
domain,
subscriber,
profile_name1,
profile_name2,
timezone,
profile_name1_alt,
profile_name2_alt
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($profile_name1),
addslashes($profile_name2),
addslashes($timezone),
addslashes($profile_name1_alt),
addslashes($profile_name2_alt)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'profile_name1' => $profile_name1,
- 'profile_name2' => $profile_name2,
- 'profile_name1_alt' => $profile_name1_alt,
- 'profile_name2_alt' => $profile_name2_alt,
- 'timezone' => $timezone
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_customers');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when inserting in billing_customers: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "3") {
$query = sprintf(
"delete from billing_customers
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_customers');
- $mongo_match = array(
- 'gateway' => $gateway,
- 'reseller_id' => intval(reseller_id),
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array("safe" => $self->mongo_safe)
- );
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when deleting from billing_customers: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "2") {
$query = sprintf(
"select * from billing_customers
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update billing_customers set
profile_name1 = '%s',
profile_name2 = '%s',
profile_name1_alt = '%s',
profile_name2_alt = '%s',
timezone = '%s'
where gateway = '%s'
and domain = '%s'
and reseller_id = '%s'
and subscriber = '%s'\n",
addslashes($profile_name1),
addslashes($profile_name2),
addslashes($profile_name1_alt),
addslashes($profile_name2_alt),
addslashes($timezone),
addslashes($gateway),
addslashes($domain),
addslashes($reseller_id),
addslashes($subscriber)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$updated++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match = array(
- 'gateway' => $gateway,
- 'reseller_id' => intval(reseller_id),
- 'domain' => $domain,
- 'subscriber' => $subscriber
- );
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'profile_name1' => $profile_name1,
- 'profile_name2' => $profile_name2,
- 'profile_name1_alt' => $profile_name1_alt,
- 'profile_name2_alt' => $profile_name2_alt,
- 'timezone' => $timezone
- );
- $mongo_options = array("upsert" => true,
- "safe" => $self->mongo_safe
- );
-
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_customers');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when updating billing_customers: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into billing_customers
(
reseller_id,
gateway,
domain,
subscriber,
profile_name1,
profile_name2,
timezone,
profile_name1_alt,
profile_name2_alt
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($profile_name1),
addslashes($profile_name2),
addslashes($timezone),
addslashes($profile_name1_alt),
addslashes($profile_name2_alt)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$inserted++;
}
- if ($this->mongo_db_rw) {
- $mongo_data=array('reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'profile_name1' => $profile_name1,
- 'profile_name2' => $profile_name2,
- 'profile_name1_alt' => $profile_name1_alt,
- 'profile_name2_alt' => $profile_name2_alt,
- 'timezone' => $timezone
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_customers');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in billing_customers: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
}
} else {
$skipped++;
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($skipped) print "Skipped $skipped records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results=$inserted+$updated+$deleted;
return $results;
}
private function ImportDestinations($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$this->mustReload=true;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
printf("Importing destinations from %s for reseller %s:\n", $file, $reseller);
while ($buffer = fgets($fp, 1024)) {
$buffer=trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$gateway = trim($p[2]);
$domain = trim($p[3]);
$subscriber = trim($p[4]);
$dest_id = trim($p[5]);
$region = trim($p[6]);
$dest_name = trim($p[7]);
$increment = intval($p[8]);
$min_duration = intval($p[9]);
$max_duration = intval($p[10]);
$max_price = trim($p[11]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (!is_numeric($dest_id) && !strstr($dest_id, '@')) {
// skip invalid destinations
$skipped++;
continue;
}
if ($ops=="1") {
$query = sprintf(
"insert into destinations
(
reseller_id,
gateway,
domain,
subscriber,
dest_id,
region,
dest_name,
increment,
min_duration,
max_duration,
max_price
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($dest_id),
addslashes($region),
addslashes($dest_name),
addslashes($increment),
addslashes($min_duration),
addslashes($max_duration),
addslashes($max_price)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id,
- 'region' => $region,
- 'dest_name' => $dest_name,
- 'increment' => intval($increment),
- 'min_duration' => intval($min_duration),
- 'max_duration' => intval($max_duration),
- 'max_price' => floatval($max_price)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('destinations');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in destinations: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "3") {
$query = sprintf(
"delete from destinations
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and dest_id = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($dest_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('destinations');
- $mongo_match = array(
- 'gateway' => $gateway,
- 'reseller_id' => intval(reseller_id),
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array("safe" => $self->mongo_safe)
- );
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when deleting from destinations: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "2") {
$query = sprintf(
"select * from destinations
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and dest_id = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($dest_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update destinations set
region = '%s',
dest_name = '%s',
increment = '%s',
min_duration = '%s',
max_duration = '%s',
max_price = '%s'
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and dest_id = '%s'
",
addslashes($region),
addslashes($dest_name),
addslashes($increment),
addslashes($min_duration),
addslashes($max_duration),
addslashes($max_price),
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($dest_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$updated++;
}
- dprint($this->database_backend);
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match = array(
- 'gateway' => $gateway,
- 'reseller_id' => intval(reseller_id),
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id
- );
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id,
- 'region' => $region,
- 'dest_name' => $dest_name,
- 'increment' => intval($increment),
- 'min_duration' => intval($min_duration),
- 'max_duration' => intval($max_duration),
- 'max_price' => floatval($max_price)
- );
- $mongo_options = array(
- "upsert" => true,
- "safe" => $self->mongo_safe
- );
-
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('destinations');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when updating destinations: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into destinations
(
reseller_id,
gateway,
domain,
subscriber,
dest_id,
region,
dest_name,
increment,
min_duration,
max_duration,
max_price
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($dest_id),
addslashes($region),
addslashes($dest_name),
addslashes($increment),
addslashes($min_duration),
addslashes($max_duration),
addslashes($max_price)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'dest_id' => $dest_id,
- 'region' => $region,
- 'dest_name' => $dest_name,
- 'increment' => intval($increment),
- 'min_duration' => intval($min_duration),
- 'max_duration' => intval($max_duration),
- 'max_price' => floatval($max_price)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('destinations');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in destinations: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
}
} else {
$skipped++;
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($skipped) print "Skipped $skipped records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results = $inserted + $updated + $deleted;
return $results;
}
private function ImportDiscounts($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$this->mustReload=true;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
printf("Importing discounts from %s for reseller %s:\n", $file, $reseller);
while ($buffer = fgets($fp, 1024)) {
$buffer=trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$gateway = trim($p[2]);
$domain = trim($p[3]);
$subscriber = trim($p[4]);
$application = trim($p[5]);
$destination = trim($p[6]);
$region = trim($p[7]);
$connect = intval($p[8]);
$duration = intval($p[9]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (!is_numeric($destination) && !strstr($destination, '@')) {
// skip invalid destinations
$skipped++;
continue;
}
if ($ops == "1") {
$query = sprintf(
"insert into billing_discounts
(
reseller_id,
gateway,
domain,
subscriber,
application,
destination,
region,
connect,
duration
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($application),
addslashes($destination),
addslashes($region),
addslashes($connect),
addslashes($duration)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'application' => $application,
- 'destination' => $destination,
- 'region' => $region,
- 'connect' => intval($connect),
- 'duration' => intval($min_duration)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_discounts');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when inserting in billing_discounts: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "3") {
$query=sprintf(
"delete from billing_discounts
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and application = '%s'
and destination = '%s'
and region = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($application),
addslashes($destination),
addslashes($region)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_discounts');
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'application' => $application,
- 'destination' => $destination,
- 'region' => $region
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array("safe" => $self->mongo_safe)
- );
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when deleting from billing_discounts: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "2") {
$query = sprintf(
"select * from billing_discounts
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and application = '%s'
and destination = '%s'
and region = '%s'
",
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($application),
addslashes($destination),
addslashes($region)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update billing_discounts set
connect = '%s',
duration = '%s',
where gateway = '%s'
and reseller_id = '%s'
and domain = '%s'
and subscriber = '%s'
and application = '%s'
and destination = '%s'
and region = '%s'
",
addslashes($connect),
addslashes($duration),
addslashes($gateway),
addslashes($reseller_id),
addslashes($domain),
addslashes($subscriber),
addslashes($application),
addslashes($destination),
addslashes($region)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$updated++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match=array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'application' => $application,
- 'destination' => $destination,
- 'region' => $region
- );
- $mongo_data=array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'application' => $application,
- 'destination' => $destination,
- 'region' => $region,
- 'connect' => intval($connect),
- 'duration' => intval($min_duration)
- );
- $mongo_options = array(
- "upsert" => true,
- "safe" => $self->mongo_safe
- );
-
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_discounts');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when updating billing_discounts: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into billing_discounts
(
reseller_id,
gateway,
domain,
subscriber,
application,
destination,
region,
connect,
duration
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($gateway),
addslashes($domain),
addslashes($subscriber),
addslashes($application),
addslashes($destination),
addslashes($region),
addslashes($connect),
addslashes($duration)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data=array(
- 'reseller_id' => intval(reseller_id),
- 'gateway' => $gateway,
- 'domain' => $domain,
- 'subscriber' => $subscriber,
- 'application' => $application,
- 'destination' => $destination,
- 'region' => $region,
- 'connect' => intval($connect),
- 'duration' => intval($min_duration)
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_discounts');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in billing_discounts: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
}
} else {
$skipped++;
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($skipped) print "Skipped $skipped records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results = $inserted + $updated + $deleted;
return $results;
}
private function ImportProfiles($file, $reseller = 0)
{
if (!$file || !is_readable($file) || !$fp = fopen($file, "r")) return false;
$this->mustReload=true;
$i=0;
$inserted = 0;
$updated = 0;
$deleted = 0;
print "Importing Profiles:\n";
while ($buffer = fgets($fp, 1024)) {
$buffer=trim($buffer);
$p = explode($this->delimiter, $buffer);
$ops = trim($p[0]);
$profile = trim($p[2]);
$rate1 = trim($p[3]);
$hour1 = trim($p[4]);
$rate2 = trim($p[5]);
$hour2 = trim($p[6]);
$rate3 = trim($p[7]);
$hour3 = trim($p[8]);
$rate4 = trim($p[9]);
$hour4 = trim($p[10]);
if ($reseller) {
$reseller_id = intval($reseller);
} else {
$reseller_id = intval($p[1]);
}
if (!$hour1) $hour1=0;
if (!$hour2) $hour2=0;
if (!$hour3) $hour3=0;
if (!$hour4) $hour4=0;
if ($ops=="1") {
$query = sprintf(
"insert into billing_profiles
(
reseller_id,
name,
rate_name1,
hour1,
rate_name2,
hour2,
rate_name3,
hour3,
rate_name4,
hour4
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($profile),
addslashes($rate1),
addslashes($hour1),
addslashes($rate2),
addslashes($hour2),
addslashes($rate3),
addslashes($hour3),
addslashes($rate4),
addslashes($hour4)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $profile,
- 'rate_name1' => $rate1,
- 'hour1' => $hour1,
- 'rate_name2' => $rate2,
- 'hour2' => $hour2,
- 'rate_name3' => $rate3,
- 'hour3' => $hour3,
- 'rate_name4' => $rate4,
- 'hour4' => $hour4
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_profiles');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when inserting in billing_profiles: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
} elseif ($ops == "3") {
$query = sprintf(
"delete from billing_profiles
where name = '%s'
and reseller_id= '%s'
",
addslashes($profile),
addslashes($reseller_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$deleted++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_profiles');
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $name
- );
- $mongo_table_rw->remove(
- $mongo_match,
- array("safe" => $self->mongo_safe)
- );
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when deleting from billing_profiles: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} elseif ($ops == "2") {
$query = sprintf(
"select * from billing_profiles
where name = '%s'
and reseller_id= '%s'
",
addslashes($profile),
addslashes($reseller_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) {
$query = sprintf(
"update billing_profiles set
rate_name1 = '%s',
rate_name2 = '%s',
rate_name3 = '%s',
rate_name4 = '%s',
hour1 = '%s',
hour2 = '%s',
hour3 = '%s',
hour4 = '%s'
where name = '%s'
and reseller_id= '%s'
\n",
addslashes($rate1),
addslashes($rate2),
addslashes($rate3),
addslashes($rate4),
addslashes($hour1),
addslashes($hour2),
addslashes($hour3),
addslashes($hour4),
addslashes($profile),
addslashes($reseller_id)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$updated++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_match = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $profile
- );
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $profile,
- 'rate_name1' => $rate1,
- 'hour1' => $hour1,
- 'rate_name2' => $rate2,
- 'hour2' => $hour2,
- 'rate_name3' => $rate3,
- 'hour3' => $hour3,
- 'rate_name4' => $rate4,
- 'hour4' => $hour4
- );
-
- $mongo_options = array(
- "upsert" => true,
- "safe" => $self->mongo_safe
- );
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_profiles');
- $result = $mongo_table_rw->update($mongo_match, $mongo_data, $mongo_options);
- } catch (Exception $e) {
- $log=sprintf("Error: Mongo exception when updating billing_profiles: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- return false;
- }
- }
- }
} else {
$query = sprintf(
"insert into billing_profiles
(
reseller_id,
name,
rate_name1,
hour1,
rate_name2,
hour2,
rate_name3,
hour3,
rate_name4,
hour4
) values (
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)",
addslashes($reseller_id),
addslashes($profile),
addslashes($rate1),
addslashes($hour1),
addslashes($rate2),
addslashes($hour2),
addslashes($rate3),
addslashes($hour3),
addslashes($rate4),
addslashes($hour4)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows() >0) {
$inserted++;
} else {
$failed++;
}
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_rw) {
- $mongo_data = array(
- 'reseller_id' => intval(reseller_id),
- 'name' => $profile,
- 'rate_name1' => $rate1,
- 'hour1' => $hour1,
- 'rate_name2' => $rate2,
- 'hour2' => $hour2,
- 'rate_name3' => $rate3,
- 'hour3' => $hour3,
- 'rate_name4' => $rate4,
- 'hour4' => $hour4
- );
-
- try {
- $mongo_table_rw = $this->mongo_db_rw->selectCollection('billing_profiles');
- $mongo_table_rw->insert($mongo_data, array("safe" => $self->mongo_safe));
- } catch (Exception $e) {
- $log = sprintf("Error: Mongo exception when inserting in billing_profiles: %s", $e->getMessage());
- print $log;
- syslog(LOG_NOTICE, $log);
- }
- }
- }
}
}
$this->showImportProgress($file);
$i++;
}
if ($i) print "Read $i records\n";
if ($inserted) print "Inserted $inserted records\n";
if ($updated) print "Updated $updated records\n";
if ($deleted) print "Delete $deleted records\n";
$results = $inserted + $updated + $deleted;
return $results;
}
public function LoadRatingTables()
{
$log = sprintf(
"Memory usage: %0.2fMB, memory limit: %sB",
memory_get_usage() / 1024 / 1024,
ini_get('memory_limit')
);
syslog(LOG_NOTICE, $log);
$loaded['profiles'] = $this->LoadProfilesTable();
$loaded['ratesHistory'] = $this->LoadRatesHistoryTable();
$loaded['holidays'] = $this->LoadHolidaysTable();
$loaded['enumTlds'] = $this->LoadENUMtldsTable();
foreach (array_keys($loaded) as $_load) {
syslog(LOG_NOTICE, "Loaded $loaded[$_load] $_load into memory");
}
$log = sprintf(
"Memory usage: %0.2fMB, memory limit: %sB",
memory_get_usage() / 1024 / 1024,
ini_get('memory_limit')
);
syslog(LOG_NOTICE, $log);
return $loaded;
}
private function LoadENUMtldsTable()
{
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_ro) {
- // mongo backend
- try {
- $table = $this->mongo_db_ro->selectCollection('billing_enum_tlds');
- $cursor = $table->find()->slaveOkay();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught Mongo exception in LoadENUMtldsTable(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return 0;
- }
-
- $i=0;
- foreach ($cursor as $result) {
- if ($result['enum_tld']) {
- $i++;
- $_app=$result['application'];
- if (!$_app) $_app='audio';
-
- $_ENUMtlds[$result['enum_tld']] = array(
- "discount" => $result['discount'],
- "e164_regexp" => $result['e164_regexp']
- );
- }
- }
- $this->ENUMtlds = $_ENUMtlds;
- $this->ENUMtldsCount = $i;
- return $i;
- } else {
- $log = sprintf("<p>Error: mongo db is not initialized in LoadENUMtldsTable()");
- syslog(LOG_NOTICE, $log);
- return 0;
- }
- }
-
$query = "select * from billing_enum_tlds";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$i=0;
$rows=$this->db->num_rows();
while ($this->db->next_record()) {
if ($this->db->Record['enum_tld']) {
$i++;
$_app=$this->db->Record['application'];
if (!$_app) $_app='audio';
$_ENUMtlds[$this->db->Record['enum_tld']] = array(
"discount" => $this->db->Record['discount'],
"e164_regexp" => $this->db->Record['e164_regexp']
);
}
}
$this->ENUMtlds = $_ENUMtlds;
$this->ENUMtldsCount = $i;
return $i;
}
private function LoadRatesHistoryTable()
{
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_ro) {
- // mongo backend
- try {
- $table = $this->mongo_db_ro->selectCollection('billing_rates_history');
- $cursor = $table->find()->slaveOkay();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught Mongo exception in LoadRatesHistoryTable(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return 0;
- }
-
- $i=0;
- foreach ($cursor as $result) {
- $i++;
- if ($result['name'] && $result['destination']) {
- $i++;
- $_app=$result['application'];
- if (!$_app) $_app='audio';
-
- preg_match("/^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$/", $result['startDateTimestamp'], $m);
- $startDate = mktime($m[4], $m[5], $m[6], $m[2], $m[3], $m[1]);
- preg_match("/^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$/", $result['endDateTimestamp'], $m);
- $endDate = mktime($m[4], $m[5], $m[6], $m[2], $m[3], $m[1]);
-
- $_rates[$result['name']][$result['destination']][$_app][$result['id']] = array(
- "connectCost" => $result['connectCost'],
- "durationRate" => $result['durationRate'],
- "connectCostIn" => $result['connectCostIn'],
- "durationRateIn" => $result['durationRateIn'],
- "increment" => $result['increment'],
- "min_duration" => $result['min_duration'],
- "startDate" => $startDate,
- "endDate" => $endDate
- );
- }
- }
- $this->ratesHistory=$_rates;
- $this->ratesHistoryCount=$i;
- return $i;
- } else {
- $log = sprintf("<p>Error: mongo db is not initialized in LoadRatesHistoryTable()");
- syslog(LOG_NOTICE, $log);
- return 0;
- }
- }
-
$query = "select *,
UNIX_TIMESTAMP(startDate) as startDateTimestamp,
UNIX_TIMESTAMP(endDate) as endDateTimestamp
from billing_rates_history
order by name ASC,destination ASC,startDate DESC";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$i=0;
$rows=$this->db->num_rows();
while ($this->db->next_record()) {
if ($this->db->Record['name'] && $this->db->Record['destination']) {
$i++;
$_app = $this->db->Record['application'];
if (!$_app) $_app='audio';
$_rates[$this->db->Record['name']][$this->db->Record['destination']][$_app][$this->db->Record['id']]=
array(
"connectCost" => $this->db->Record['connectCost'],
"durationRate" => $this->db->Record['durationRate'],
"connectCostIn" => $this->db->Record['connectCostIn'],
"durationRateIn" => $this->db->Record['durationRateIn'],
"increment" => $this->db->Record['increment'],
"min_duration" => $this->db->Record['min_duration'],
"startDate" => $this->db->Record['startDateTimestamp'],
"endDate" => $this->db->Record['endDateTimestamp']
);
}
}
$this->ratesHistory = $_rates;
$this->ratesHistoryCount = $i;
return $i;
}
private function LoadProfilesTable()
{
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_ro) {
- // mongo backend
- try {
- $table = $this->mongo_db_ro->selectCollection('billing_profiles');
- $cursor = $table->find()->slaveOkay();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught Mongo exception in LoadProfilesTable(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return 0;
- }
-
- $i=0;
- foreach ($cursor as $result) {
- $i++;
- if ($result['name'] && $result['hour1'] > 0) {
- $_profiles[$result['name']] = array(
- "rate_name1" => $result['rate_name1'],
- "hour1" => $result['hour1'],
- "rate_name2" => $result['rate_name2'],
- "hour2" => $result['hour2'],
- "rate_name3" => $result['rate_name3'],
- "hour3" => $result['hour3'],
- "rate_name4" => $result['rate_name4'],
- "hour4" => $result['hour4'],
- );
- }
- }
- $this->profiles=$_profiles;
- return $i;
- } else {
- $log = sprintf("<p>Error: mongo db is not initialized in LoadProfilesTable()");
- syslog(LOG_NOTICE, $log);
- return 0;
- }
- }
-
$query = "select * from billing_profiles order by name";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$i=0;
while ($this->db->next_record()) {
$i++;
if ($this->db->Record['name'] && $this->db->Record['hour1'] > 0) {
$_profiles[$this->db->Record['name']]=
array(
"rate_name1" => $this->db->Record['rate_name1'],
"hour1" => $this->db->Record['hour1'],
"rate_name2" => $this->db->Record['rate_name2'],
"hour2" => $this->db->Record['hour2'],
"rate_name3" => $this->db->Record['rate_name3'],
"hour3" => $this->db->Record['hour3'],
"rate_name4" => $this->db->Record['rate_name4'],
"hour4" => $this->db->Record['hour4'],
);
}
}
$this->profiles=$_profiles;
return $i;
}
private function LoadHolidaysTable()
{
- if ($this->database_backend == 'mongo') {
- if ($this->mongo_db_ro) {
- // mongo backend
- try {
- $table = $this->mongo_db_ro->selectCollection('billing_holidays');
- $cursor = $table->find()->slaveOkay();
- } catch (Exception $e) {
- $log = sprintf("<p>Caught Mongo exception in LoadHolidaysTable(): %s", $e->getMessage());
- syslog(LOG_NOTICE, $log);
- return 0;
- }
-
- $i=0;
- foreach ($cursor as $result) {
- $i++;
- if ($result['day']) {
- $i++;
- $_holidays[$result['day']]++;
- }
- }
- $this->holidays=$_holidays;
- return $i;
- } else {
- $log = sprintf("<p>Error: mongo db is not initialized in LoadHolidaysTable()");
- syslog(LOG_NOTICE, $log);
- return 0;
- }
- }
-
$query="select * from billing_holidays order by day";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$i=0;
while ($this->db->next_record()) {
if ($this->db->Record['day']) {
$i++;
$_holidays[$this->db->Record['day']]++;
}
}
$this->holidays=$_holidays;
return $i;
}
public function checkRatingEngineConnection()
{
if ($this->settings['socketIPforClients'] && $this->settings['socketPort']
&& $fp = fsockopen($this->settings['socketIPforClients'], $this->settings['socketPort'], $errno, $errstr, 2)
) {
fclose($fp);
return true;
}
return false;
}
function showCustomers($filter)
{
return true;
foreach (array_keys($this->customers) as $key) {
if (strlen($filter)) {
if (preg_match("/$filter/", $key)) {
$customers = $customers.$key."\n";
}
} else {
$customers = $customers.$key."\n";
}
}
return $customers;
}
public function showProfiles()
{
foreach (array_keys($this->profiles) as $key) {
$profiles=$profiles.$key."\n";
}
return $profiles;
}
public function showENUMtlds()
{
foreach (array_keys($this->ENUMtlds) as $key) {
$ENUMtlds=$ENUMtlds.$key."\n";
}
return $ENUMtlds;
}
private function scanFilesForImport($dir)
{
$import_dirs[$this->cvs_import_dir] = array(
'path' => $this->cvs_import_dir,
'reseller' => 0
);
if ($handle = opendir($this->cvs_import_dir)) {
while (false !== ($filename = readdir($handle))) {
$reseller=0;
if ($filename == "." || $filename == "..") continue;
$fullPath = $this->cvs_import_dir."/".$filename;
if (is_dir($fullPath) && is_numeric($filename)) {
$reseller = $filename;
$import_dirs[$fullPath]=array(
'path' => $fullPath,
'reseller'=> $reseller
);
}
}
}
foreach (array_keys($import_dirs) as $_dir) {
if ($handle = opendir($_dir)) {
while (false !== ($filename = readdir($handle))) {
if ($filename != "." && $filename != "..") {
foreach ($this->importFilesPatterns as $_pattern) {
if (strstr($filename, $_pattern) && preg_match("/\.csv$/", $filename)) {
$fullPath = $_dir."/".$filename;
if ($content = file_get_contents($fullPath)) {
$watermark = $filename."-".md5($content);
if ($this->hasFileBeenImported($filename, $watermark)) {
$this->previously_imported_files++;
break;
}
$this->filesToImport[$filename] = array(
'name' => $filename,
'watermark' => $watermark,
'type' => $_pattern,
'path' => $fullPath,
'reseller' => $import_dirs[$_dir]['reseller']
);
}
break;
}
}
}
}
}
}
}
private function hasFileBeenImported($filename, $watermark)
{
$query = sprintf(
"select * from log where url = '%s'\n",
addslashes($watermark)
);
if ($this->db->query($query)) {
if ($this->db->num_rows()) {
$this->db->next_record();
/*
$log=sprintf ("File %s has already been imported at %s.\n",$filename,$this->db->f('date'));
syslog(LOG_NOTICE, $log);
print $log;
*/
return true;
} else {
return false;
}
} else {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
private function logImport($dir, $filename, $watermark, $results = 0, $reseller = 0)
{
$query = sprintf(
"insert into log (
date,
login,
ip,
url,
results,
description,
datasource,
reseller_id
) values (
NOW(),
'ImportScript',
'localhost',
'%s',
'%s',
'Imported %s',
'%s',
%d
)",
addslashes($watermark),
addslashes($results),
addslashes($filename),
addslashes($dir),
addslashes($reseller)
);
$log = sprintf(
"Imported file %s, %d records have been affected\n",
$filename,
$results
);
syslog(LOG_NOTICE, $log);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
function showImportProgress($filename = 'unspecified', $increment = 5000)
{
$this->importIndex++;
if ($this->importIndex == $increment) {
printf("Loaded %d records from %s\n", $this->importIndex, $filename);
flush();
$this->importIndex=0;
}
}
function createRatingTable($name)
{
if ($name) {
$table='billing_rates_'.$name;
} else {
$table='billing_rates_default';
}
$query = sprintf(
"create table %s select * from billing_rates where name = '%s'\n",
addslashes($table),
addslashes($name)
);
if ($this->db->query($query)) {
$query = sprintf(
"alter table %s add index rate_idx (name)",
addslashes($table)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
$query = sprintf(
"alter table %s add index destination_idx (destination)",
addslashes($table)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
printf("Created table %s\n", $table);
return true;
} else {
return false;
}
}
public function splitRatingTable()
{
$query = "select count(*) as c from billing_rates";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$this->db->next_record();
$rows=$this->db->f('c');
$query="select distinct(name) from billing_rates order by name ASC";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
while ($this->db->next_record()) {
$rate_names[]=$this->db->f('name');
}
foreach ($rate_names as $name) {
if (!$name) $name='default';
$table="billing_rates_".$name;
$query = sprintf("drop table if exists %s", addslashes($table));
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query = sprintf(
"create table %s select * from billing_rates where name = '%s'\n",
addslashes($table),
addslashes($name)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
} else {
$query = sprintf(
"alter table %s add index rate_idx (name)",
addslashes($table)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query = sprintf(
"alter table %s add index destination_idx (destination)",
addslashes($table)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query = sprintf("select count(*) as c from %s", addslashes($table));
$this->db->query($query);
$this->db->next_record();
$records=$this->db->f('c');
$created_records=$created_records+$records;
$progress=100*$created_records/$rows;
printf(
"Created table %s with %s records (%.1f %s)\n",
$table,
$records,
$progress,
'%'
);
}
}
return true;
}
public function updateTable()
{
global $auth;
$loginname=$auth->auth["uname"];
foreach ($this->web_elements as $_el) {
${$_el}= $_REQUEST[$_el];
}
if (!$table) return false;
if ($this->readonly) {
return true;
}
// Init table structure
if (!is_array($this->tables[$table]['exceptions'])) $this->tables[$table]['exceptions']=array();
if (!is_array($this->tables[$table]['keys'])) $this->tables[$table]['keys']=array();
if (!is_array($this->tables[$table]['fields'])) $this->tables[$table]['fields']=array();
$metadata = $this->db->metadata($table = "$table");
$cc = count($metadata);
// end init table structure
if ($web_task =="update") {
$affected_rows=0;
if ($subweb_task == "Update") {
if ($this->checkValues($table, $_REQUEST)) {
$update_set='';
$k=0;
while ($k < $cc) {
$k++;
$Fname=$metadata[$k]['name'];
if (!$Fname) continue;
$value=$_REQUEST[$Fname];
if ($this->tables[$table]['fields'][$Fname]['readonly']) {
continue;
}
if (in_array($Fname, $this->tables[$table]['exceptions'])) {
continue;
}
if (in_array($Fname, $this->tables[$table]['keys'])) {
continue;
}
if ($kkk > 0) {
$comma = ",";
} else {
$comma = "";
}
if (!$this->tables[$table]['skip_math'] && preg_match("/^([\+\-\*\/])(.*)$/", $value, $sign)) {
$update_set .= $comma.addslashes($Fname)."= ROUND(".addslashes($Fname). " ".$sign[1]. "'".$sign[2]."')";
} else {
$update_set .= $comma.addslashes($Fname)."='".addslashes($value)."'";
}
$kkk++;
}
$k=0;
while ($k < $cc) {
if ($metadata[$k]['name'] == 'change_date') {
$update_set .= sprintf("%s %s = NOW() ", $comma, addslashes($metadata[$k]['name']));
break;
}
$k++;
}
$log_entity=" id = $id ";
$where = sprintf(" id = '%s' and %s", addslashes($id), $this->whereResellerFilter);
if ($table == "billing_rates") {
if ($this->settings['split_rating_table']) {
$rate_table_affected = array();
$query_r = "select distinct (name) from billing_rates where". $where;
if ($this->db->query($query_r)) {
while ($this->db->next_record()) {
$rate_tables_affected[]='billing_rates_'.$this->db->f('name');
}
} else {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
} elseif ($table=="prepaid") {
register_shutdown_function("unLockTables", $this->db);
if ($this->db->query("lock table prepaid write")) {
$query_q = sprintf(
"select * from prepaid where account = '%s'",
addslashes($account)
);
if ($this->db->query($query_q) && $this->db->num_rows()) {
$this->db->next_record();
$old_balance=$this->db->f('balance');
}
$this->db->query("unlock tables");
}
}
$query = sprintf(
"update %s set %s where %s ",
addslashes($table),
$update_set,
$where
);
if ($this->db->query($query)) {
$affected_rows=$this->db->affected_rows();
if ($affected_rows) {
if ($table=="prepaid") {
list($username, $domain) = explode("@", $account);
$value=$balance-$old_balance;
if (floatval($balance) != floatval($old_balance)) {
$query = sprintf(
"insert into prepaid_history
(username,domain,action,description,value,balance,date,reseller_id)
values
('%s','%s','Set balance','Manual update','%s','%s',NOW(),%d)",
addslashes($username),
addslashes($domain),
addslashes($value),
addslashes($balance),
$this->CDRTool['filter']['reseller']
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
} elseif ($table=='billing_rates') {
if ($this->settings['split_rating_table']) {
foreach ($rate_tables_affected as $extra_rate_table) {
$query_u = sprintf(
"update %s set %s where %s ",
addslashes($extra_rate_table),
$update_set,
$where
);
if (!$this->db->query($query_u)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query_u,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
}
}
if (in_array($table, $this->requireReload)) {
if (!$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'")) {
printf(
"<font color=red>Database error: %s (%s)</font>",
$this->db->Error,
$this->db->Errno
);
}
}
}
} else {
printf(
"<font color=red>Database error for query '%s': %s (%s)</font>",
$query,
$this->db->Error,
$this->db->Errno
);
}
} else {
print "<p>Correct the values and try again.";
}
} elseif ($subweb_task == "Update selection") {
$k=0;
$kkk=0;
$update_set='';
while ($k < $cc) {
$k++;
$Fname=$metadata[$k]['name'];
$value=$_REQUEST[$Fname];
if (!strlen($value)) continue;
if ($this->tables[$table]['fields'][$Fname]['readonly']) {
continue;
}
if (in_array($Fname, $this->tables[$table]['exceptions'])) {
continue;
}
if (in_array($Fname, $this->tables[$table]['keys'])) {
continue;
}
if ($kkk > 0) {
$comma = ",";
} else {
$comma="";
}
if ($value == "NULL") {
$value="";
}
if (preg_match("/^([\+\-\*\/])(.*)$/", $value, $sign)) {
$update_set .= $comma.$Fname." = ROUND(".$Fname. " ".$sign[1]. "'".$sign[2]."')";
} else {
$update_set .= $comma.$Fname." = '".$value."'";
}
$kkk++;
}
$where = $this->whereResellerFilter;
if ($kkk) {
// reconstruct where clause to apply all changes to selection
// build where clause
// Search build for each field
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$table]['exceptions'])) {
$f_name="search_".$Fname;
$value=$_REQUEST[$f_name];
if (preg_match("/^([<|>]+)(.*)$/", $value, $likes)) {
$like=$likes[1];
$likewhat=$likes[2];
$quotes="";
} else {
$like="like";
$likewhat=$value;
$quotes="'";
}
if (strlen($value)) {
$where .= " and $Fname $like $quotes".$likewhat."$quotes";
$t++;
}
}
$j++;
}
if ($table == 'billing_rates') {
if ($this->settings['split_rating_table']) {
$rate_table_affected = array();
$query_r = "select distinct (name) from billing_rates where". $where;
if ($this->db->query($query_r)) {
while ($this->db->next_record()) {
$rate_tables_affected[] = 'billing_rates_'.$this->db->f('name');
}
} else {
printf(
"<font color=red>Database error: %s (%s)</font>",
$this->db->Error,
$this->db->Errno
);
}
}
}
$query = sprintf(
"update %s set %s where %s ",
addslashes($table),
$update_set,
$where
);
if ($this->db->query($query)) {
$affected_rows=$this->db->affected_rows();
if ($affected_rows) {
if ($table == 'billing_rates') {
if ($this->settings['split_rating_table']) {
foreach ($rate_tables_affected as $extra_rate_table) {
$query_u = sprintf(
"update %s set %s where %s ",
addslashes($extra_rate_table),
$update_set,
$where
);
if (!$this->db->query($query_u)) {
printf(
"<font color=red>Database error for %s: %s (%s)</font>",
$query_u,
$this->db->Error,
$this->db->Errno
);
}
}
}
}
if (in_array($table, $this->requireReload)) {
$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'");
}
}
} else {
printf("<font color=red>Database error: %s</font>", $this->db->Error);
}
}
} elseif ($subweb_task == "Delete selection") {
if ($confirmDelete) {
// reconstruct where clause to apply all changes to selection
// build where clause
// Search build for each field
$where = $this->whereResellerFilter;
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$table]['exceptions'])) {
$f_name="search_".$Fname;
$value=$_REQUEST[$f_name];
if (preg_match("/^([<|>]+)(.*)$/", $value, $likes)) {
$like = $likes[1];
$likewhat = $likes[2];
$quotes = "";
} else {
$like = "like";
$likewhat = $value;
$quotes = "'";
}
if (strlen($value)) {
$where .= " and $Fname $like $quotes".$likewhat."$quotes";
$t++;
}
}
$j++;
}
if ($table == 'billing_rates') {
if ($this->settings['split_rating_table']) {
$rate_table_affected=array();
$query_r = "select distinct (name) from billing_rates where". $where;
if ($this->db->query($query_r)) {
while ($this->db->next_record()) {
$rate_tables_affected[] = 'billing_rates_'.$this->db->f('name');
}
} else {
printf(
"<font color=red>Database error: %s (%s)</font>",
$this->db->Error,
$this->db->Errno
);
}
}
}
$query = sprintf(
"delete from %s where %s",
addslashes($table),
$where
);
if ($this->db->query($query)) {
$affected_rows = $this->db->affected_rows();
if ($affected_rows) {
if ($table == 'billing_rates') {
if ($this->settings['split_rating_table']) {
foreach ($rate_tables_affected as $extra_rate_table) {
$query_u = sprintf(
"delete from %s where %s ",
addslashes($extra_rate_table),
$where
);
if (!$this->db->query($query_u)) {
printf(
"<font color=red>Database error for %s: %s (%s)</font>",
$query_u,
$this->db->Error,
$this->db->Errno
);
}
}
}
}
if (in_array($table, $this->requireReload)) {
$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'");
}
}
} else {
printf(
"<font color=red>Database error: %s</font>",
$this->db->Error
);
}
unset($confirmDelete);
} else {
print "<p><font color=blue>";
print "Please confirm the deletion by pressing the Delete button again. ";
print "</font>";
print "<input type=hidden name=confirmDelete value=1>";
}
} elseif ($subweb_task == "Copy rate" && strlen($fromRate) && strlen($toRate)) {
$toRate=preg_replace("/%/", "", $toRate);
if ($confirmCopy) {
if ($toRate == 'history') {
$values = sprintf(
"(reseller_id,name,destination,application,connectCost,durationRate,connectCostIn,durationRateIn,startDate,endDate)
select
billing_rates.reseller_id,
'%s',
billing_rates.destination,
billing_rates.application,
billing_rates.connectCost,
billing_rates.durationRate,
billing_rates.connectCostIn,
billing_rates.durationRateIn,
NOW(),
NOW()
from billing_rates ",
addslashes($fromRate)
);
} else {
$values = sprintf(
"(reseller_id,name,destination,application,connectCost,durationRate,connectCostIn,durationRateIn)
select
billing_rates.reseller_id,
'%s',
billing_rates.destination,
billing_rates.application,
billing_rates.connectCost,
billing_rates.durationRate,
billing_rates.connectCostIn,
billing_rates.durationRateIn
from billing_rates ",
addslashes($toRate)
);
}
$where = $this->whereResellerFilter;
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$table]['exceptions'])) {
$f_name="search_".$Fname;
$value=$_REQUEST[$f_name];
if (preg_match("/^([<|>]+)(.*)$/", $value, $likes)) {
$like=$likes[1];
$likewhat=$likes[2];
$quotes="";
} else {
$like="like";
$likewhat=$value;
$quotes="'";
}
if (strlen($value)) {
$where .= sprintf(
" and %s %s %s%s%s ",
addslashes($Fname),
$like,
$quotes,
addslashes($likewhat),
$quotes
);
$t++;
}
}
$j++;
}
if ($toRate == 'history') {
$query="insert into billing_rates_history $values where $where";
} else {
$query="insert into billing_rates $values where $where";
}
if ($this->db->query($query)) {
$affected_rows=$this->db->affected_rows();
if ($affected_rows) {
print "$affected_rows rates copied. ";
if ($table == 'billing_rates') {
if ($this->settings['split_rating_table']) {
$query = sprintf(
"create table billing_rates_%s select * from billing_rates where %s ",
addslashes($toRate),
$where
);
if (!$this->db->query($query)) {
printf(
"<font color=red>Database error for %s: %s (%s)</font>",
$query,
$this->db->Error,
$this->db->Errno
);
}
}
}
if (in_array($table, $this->requireReload)) {
$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'");
}
}
if ($toRate == 'history') {
// Switch to history
$table = 'billing_rates_history';
// Init table structure
$this->tables[$table]['exceptions']= $this->tables[$table]['exceptions'];
$this->tables[$table]['keys'] = $this->tables[$table]['keys'];
$this->tables[$table]['fields'] = $this->tables[$table]['fields'];
$metadata = $this->db->metadata($table = "$table");
$cc = count($metadata);
// end init table structure
}
unset($confirmCopy);
} else {
printf("<font color=red>Database error: %s</font>", $this->db->Error);
}
$log_entity="rate=$toRate";
} else {
print "<p><font color=blue>";
print "Please confirm the copy of rate $fromRate to $toRate. ";
print "</font>";
}
} elseif ($subweb_task == "Insert") {
//print "<h3>Insert</h3>";
if ($this->checkValues($table, $_REQUEST)) {
$query=sprintf("insert into %s ( ", addslashes($table));
$k=1;
$kkk=0;
while ($k < $cc) {
$Fname=$metadata[$k]['name'];
if (!in_array($Fname, $this->tables[$table]['exceptions'])) {
if ($kkk > 0) {
$comma = ",";
} else {
$comma="";
}
$query .= $comma.addslashes($Fname);
$kkk++;
}
$k++;
}
$query .= ") values ( ";
$k=1;
$kkk=0;
while ($k < $cc) {
$Fname=$metadata[$k]['name'];
$value=$_REQUEST[$Fname];
if (!in_array($Fname, $this->tables[$table]['exceptions'])) {
if ($kkk > 0) {
$comma = ",";
} else {
$comma="";
}
if ($Fname == 'reseller_id' && $this->CDRTool['filter']['reseller']) {
$query .= $comma."'".addslashes($this->CDRTool['filter']['reseller'])."'";
} else {
$query .= $comma."'".addslashes($value)."'";
}
$kkk++;
}
$k++;
}
$query .= ") ";
$k=1;
while ($k < $cc) {
$Fname=$metadata[$k]['name'];
$value=$_REQUEST[$Fname];
if (in_array($Fname, $this->tables[$table]['keys'])) {
if ($value == "") {
$Fname_print_insert = substr($Fname, 4);
print "$Fname_print_insert = ???? <br>";
$empty_insert = 1;
}
}
$k++;
}
if (!$empty_insert) {
if ($this->db->query($query)) {
$affected_rows=$this->db->affected_rows();
if ($affected_rows) {
$this->db->query("select LAST_INSERT_ID() as lid");
$this->db->next_record();
$log_entity = sprintf("id=%s", $this->db->f('lid'));
if (in_array($table, $this->requireReload)) {
$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'");
}
}
} else {
printf(
"<font color=red>Database error for query %s: %s (%s)</font>",
$query,
$this->db->Error,
$this->db->Errno
);
}
} else {
print "<font color=red>
Error: The insert statement contains an empty key!
</font>
";
}
} else {
print "<p>Correct the values and try again.";
}
} elseif ($subweb_task == "Delete") {
if ($confirmDelete) {
$query = sprintf(
"delete from %s where id = '%s' and %s ",
addslashes($table),
addslashes($id),
addslashes($this->whereResellerFilter)
);
if ($this->db->query($query)) {
$affected_rows=$this->db->affected_rows();
if ($affected_rows && in_array($table, $this->requireReload)) {
$this->db->query("update settings set var_value= '1' where var_name = 'reloadRating'");
}
$log_entity = sprintf("id=%s", $id);
} else {
printf("<font color=red>Database error: %s</font>", $this->db->Error);
}
unset($confirmDelete);
} else {
$idForDeletion=$id;
print "<p><font color=blue>";
print "Please confirm the deletion by pressing the Delete button again. ";
print "</font>";
print "<input type=hidden name=confirmDelete value=1>";
}
} elseif ($subweb_task == "Delete session" && $sessionId && $table=='prepaid') {
$query = sprintf(
"select active_sessions from %s where id = %d and %s",
addslashes($table),
addslashes($id),
$this->whereResellerFilter
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
}
if (!$this->db->num_rows()) return;
$this->db->next_record();
if (strlen($this->db->f('active_sessions'))) {
// remove session
$active_sessions=array();
$old_active_sessions = json_decode($this->db->f('active_sessions'), true);
if (!count($old_active_sessions)) return;
foreach (array_keys($old_active_sessions) as $_key) {
if ($_key==$sessionId) continue;
$active_sessions[$_key]=$old_active_sessions[$_key];
}
} else {
$active_sessions=array();
}
$query = sprintf(
"update %s
set active_sessions = '%s',
session_counter = %d
where id = %d",
addslashes($table),
addslashes(json_encode($active_sessions)),
count($active_sessions),
addslashes($id)
);
if ($this->db->query($query)) {
return 1;
} else {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
print $log;
return 0;
}
}
if ($affected_rows && $table!="prepaid") {
$log_query = sprintf(
"insert into log
(date,login,ip,datasource,results,description,reseller_id)
values (NOW(),'%s','%s','Rating','%d','%s in table %s %s',%d)",
addslashes($loginname),
addslashes($_SERVER['REMOTE_ADDR']),
addslashes($affected_rows),
addslashes($subweb_task),
addslashes($table),
addslashes($log_entity),
addslashes($this->CDRTool['filter']['reseller'])
);
$this->db->query($log_query);
}
}
}
public function showTable()
{
$PHP_SELF=$_SERVER['PHP_SELF'];
foreach ($this->web_elements as $_el) {
${$_el}= $_REQUEST[$_el];
}
if ($this->table == 'prepaid_cards') {
print "<p>
<a href=prepaid_cards.phtml>Prepaid card generator</a>";
}
// Init table structure
if (!is_array($this->tables[$this->table]['exceptions'])) $this->tables[$this->table]['exceptions']=array();
if (!is_array($this->tables[$this->table]['keys'])) $this->tables[$this->table]['keys']=array();
if (!is_array($this->tables[$this->table]['fields'])) $this->tables[$this->table]['fields']=array();
if ($this->table=='prepaid' && strlen($_REQUEST['search_session_counter'])) {
$this->readonly=true;
}
if ($this->readonly) {
$this->tables[$this->table]['readonly']=1;
}
$metadata = $this->db->metadata($this->table);
$cc = count($metadata);
// end init table structure
//
// delimiter for exporting records
if ($this->settings['csv_delimiter']) {
$delimiter=$this->settings['csv_delimiter'];
} else {
$delimiter=",";
}
$query = sprintf(
"select count(*) as c from %s where %s",
addslashes($this->table),
$this->whereResellerFilter
);
$t=0;
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
$class=$metadata[$j]['class'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$f_name="search_".$Fname;
$value=$_REQUEST[$f_name];
if (preg_match("/^([<|>]+)(.*)$/", $value, $likes)) {
$like=$likes[1];
$likewhat=$likes[2];
$quotes="";
} else {
$like="like";
$likewhat=$value;
$quotes="'";
}
if (strlen($value)) {
$where .= sprintf(
" and %s %s %s%s%s ",
addslashes($Fname),
$like,
$quotes,
addslashes($likewhat),
$quotes
);
$t++;
}
}
$j++;
}
$query .= $where;
$this->db->query($query);
$this->db->next_record();
$rows=$this->db->Record['c'];
if (!$export) {
print "
<table border=0 align=center>
<tr><td colspan=\"2\">
";
if ($rows == 0) {
print "No records found. ";
} else {
print "$selectie $rows records found. ";
}
if ($this->settings['socketIPforClients'] && $this->settings['socketPort']) {
$engineAddress = $this->settings['socketIPforClients'].":".$this->settings['socketPort'];
if ($this->checkRatingEngineConnection()) {
print " | <span class=\"label label-success\">Rating engine running at $engineAddress</span>";
} else {
print " | <span class=\"label label-important\">Cannot connect to rating engine $engineAddress</span>";
}
}
print " | <a href=doc/RATING.txt target=rating_help>Rating documentation</a>";
print "
</td>
</tr> ";
if ($this->csv_import[$this->table]) {
print "<td style='text-align: center; padding-top:5px'>
<form class='form-inline' action=$PHP_SELF method='post' enctype='multipart/form-data'>
<input type=hidden name=import value=1>
";
printf(
"
<input type='hidden' name=table value=%s>
<input type='hidden' name='MAX_FILE_SIZE' value=1024000>
<div class='fileupload fileupload-new' style='display: inline-block; margin-bottom:0px' data-provides='fileupload'>
<div class='input-append'>
<div class='uneditable-input input-small'>
<span class='fileupload-preview'></span>
</div>
<span class='btn btn-file'>
<span class='fileupload-new'>Select file</span>
<span class='fileupload-exists'>Change</span>
<input type='file' name='%s'/></span>
<a href='#' class='btn fileupload-exists' data-dismiss='fileupload'>Remove</a>
<button type='submit' class='btn fileupload-exists' value=\"Import\"><i class='icon-upload'></i> Import</button>
</div>
</div>
",
$this->table,
$this->table
);
print "</form><td style='padding-top:5px'>
";
} else {
print "<td style='padding-top:5px; text-align: center' colspan=\"2\">";
}
print "<form class='form-inline' action=$PHP_SELF method=post target=export>
<input type=hidden name=export value=1>
";
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME="search_".$Fname;
$value=$_REQUEST[$SEARCH_NAME];
print "<input type=hidden name=search_$Fname value=\"$value\">";
}
$j++;
}
if ($this->table!=='prepaid_cards') {
printf(
"
<input type=hidden name=table value=%s>
<button class=btn type=submit value=\"Export %s\"><i class=icon-file></i> Export %s</button>
",
$this->table,
$this->csv_export[$this->table],
$this->csv_export[$this->table]
);
}
if ($this->settings['socketIPforClients'] && $this->settings['socketPort']) {
if ($ReloadRatingTables) {
reloadRatingEngineTables();
} else {
$this->db->query("select var_value from settings where var_name = 'reloadRating' and var_value='1'");
if ($this->db->num_rows()) {
print "<a class='btn btn-danger' href=rating_tables.phtml?ReloadRatingTables=1&table=$this->table>Reload rating tables</a>";
}
}
}
print "</form></td>
</tr>
</table>
";
} else {
$this->maxrowsperpage = 10000000;
}
if (!$next) {
$i=0;
$next=0;
} else {
$i=intval($next);
}
$j=0;
$z=0;
if ($rows > $this->maxrowsperpage) {
$maxrows = $this->maxrowsperpage + $next;
if ($maxrows > $rows) {
$maxrows=$rows;
$prev_rows=$maxrows;
}
} else {
$maxrows=$rows;
}
if (!$order && $this->tables[$this->table]['order']) {
$order = sprintf(
" order by %s ",
addslashes($this->tables[$this->table]['order'])
);
}
$query = sprintf(
"select * from %s where (1=1) %s and %s %s limit %d, %d",
addslashes($this->table),
$where,
$this->whereResellerFilter,
$order,
intval($i),
intval($this->maxrowsperpage)
);
$this->db->query($query);
$num_fields=$this->db->num_fields();
$k=0;
if (!$export) {
if ($this->table=='prepaid') {
print "
<table class='table-hover table table-condensed' id='rates_table' align=center width=100%>
<thead>
<tr>
<th></th>";
} else {
print "
<table class='table-hover table table-condensed table-striped' id='rates_table' align=center width=100%>
<thead>
<tr>
<th></th>
";
}
}
while ($k < $cc) {
$th = $metadata[$k]['name'];
if (!in_array($th, $this->tables[$this->table]['exceptions'])) {
if ($this->tables[$this->table]['fields'][$th]['name']) {
$th=$this->tables[$this->table]['fields'][$th]['name'];
} else {
$th=ucfirst($th);
}
if (!$export) {
print "<th>$th</th>";
} else {
if ($k) {
printf("%s%s", $delimiter, $th);
} else {
print "Ops";
}
}
$t_columns++;
}
$k++;
}
if ($export) {
print "\n";
}
if (!$export) {
print "
<th>Action</th>
</tr>";
$t_columns=$t_columns+2;
// SEARCH FORM
print "
<tr>
<td colspan=$t_columns>
Use _ to match one character and % to match any. Use > or <
to find greater or smaller values.</td>
</tr>
";
// Search form
print "
<form class='form-inline' style='display:none' action=$PHP_SELF method=post name=rating>
<input type=hidden name=web_task value=Search>
<tr>
<td>&nbsp;</td>";
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME = "search_".$Fname;
$value = $_REQUEST[$SEARCH_NAME];
if ($value != "") {
$selection_made=1;
}
$maxlength=$size;
if ($this->tables[$this->table]['fields'][$Fname]['size']) {
$field_size = $this->tables[$this->table]['fields'][$Fname]['size'];
} else {
$field_size = $el_size;
}
$class=$this->tables[$this->table]['fields'][$Fname]['class'];
if (!in_array($Fname, $this->tables[$this->table]['keys'])) {
if (!$class) {
$class = "span1";
}
print "<td><input class=$class type=text size=$field_size maxlength=$maxlength name=search_$Fname value=\"$value\"></td>";
} else {
print "<td></td>";
}
}
$j++;
}
printf(
"
<script type=\"text/JavaScript\">
function jumpMenu() {
location.href=\"%s?table=\" + document.rating.table.options[document.rating.table.selectedIndex].value;
}
</script>
",
$PHP_SELF
);
print "
<td>
";
print("<div class='input-append'><select class='span3' name='table' onChange=\"jumpMenu('this.form')\">\n");
$selected_table[$this->table]="selected";
foreach (array_keys($this->tables) as $tb) {
$sel_name=$this->tables[$tb]['name'];
print "<option value=$tb $selected_table[$tb]>$sel_name";
}
print "
</select><input class='btn btn-primary' type=submit name=subweb_task value=Search></div>
</form>";
print "
</td>
</tr></thead>
";
//print "
//<tr>
//<td colspan=$t_columns><hr noshade size=2></td>
//</tr>
//";
if ($selection_made && !$this->tables[$this->table]['readonly']) {
// Update all form
print "
<tr><td colspan=$t_columns>
Use + or - to add/substract from curent values.
Use * or / to multiply/divide curent values.</td>
</tr>";
$j=0;
print "
<form class='form-inline' action=$PHP_SELF method=post>
<input type=hidden name=web_task value=update>
<input type=hidden name=next value=$next>
<tr>
<td>&nbsp;</td>";
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if ($this->tables[$this->table]['fields'][$Fname]['size']) {
$field_size=$this->tables[$this->table]['fields'][$Fname]['size'];
} else {
$field_size=$el_size;
}
$class=$this->tables[$this->table]['fields'][$Fname]['class'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
if (!in_array($Fname, $this->tables[$this->table]['keys'])) {
if (!$class) {
$class="span1";
}
print "<td><input class='$class' type=text size=$field_size maxlength=$size name=$Fname></td>";
} else {
print "<td></td>";
}
}
$j++;
}
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME="search_".$Fname;
$value=$_REQUEST[$SEARCH_NAME];
print "<input type=hidden name=search_$Fname value=\"$value\">";
}
$j++;
}
if ($subweb_task=="Delete selection" && !$confirmDelete) {
print "<td>";
print "<input type=hidden name=confirmDelete value=1>";
print "<input class='btn btn-danger' type=submit name=subweb_task value=\"Delete selection\">";
print " ($rows records)";
} elseif (!$this->tables[$this->table]['readonly']) {
if ($this->table == "billing_rates" && strlen($_REQUEST['search_name'])) {
if ($subweb_task=="Copy rate" && !$confirmCopy) {
print "<td>";
print "<input type=hidden name=confirmCopy value=1>";
} else {
print "<td>";
print "<div class=\"btn-group\">
<input class='btn' type=submit name=subweb_task value=\"Update selection\">
<input class='btn btn-danger' type=submit name=subweb_task value=\"Delete selection\">
</div>
";
}
print "
<input type=submit name=subweb_task value=\"Copy rate\">";
printf(" id %s to", $_REQUEST['search_name']);
$query = sprintf(
"select distinct(name) as name
from billing_rates where
name like '%s'
order by name DESC
limit 1",
addslashes($_REQUEST['search_name'])
);
$this->db1->query($query);
$this->db1->next_record();
$_rateName = $this->db1->f('name');
$_rateName = preg_replace("/%/", "", $_rateName);
if (preg_match("/^(.*)_(\d+)$/", $_rateName, $m)) {
$_idx = $m[2] + 1;
$newRateName = $m[1]."_".$_idx;
} else {
$newRateName = $_rateName."_1";
}
printf(
"<input type=hidden name=fromRate value=\"%s\">",
$_REQUEST['search_name']
);
$selected_newtable[$toRate]='selected';
printf(
"<select name=toRate>
<option value=\"%s\" %s>Rate id %s
<option value=history %s>Rate history table
</select>",
$newRateName,
$selected_newtable[$newRateName],
$newRateName,
$selected_newtable['history']
);
} else {
print "<td>";
print "<div class=\"btn-group\">
<input class='btn' type=submit name=subweb_task value=\"Update selection\">
<input class='btn btn-danger' type=submit name=subweb_task value=\"Delete selection\">
</div>";
}
}
print "
<td>
<input type=hidden name=table value=$this->table>
<input type=hidden name=search_text value=\"$search_text\">
</td>
</tr></thead>
</form>
";
} elseif (!$this->tables[$this->table]['readonly']) {
// Insert form
$j=0;
print "
<form style='display:none' action=$PHP_SELF method=post>
<input type=hidden name=web_task value=update>
<input type=hidden name=next value=$next>
<tr>
<td>&nbsp; </td>
";
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if ($this->tables[$this->table]['fields'][$Fname]['size']) {
$field_size=$this->tables[$this->table]['fields'][$Fname]['size'];
} else {
$field_size=$el_size;
}
$class=$this->tables[$this->table]['fields'][$Fname]['class'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
if (!in_array($Fname, $this->tables[$this->table]['keys'])) {
if (!$class) {
$class='span1';
}
print "<td><input class='$class' type=text size=$field_size maxlength=$size name=$Fname></td>";
} else {
print "<td></td>";
}
}
$j++;
}
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME = "search_".$Fname;
$value = $_REQUEST[$SEARCH_NAME];
print "<input type=hidden name=search_$Fname value=\"$value\">";
}
$j++;
}
print "
<td>
<input type=hidden name=table value=\"$this->table\">
<input type=hidden name=search_text value=\"$search_text\">
<input class='btn btn-warning' type=submit name=subweb_task value=Insert>
</td>
</tr></thead>
</form>
";
//print "
//<tr>
//<td colspan=$t_columns><hr noshade size=2></td>
//</tr>
//";
}
}
while ($i < $maxrows) {
$this->db->next_record();
$id = $this->db->f('id');
$status = $this->db->f('status');
$found = $i+1;
if (!$export) {
print "
<form style='display:none' action=$PHP_SELF method=post>
<input type=hidden name=web_task value=update>
<input type=hidden name=next value=$next>
<input type=hidden name=id value=$id>
<tr>
";
if ($this->table == 'prepaid') {
$active_sessions = json_decode($this->db->f('active_sessions'), true);
if (!isset($active_sessions)) {
$active_sessions = array();
}
$account=$this->db->f('account');
$extraInfo="
<table border=0 bgcolor=#CCDDFF cellpadding=0 cellspacing=0>
<form action=$PHP_SELF method=post>
<input type=hidden name=web_task value=update>
<input type=hidden name=next value=$next>
<input type=hidden name=id value=$id>
<tr>
<td valign=top>
<table border=0>
";
$t=0;
foreach (array_keys($active_sessions) as $_session) {
$t++;
$maxsessiontime=$active_sessions[$_session]['MaxSessionTime'];
$extraInfo .= sprintf(
"<tr bgcolor=lightgrey><td class=border>%d. Session id</td><td>%s</td></tr>",
$t,
$_session
);
$duration = time() - $active_sessions[$_session]['timestamp'];
foreach (array_keys($active_sessions[$_session]) as $key) {
if ($key=='timestamp') {
$extraInfo .= sprintf(
"<tr><td class=border><b>StartTime</b></td><td>%s</td></tr>",
Date("Y-m-d H:i", $active_sessions[$_session]['timestamp'])
);
$extraInfo .= sprintf(
"<tr><td class=border><b>Progress</b></td><td>%s (%s s)</td></tr>",
sec2hms($duration),
$duration
);
} else {
$extraInfo .= sprintf(
"<tr><td class=border><b>%s</b></td><td>%s</td></tr>",
ucfirst($key),
$active_sessions[$_session][$key]
);
}
}
if ($maxsessiontime < $duration) {
$extraInfo .= sprintf(
"<tr>
<td class=border colspan=2><font color=red><b>Session expired since %d s</b></font></td>
</tr>",
$duration - $maxsessiontime
);
$extraInfo .= "<tr><td colspan=2><input type=submit name=subweb_task value='Delete session'></td></tr>";
}
//if (!$this->readonly) {
//}
}
$extraInfo.=sprintf(
"<input type=hidden name=table value='%s'>
<input type=hidden name=next value='%s'>
<input type=hidden name=sessionId value='%s'>
<input type=hidden name=search_text value='%s'>
</form>
</table>
</td>
</tr>
</table>",
$this->table,
$next,
$_session,
$search_text
);
}
print "<td>$found. </td>";
}
$j=0;
while ($j < $this->db->num_fields()) {
$value=$this->db->Record[$metadata[$j]['name']];
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
$class=$metadata[$j]['class'];
if ($this->tables[$this->table]['fields'][$Fname]['size']) {
$field_size=$this->tables[$this->table]['fields'][$Fname]['size'];
} else {
$field_size=$el_size;
}
$class=$this->tables[$this->table]['fields'][$Fname]['class'];
if ($this->tables[$this->table]['fields'][$Fname]['readonly']=="1") {
$extra_form_els = "disabled=true";
} else {
$extra_form_els = "";
}
$class=$this->tables[$this->table]['fields'][$Fname]['class'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
if (!$export) {
if (!in_array($Fname, $this->tables[$this->table]['keys']) && !$this->readonly) {
if ($this->table == 'prepaid' && $Fname == 'session_counter' && $value) {
if (count($active_sessions) > 1) {
$session_counter_txt = sprintf("%d sessions", $value);
} else {
$session_counter_txt = sprintf("%d session", $value);
}
printf(
"<td onClick=\"return toggleVisibility('row%s')\"><a href=#>%s</td>",
$found,
$session_counter_txt
);
} else {
if (!$class) {
$class="span1";
}
print "<td>
<input class='$class' type=text bgcolor=grey size=$field_size maxlength=$size name=$Fname value=\"$value\" $extra_form_els>
</td>";
}
} else {
if ($this->table == 'prepaid' && $Fname == 'session_counter' && $value) {
if (count($active_sessions) > 1) {
$session_counter_txt = sprintf("%d sessions", $value);
} else {
$session_counter_txt = sprintf("%d session", $value);
}
printf(
"<td onClick=\"return toggleVisibility('row%s')\"><a href=#>%s</td>",
$found,
$session_counter_txt
);
} else {
print "<td>$value</td>";
}
}
} else {
if ($j) {
printf("%s%s", $delimiter, $value);
} else {
print "2";
}
}
}
$j++;
}
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME = "search_".$Fname;
$value=$_REQUEST[$SEARCH_NAME];
if (!$export) {
print "<input type=hidden name=search_$Fname value=\"$value\">";
}
}
$j++;
}
if ($export) {
print "\n";
}
if (!$export) {
if (!$this->tables[$this->table]['readonly']) {
if ($subweb_task=="Delete" && $idForDeletion == $id && !$confirmDelete) {
print "<td class=border bgcolor=lightgrey>";
print "<input type=hidden name=confirmDelete value=1>";
print "<input type=submit name=subweb_task value=Delete>";
} else {
print "
<td class=border>
<div class=\"btn-group\">
<input class='btn' type=submit name=subweb_task value=Update>
<input class='btn btn-danger' type=submit name=subweb_task value=Delete></div>
";
print "<input type=hidden name=confirmDelete value=1>";
}
print "
<input type=hidden name=table value=$this->table>
<input type=hidden name=next value=$next>
<input type=hidden name=search_text value=\"$search_text\">
</td>
</tr>
</form>";
if ($extraInfo!='') {
print "
<tr style='display:none' id='row$found'>
<td></td>
<td colspan=$t_columns>$extraInfo</td>
</tr>
";
}
} else {
if ($this->table == 'prepaid') {
print "
<tr style='display:none' id='row$found'>
<td></td>
<td colspan=$t_columns>$extraInfo</td>
</tr>
";
}
}
}
$i++;
}
if (!$export) {
print "</form>
</table>
";
print "<form class=form-inline id=prev method=post>";
if ($next != 0) {
$show_next = $this->maxrowsperpage - $next;
if ($show_next < 0) {
$mod_show_next = $show_next - 2 * $show_next;
print "<input type=hidden name=next value=$mod_show_next>";
}
print "
<input style=\"display:none\" type=hidden name=maxrowsperpage value=$this->maxrowsperpage>
<input type=hidden name=web_task value=Search>
<input type=hidden name=table value=$this->table>
<input type=hidden name=search_text value=\"$search_text\">
";
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME="search_".$Fname;
$value=$_REQUEST[$SEARCH_NAME];
print "<input type=hidden name=search_$Fname value=\"$value\">
";
}
$j++;
}
}
print "
</form>
<form class=form-inline id=next method=post>
";
if ($rows>$this->maxrowsperpage && $rows!=$maxrows) {
$show_next = $this->maxrowsperpage + $next;
print "
<input type=hidden name=maxrowsperpage value=$this->maxrowsperpage>
<input type=hidden name=next value=$show_next>
<input type=hidden name=table value=$this->table>
<input type=hidden name=web_task value=Search>
";
$j=0;
while ($j < $cc) {
$Fname=$metadata[$j]['name'];
$size=$metadata[$j]['len'];
if (!in_array($Fname, $this->tables[$this->table]['exceptions'])) {
$SEARCH_NAME="search_".$Fname;
$value=$_REQUEST[$SEARCH_NAME];
print "<input type=hidden name=search_$Fname value=\"$value\">";
}
$j++;
}
print "
<input type=hidden name=search_text value=\"$search_text\">
";
}
print "
</form>
<ul class=\"pager\">";
if ($next!= 0) {
print "<li><a href=\"javascript:document.forms['prev'].submit()\">&larr; Previous</a></li>";
}
if ($rows>$this->maxrowsperpage && $rows!=$maxrows) {
print "<li><a href=\"javascript:document.forms['next'].submit()\">Next &rarr;</a></li>";
}
print "</ul>";
print "
</body>
</html>
";
}
}
private function checkValues($table, $values = array())
{
if (!$table) return false;
$metadata = $this->db->metadata($table);
if (!is_array($metadata)) return false;
$k=1;
while ($k < count($metadata)) {
$db_name = $metadata[$k]['name'];
$k++;
$web_name = $this->tables[$table]['fields'][$db_name]['name'];
$value = $values[$db_name];
$checkType = $this->tables[$table]['fields'][$db_name]['checkType'];
$mustExist = $this->tables[$table]['fields'][$db_name]['mustExist'];
if ($web_name) {
$name_print=$web_name;
} else {
$name_print=$db_name;
}
if ($mustExist) {
if (!strlen($value)) {
printf("Error: field '%s' must be filled in\n", $name_print);
return false;
}
}
if ($checkType) {
if (!strlen($value)) {
if (!$mustExist) continue;
}
if ($checkType == 'sip_account') {
if (!checkEmail($value)) {
printf(
"Error: value '%s' for field '%s' must be of format 'user@domain'\n",
$value,
$name_print
);
return false;
}
}
if ($checkType == 'domain') {
if (stristr($value, "-.") || !preg_match("/^([a-zA-Z0-9][a-zA-Z0-9-]*\.)+[a-zA-Z]{2,}$/i", $value)) {
printf(
"Error: value '%s' for field '%s' must be of format 'example.com'\n",
$value,
$name_print
);
return false;
}
}
if ($checkType == 'ip') {
if (!preg_match("/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i", $value, $m)) {
printf(
"Error: value '%s' for field '%s' must be of format 'X.X.X.X'\n",
$value,
$name_print
);
return false;
} else {
$i=1;
while ($i<=4) {
if ($m[$i] < 0 || $m[$i] > 255) {
printf(
"Error: value '%s' for field '%s' must be of a valid IP address\n",
$value,
$name_print
);
return false;
}
$i++;
}
}
}
if ($checkType == 'numeric') {
if (!is_numeric($value)) {
printf(
"Error: value '%s' for field '%s' must be of type '%s'\n",
$value,
$name_print,
$checkType
);
return false;
}
}
}
}
return true;
}
public function importTable($table = '')
{
// import a table from web
if (!is_array($_FILES[$table]) || $_FILES[$table]['size'] == 0) return false;
foreach ($this->importFilesPatterns as $_pattern) {
if (strstr($_FILES[$table]['name'], $_pattern) && preg_match("/\.csv$/", $_FILES[$table]['name'])) {
if ($this->CDRTool['filters']['reseller']) {
$dir=$this->cvs_import_dir.'/'.$this->CDRTool['filters']['reseller'];
if (!is_dir($dir)) {
if (!mkdir($dir)) {
printf("<font color=red>Error: cannot create directory %s</font>", $dir);
return false;
}
}
$fullPath=$this->cvs_import_dir.'/'.$this->CDRTool['filters']['reseller'].'/'.$_FILES[$table]['name'];
} else {
$fullPath=$this->cvs_import_dir.'/'.$_FILES[$table]['name'];
}
if (!is_file($fullPath)) {
if ($fp = fopen($fullPath, "w")) {
} else {
printf("<font color=red>Error: cannot open file %s for writing</font>", $fullPath);
return false;
}
} else {
list($basename, $extension) = explode('.', $_FILES[$table]['name']);
$j=0;
while (1) {
$j++;
if ($this->CDRTool['filters']['reseller']) {
$fullPath=$this->cvs_import_dir.'/'.$this->CDRTool['filters']['reseller'].'/'.$basename.'-'.$j.'.'.$extension;
} else {
$fullPath=$this->cvs_import_dir.'/'.$basename.'-'.$j.'.'.$extension;
}
if (is_file($fullPath)) continue;
if ($fp = fopen($fullPath, "w")) {
break;
} else {
printf("<font color=red>Error: cannot open file %s for writing</font>", $fullPath);
return false;
}
}
}
$content = fread(
fopen($_FILES[$table]['tmp_name'], "r"),
$_FILES[$table]['size']
);
fwrite($fp, $content);
fclose($fp);
printf(
"<p><font color=green>Imported %s bytes into %s</font>",
$_FILES[$table]['size'],
$fullPath
);
break;
}
}
}
}
class OpenSIPSQuota
{
var $localDomains = array();
var $quotaGroup = 'quota'; // group set if subscriber was blocked by quota
var $timeout = 5; // soap connection timeout
var $daily_quota = 0; // by default do not check daily quota
public function OpenSIPSQuota($parent)
{
global $DATASOURCES;
$this->CDRdb = $parent->CDRdb;
$this->table = $parent->table;
$this->CDRTool = $parent->CDRTool;
$this->cdr_source = $parent->cdr_source;
$this->path=$this->CDRTool['Path'];
$this->db_subscribers = $parent->db_subscribers;
if (!class_exists($this->db_subscribers)) {
printf("Info: No database defined for SIP accounts for source '%s'.\n", $this->cdr_source);
return false;
}
$this->AccountsDB = new $this->db_subscribers;
$this->enableThor = $parent->enableThor;
$parent->LoadDomains();
$this->localDomains = $parent->localDomains;
$this->cdr_source = $parent->cdr_source;
$this->BillingPartyIdField = $parent->CDRFields['BillingPartyId'];
$this->parent = $parent;
$this->db = new DB_cdrtool;
$this->db->Halt_On_Error="no";
$this->db1 = new DB_cdrtool;
$this->db1->Halt_On_Error="no";
$this->db1 = new DB_cdrtool;
$this->db1->Halt_On_Error="no";
$this->CDRS = $parent;
$this->quota_init_flag = $parent->quota_init_flag;
$this->quota_reset_flag = $parent->quota_reset_flag;
if ($parent->daily_quota && is_numeric($parent->daily_quota) && $parent->daily_quota > 1 && $parent->daily_quota < 100) {
$this->daily_quota = $parent->daily_quota;
}
// load e-mail addresses for quota notifications
$query = "select * from settings where var_module = 'notifications'";
if ($this->db->query($query) && $this->db->num_rows()) {
while ($this->db->next_record()) {
$_bp = $this->db->f('billing_party');
$_name = $this->db->f('var_name');
$_value = $this->db->f('var_value');
if ($_bp && $_name && $_value) {
$this->notificationAddresses[$_bp][$_name]=$_value;
}
}
}
if ($DATASOURCES[$this->cdr_source]['soapEngineId']) {
require("/etc/cdrtool/ngnpro_engines.inc");
require_once("ngnpro_soap_library.php");
if (in_array($DATASOURCES[$this->cdr_source]['soapEngineId'], array_keys($soapEngines))) {
$this->SOAPurl = $soapEngines[$DATASOURCES[$this->cdr_source]['soapEngineId']]['url'];
$log = sprintf(
"Using SOAP engine %s to block accounts at %s\n",
$DATASOURCES[$this->cdr_source]['soapEngineId'],
$this->SOAPurl
);
syslog(LOG_NOTICE, $log);
$this->SOAPlogin = array(
"username" => $soapEngines[$DATASOURCES[$this->cdr_source]['soapEngineId']]['username'],
"password" => $soapEngines[$DATASOURCES[$this->cdr_source]['soapEngineId']]['password'],
"admin" => true
);
$this->SoapAuth=array('auth', $this->SOAPlogin , 'urn:AGProjects:NGNPro', 0, '');
$this->soapclient = new WebService_NGNPro_SipPort($this->SOAPurl);
$this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
$this->soapclient->_options['timeout'] = $this->timeout;
} else {
$e = $DATASOURCES[$this->cdr_source]['soapEngineId'];
$log = "Error: soap engine id $e not found in /etc/cdrtool/ngnpro_engines.inc\n";
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
} else {
$log = "Using database queries to block accounts\n";
syslog(LOG_NOTICE, $log);
}
}
function ShowAccountsWithQuota($treshhold = '')
{
$query = sprintf(
"select * from quota_usage where datasource = '%s' and quota > 0 and cost > 0",
addslashes($this->CDRS->cdr_source)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
while ($this->db->next_record()) {
if ($this->db->f('blocked')) {
$blockedStatus="blocked";
} else {
$blockedStatus='';
}
$usageRatio = $this->db->f('cost') * 100 / $this->db->f('quota');
if ($treshhold && $treshhold > $usageRatio) continue;
$usageStatus = sprintf("usage=%-10s", $this->db->f('cost'));
printf(
"%-35s quota=%-6s %s %.2f%s %s\n",
$this->db->f('account'),
$this->db->f('quota'),
$usageStatus,
$usageRatio,
'%',
$blockedStatus
);
}
}
public function deblockAccounts($reset_quota_for = array())
{
// deblock users blocked by quota
if (!$this->db_subscribers) {
print("Info: No database defined for SIP accounts.\n");
return false;
}
if (!count($reset_quota_for)) {
printf("Deblocking all SIP accounts blocked by quota\n");
} else {
printf("Deblocking %d SIP accounts blocked by quota\n", count($reset_quota_for));
}
if ($this->enableThor) {
$query = sprintf("select username, domain, profile from sip_accounts where (1=1) ");
if (count($reset_quota_for)) {
$k=0;
foreach ($reset_quota_for as $_account) {
if ($k) $usage_keys.= ", ";
$usage_keys.="'".addslashes($_account)."'";
$k++;
}
$query.= "and CONCAT(username,'@',domain) in (".$usage_keys.")";
}
if (!$this->AccountsDB->query($query)) {
$log = sprintf("Error: %s (%s)", $this->AccountsDB->Error, $this->AccountsDB->Errno);
syslog(LOG_NOTICE, $log);
return false;
}
while ($this->AccountsDB->next_record()) {
$i++;
$_account=$this->AccountsDB->f('username')."@".$this->AccountsDB->f('domain');
$_profile=json_decode(trim($this->AccountsDB->f('profile')));
if (in_array('quota', $_profile->groups)) {
$blockedAccounts[]=$_account;
}
if ($i%5000 == 0) {
print "$i accounts checked for deblocking\n";
flush();
}
}
if ($i) {
print "$i accounts checked for deblocking\n";
flush();
}
} else {
$query = sprintf(
"select CONCAT(username,'@',domain) as account from grp where grp = '%s'",
addslashes($this->quotaGroup)
);
if (count($reset_quota_for)) {
$k=0;
foreach ($reset_quota_for as $_account) {
if ($k) $usage_keys.= ", ";
$usage_keys .= "'".addslashes($_account)."'";
$k++;
}
$query.= "and CONCAT(username,'@',domain) in (".$usage_keys.")";
}
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%s)",
$this->AccountsDB->Error,
$this->AccountsDB->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$blockedAccounts=array();
while ($this->AccountsDB->next_record()) {
$i++;
$blockedAccounts[]=$this->AccountsDB->f('account');
if ($i%10000 == 0) {
print "$i accounts checked for deblocking\n";
flush();
}
}
}
if (count($reset_quota_for)) {
$blockedAccounts = array_intersect($blockedAccounts, $reset_quota_for);
}
if (count($blockedAccounts) >0) {
$this->unBlockRemoteAccounts($blockedAccounts);
if (!$this->enableThor) {
$query = sprintf("delete from grp where grp = '%s'", $this->quotaGroup);
if (count($reset_quota_for)) {
$k=0;
foreach ($reset_quota_for as $_account) {
if ($k) $usage_keys.= ", ";
$usage_keys.="'".addslashes($_account)."'";
$k++;
}
$query.= "and CONCAT(username,'@',domain) in (".$usage_keys.")";
}
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%s)",
$this->AccountsDB->Error,
$this->AccountsDB->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
}
if (count($blockedAccounts)) {
$log = sprintf(
"Reset %d users blocked by quota\n",
count($blockedAccounts)
);
print $log;
syslog(LOG_NOTICE, $log);
}
}
private function initQuotaUsageFromDatabase($month = "", $reset_quota_for = array())
{
if (!$month) {
$this->startTime=Date("Y-m-01 00:00", time());
} else {
$this->startTime=$month."-01 00:00";
}
$j=0;
$usage_keys='';
if (count($reset_quota_for)) {
$log = sprintf(
"Init quota of data source %s for %d accounts\n",
addslashes($this->CDRS->cdr_source),
count($reset_quota_for)
);
print $log;
syslog(LOG_NOTICE, $log);
$k=0;
foreach ($reset_quota_for as $_account) {
if ($k) $usage_keys.= ", ";
$usage_keys.="'".addslashes($_account)."'";
$k++;
}
$usage_keys="and ".addslashes($this->BillingPartyIdField). " in (".$usage_keys.")";
} else {
if (count($this->localDomains)) {
$domain_filter="and Realm in (";
$t=0;
foreach (array_keys($this->localDomains) as $_domain) {
if (!$_domain) continue;
if ($t) $domain_filter .= ",";
$domain_filter .= sprintf("'%s'", addslashes($_domain));
$t++;
}
$domain_filter .= ") ";
}
$log = sprintf(
"Init quota of data source %s for all accounts\n",
$this->CDRS->cdr_source
);
print $log;
syslog(LOG_NOTICE, $log);
}
$query = sprintf(
"select %s,
count(*) as calls,
sum(AcctSessionTime) as duration,
sum(Price) as cost,
sum(AcctInputOctets + AcctOutputOctets)/2 as traffic
from %s
where AcctStartTime >= '%s'
and Normalized = '1'
%s
%s
group by %s\n",
addslashes($this->BillingPartyIdField),
addslashes($this->table),
addslashes($this->startTime),
$domain_filter,
$usage_keys,
addslashes($this->BillingPartyIdField)
);
if (!$this->CDRdb->query($query)) {
if ($this->CDRdb->Errno != 1146) {
$log = sprintf(
"Database error: %s (%s)",
$this->CDRdb->Error,
$this->CDRdb->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
$rows = $this->CDRdb->num_rows();
$log = sprintf(
"%d callers generated traffic in %s for data source %s\n",
$rows,
Date("Y-m", time()),
$this->CDRS->cdr_source
);
print $log;
flush();
syslog(LOG_NOTICE, $log);
$j=0;
$progress=0;
while ($this->CDRdb->next_record()) {
if ($rows > 1000) {
if ($j > $progress * $rows/100) {
$progress++;
if ($progress % 10 == 0) {
print "$progress% ";
flush();
}
}
}
unset($accounts);
$accounts[$this->CDRdb->f($this->BillingPartyIdField)]['usage']['calls'] = $this->CDRdb->f('calls');
$accounts[$this->CDRdb->f($this->BillingPartyIdField)]['usage']['duration'] = $this->CDRdb->f('duration');
$accounts[$this->CDRdb->f($this->BillingPartyIdField)]['usage']['cost'] = $this->CDRdb->f('cost');
$accounts[$this->CDRdb->f($this->BillingPartyIdField)]['usage']['traffic'] = $this->CDRdb->f('traffic');
$accounts[$this->CDRdb->f($this->BillingPartyIdField)]['usage']['cost_today'] = 0;
$this->CDRS->cacheQuotaUsage($accounts);
$j++;
}
}
public function checkQuota($notify)
{
global $UserQuota;
$this->initQuotaUsage();
$query = sprintf(
"select * from quota_usage where datasource = '%s' and quota > 0 and (cost > quota or cost_today >= quota * $this->daily_quota/100)",
addslashes($this->CDRS->cdr_source)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$toNotify=array();
$_checks=0;
while ($this->db->next_record()) {
$account=$this->db->f('account');
list($username, $domain)=explode("@", $account);
if ($this->db->f('cost') >= $this->db->f('quota')) {
$quota_exceeded = true;
$exceeded_period = 'monthly';
} elseif ($this->daily_quota && ($this->db->f('cost_today') >= $this->db->f('quota') * $this->daily_quota/100)) {
$quota_exceeded = true;
$exceeded_period = 'daily';
} else {
$quota_exceeded = false;
}
if ($quota_exceeded) {
$exceeding_accounts++;
if (!$this->db->f('blocked')) {
$reason='Cost exceeded';
if (!$seen_title) {
$line = sprintf(
"%40s %6s %8s %8s %13s %s\n",
"User",
"Calls",
"Price",
"Minutes",
"Traffic",
"Reason"
);
print $line;
$email_body=$line;
$seen_title++;
}
$line = sprintf(
"%40s %6s %8s %8s %10s MB %s\n",
$account,
$this->db->f('calls'),
$this->db->f('cost'),
number_format($this->db->f('duration') / 60, 0, "", ""),
number_format($this->db->f('traffic') / 1024 / 1024, 2),
$reason
);
$email_body = $email_body.$line;
print $line;
if ($this->enableThor) {
$this->domain_table = "sip_domains";
} else {
$this->domain_table = "domain";
}
$query = sprintf(
"select * from %s where domain = '%s'",
addslashes($this->domain_table),
addslashes($domain)
);
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%d) %s\n",
$this->AccountsDB->Error,
$this->AccountsDB->Errno,
$query
);
syslog(LOG_NOTICE, $log);
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_reseller = $this->AccountsDB->f('reseller_id');
} else {
$_reseller = 0;
}
$log = sprintf(
"%s quota exceeded for %s (%s > %s)",
ucfirst($exceeded_period),
$account,
$this->db->f('cost'),
$this->db->f('quota')
);
syslog(LOG_NOTICE, $log);
$log_query = sprintf(
"insert into log
(date,login,ip,datasource,results,description,reseller_id)
values (NOW(),'quotacheck','localhost','QuotaCheck','1','%s',%d)",
addslashes($log),
$_reseller
);
if (!$this->db1->query($log_query)) {
$log = sprintf(
"Database error: %s (%s)",
$this->db1->Error,
$this->db1->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
}
if ($this->blockAccount($account)) {
if ($notify) {
$toNotify[]=$account;
}
$blocked_now++;
$blockedAccountsNow=$blockedAccountsNow.$account."\n";
}
} else {
$blockedAccountsPrevious=$blockedAccountsPrevious.$account."\n";
$blocked_previous++;
}
}
$_checks++;
}
if ($exceeding_accounts) {
$line = sprintf("%6d accounts have exceeded their traffic limits\n", $exceeding_accounts);
print $line;
$email_body=$email_body.$line;
} else {
$log=sprintf("No quota has been exceeded\n");
syslog(LOG_NOTICE, $log);
}
if ($blocked_now) {
$line = sprintf("%6d accounts have been blocked now\n", $blocked_now);
$email_body=$email_body.$line;
}
if ($blockedAccountsNow) {
$line = "Blocked accounts now:\n".$blockedAccountsNow;
print $line;
$email_body=$email_body.$line.$batch_block;
}
if ($blockedAccountsPrevious) {
$line = "Blocked acccounts previously:\n".$blockedAccountsPrevious;
print $line;
$email_body=$email_body.$line.$batch_unblock;
}
// send notification to the provider
if ($this->CDRTool['provider']['toEmail'] && $blockedAccountsNow) {
$from = $this->CDRTool['provider']['fromEmail'];
$to = $this->CDRTool['provider']['toEmail'];
$bcc = $this->CDRTool['provider']['bccEmail'];
$service = $this->CDRTool['provider']['service'];
if (!$service) $service = "SIP";
if ($from) $extraHeaders="From: $from\r\nBCC: $from";
if ($bcc) $extraHeaders=$extraHeaders.",".$bcc;
print("Notify CDRTool provider at $to\n");
mail($to, "$service platform - CDRTool quota check", $email_body, $extraHeaders);
}
if ($notify && is_array($toNotify) && count($toNotify) >0) {
// send notification to accounts
foreach ($toNotify as $rcpt) {
$this->notify($rcpt);
}
}
}
function notify($account)
{
global $DATASOURCES;
list($username, $domain) = explode("@", $account);
if (!$DATASOURCES[$this->cdr_source]['UserQuotaNotify']) {
return false;
}
// get account information
if ($this->enableThor) {
$query = sprintf(
"select first_name,last_name,email,profile from sip_accounts where username = '%s' and domain = '%s'",
addslashes($username),
addslashes($domain)
);
} else {
$query = sprintf(
"select first_name,last_name,email_address as email,profile from subscriber where username = '%s' and domain = '%s'",
addslashes($username),
addslashes($domain)
);
}
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%s)",
$this->AccountsDB->Error,
$this->AccountsDB->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
if (!$this->AccountsDB->num_rows()) return false;
$this->AccountsDB->next_record();
$fullname = $this->AccountsDB->f('first_name')." ".$this->AccountsDB->f('last_name');
$toEmail = $this->AccountsDB->f('email');
$profile = json_decode($this->AccountsDB->f('profile'), true);
$providerName=$this->notificationAddresses[$domain]['providerName'];
if (!$providerName) $providerName="your SIP service provider";
$body = sprintf(
"Dear __NAME__,\n\n".
"Your SIP account %s has been temporarily blocked\n".
"because your monthly quota has been exceeded.\n\n".
"To unblock your account you may contact %s.\n\n".
"N.B. This is an automatically generated message. Do not reply to it.\n",
$account,
$providerName
);
$fromEmail = $this->CDRTool['provider']['fromEmail'];
$bccEmail = $this->CDRTool['provider']['bccEmail'];
$seen_bcc[$bccEmail]++;
if ($this->notificationAddresses[$domain]['fromEmail']) {
$fromEmail=$this->notificationAddresses[$domain]['fromEmail'];
}
if ($this->notificationAddresses[$domain]['quotaBody']) {
$body=$this->notificationAddresses[$domain]['quotaBody'];
}
if ($this->notificationAddresses[$domain]['quotaSubject']) {
$subject=$this->notificationAddresses[$domain]['quotaSubject'];
}
$body = preg_replace("/__NAME__/", $fullname, $body);
$body = preg_replace("/__ACCOUNT__/", $account, $body);
$body = preg_replace("/__CALLERID__/", "$profile[rpid]", $body);
if (!$subject) {
$subject=sprintf("Monthly quota exceeded for account %s", $account);
} else {
$subject=preg_replace("/__ACCOUNT__/", $account, $subject);
$subject=preg_replace("/__CALLERID__/", "$profile[rpid]", $subject);
}
if (!$toEmail || !$fromEmail) {
return false;
}
$seen_bcc[$toEmail]++;
$extraHeaders="From: $fromEmail";
if ($this->notificationAddresses[$domain][bccEmail]) {
if ($bccEmail) $bccEmail.= ",";
$bccEmail.=$this->notificationAddresses[$domain][bccEmail];
}
if ($bccEmail) $extraHeaders = $extraHeaders."\r\nBCC: ".$bccEmail;
mail($toEmail, $subject, $body, $extraHeaders);
$log_msg = sprintf(
"Monthly quota exceeded for %s. Notified To:%s From:%s\n",
$account,
$toEmail,
$fromEmail
);
syslog(LOG_NOTICE, $log_msg);
print $log_msg;
}
function blockAccount($account)
{
list($username, $domain) = explode("@", $account);
if (is_object($this->soapclient)) {
return $this->blockAccountRemote($account);
} else {
$query = sprintf(
"insert into grp
(username,domain,grp,last_modified)
values
('%s','%s','%s',NOW())",
addslashes($username),
addslashes($domain),
addslashes($this->quotaGroup)
);
if (!$this->AccountsDB->query($query)) {
if ($this->AccountsDB->Errno != 1062) {
$log = sprintf(
"Database error: %s (%s)",
$this->AccountsDB->Error,
$this->AccountsDB->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
} else {
return true;
}
} else {
$this->markBlocked($account);
return true;
}
}
}
function blockAccountRemote($account)
{
list($username, $domain) = explode("@", $account);
if (!$username || !$domain) {
$log = sprintf("Error: misssing username/domain in blockAccountRemote()");
syslog(LOG_NOTICE, $log);
return false;
}
$this->soapclient->addHeader($this->SoapAuth);
$result = $this->soapclient->addToGroup(array("username" => $username,"domain"=> $domain), "quota");
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
$log = sprintf(
"Error from %s: %s (%s)",
$this->SOAPurl,
$error_fault->faultstring,
$error_fault->faultcode
);
syslog(LOG_NOTICE, $log);
print $log;
if ($error_fault->detail->exception->errorcode != "1030") {
$from = $this->CDRTool['provider']['fromEmail'];
$to = $this->CDRTool['provider']['toEmail'];
$extraHeaders = "From: $from";
$email_body = "Remote SOAP request failure when calling blockAccountRemote(): \n\n".
$log;
mail($to, "CDRTool SOAP client failure", $email_body, $extraHeaders);
}
return false;
} else {
$log = sprintf("Block account %s at %s", $account, $this->SOAPurl);
syslog(LOG_NOTICE, $log);
$this->markBlocked($account);
return true;
}
}
function unBlockRemoteAccounts($accounts)
{
if (!is_object($this->soapclient)) {
return;
}
foreach ($accounts as $account) {
list($username, $domain)=explode("@", $account);
if (!$username || !$domain) return true;
$this->soapclient->addHeader($this->SoapAuth);
$result = $this->soapclient->removeFromGroup(array("username" => $username,"domain"=> $domain), "quota");
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault = $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode
&& $error_fault->detail->exception->errorcode != "1030"
&& $error_fault->detail->exception->errorcode != "1031"
) {
$from = $this->CDRTool[provider][fromEmail];
$to = $this->CDRTool[provider][toEmail];
$extraHeaders="From: $from";
$email_body="SOAP request failure: \n\n".
$log = sprintf(
"SOAP client error: %s %s\n",
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
syslog(LOG_NOTICE, $log);
mail($to, "CDRTool SOAP failure", $email_body, $extraHeaders);
}
} else {
$log = sprintf("Unblock remote account %s at %s", $account, $this->SOAPurl);
syslog(LOG_NOTICE, $log);
}
}
}
function saveQuotaInitFlag()
{
$query = sprintf("insert into memcache (`key`,`value`) values ('%s','1')", addslashes($this->quota_init_flag));
if (!$this->db->query($query)) {
if ($this->db->Errno != '1062') {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
return true;
}
function deleteQuotaInitFlag()
{
$query = sprintf(
"delete from memcache where `key` in ('%s','%s')",
addslashes($this->quota_init_flag),
addslashes($this->quota_reset_flag)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
return true;
}
function deleteQuotaUsageFromCache ($reset_quota_for=array())
{
$query = sprintf(
"delete from quota_usage where datasource = '%s' ",
addslashes($this->CDRS->cdr_source)
);
if (count($reset_quota_for)) {
$query.= " and account in (";
$t=0;
foreach ($reset_quota_for as $_account) {
if ($t) $query.=",";
$query.= sprintf("'%s'", $_account);
$t++;
}
$query.=")";
}
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->affected_rows()) {
$log = sprintf("Deleted %d keys from cache\n", $this->db->affected_rows());
print $log;
syslog(LOG_NOTICE, $log);
}
return true;
}
private function initQuotaUsage()
{
$query = sprintf(
"select value from memcache where `key` = '%s'",
addslashes($this->quota_init_flag)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
if ($this->db->num_rows()) return true;
$lockName = sprintf("%s:%s", $this->CDRS->cdr_source, $this->CDRS->table);
if (!$this->CDRS->getNormalizeLock($lockName)) {
$log = "Error: cannot initialize now the quota because a normalization process in progress\n";
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$query = sprintf(
"select value from memcache where `key` = '%s'",
addslashes($this->quota_reset_flag)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
$reset_quota_for= array();
if ($this->db->num_rows()) {
$this->db->next_record();
$reset_quota_for = json_decode($this->db->f('value'));
}
$this->deblockAccounts($reset_quota_for);
$this->deleteQuotaUsageFromCache($reset_quota_for);
$this->initQuotaUsageFromDatabase('', $reset_quota_for);
if ($this->CDRS->status['cached_keys']['saved_keys']) {
$log = sprintf(
"Saved %d accounts in quota cache\n",
$this->CDRS->status['cached_keys']['saved_keys']
);
print $log;
syslog(LOG_NOTICE, $log);
}
if ($this->CDRS->status['cached_keys']['failed_keys']) {
$log = sprintf(
"Error: failed to save %d account\n",
$this->CDRS->status['cached_keys']['failed_keys']
);
print $log;
syslog(LOG_NOTICE, $log);
}
if ($this->saveQuotaInitFlag()) {
$query = sprintf(
"delete from memcache where `key` = '%s'",
addslashes($this->quota_reset_flag)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
return true;
} else {
$log = "Error: failed to save key quotaCheckInit";
syslog(LOG_NOTICE, $log);
return false;
}
}
function markBlocked($account)
{
$query = sprintf(
"update quota_usage set blocked = '1', notified = NOW() where account = '%s' and datasource = '%s'",
addslashes($account),
addslashes($this->CDRS->cdr_source)
);
if (!$this->db1->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db1->Error,
$this->db1->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
}
function resetDailyQuota()
{
$query = sprintf(
"update quota_usage set cost_today = 0 where datasource = '%s'",
addslashes($this->CDRS->cdr_source)
);
if (!$this->db1->query($query)) {
$log = sprintf(
"Database error for query %s: %s (%s)",
$query,
$this->db1->Error,
$this->db1->Errno
);
print $log;
syslog(LOG_NOTICE, $log);
return false;
}
return true;
}
}
class RatingEngine
{
var $method = '';
var $log_runtime = false;
var $prepaid_table = "prepaid";
var $init_ok = false;
public function RatingEngine()
{
global $RatingEngine; // set in global.inc
global $DATASOURCES; // set in global.inc
if (!strlen($RatingEngine['socketIP']) || !$RatingEngine['socketPort'] || !$RatingEngine['cdr_source']) {
$log = sprintf("Please define \$RatingEngine['socketIP'], \$RatingEngine['socketPort'] and \$RatingEngine['cdr_source'] in /etc/cdrtool/global.inc\n");
syslog(LOG_NOTICE, $log);
return false;
}
if (preg_match("/^\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3}$/", $RatingEngine['socketIP'])) {
$log = sprintf("Invalid \$RatingEngine['socketIP'] in /etc/cdrtool/global.inc\n");
syslog(LOG_NOTICE, $log);
return false;
}
if (intval($RatingEngine['socketPort']) < 1 || intval($RatingEngine['socketPort']) > 65535) {
$log = sprintf("Invalid \$RatingEngine['socketPort'] in /etc/cdrtool/global.inc\n");
syslog(LOG_NOTICE, $log);
return false;
}
if (!is_array($DATASOURCES[$RatingEngine['cdr_source']])) {
$log = sprintf("Datasource '%s' does not exist in /etc/cdrtool/global.inc\n", $RatingEngine['cdr_source']);
syslog(LOG_NOTICE, $log);
return false;
}
$this->settings = $RatingEngine;
if ($this->settings['log_runtime']) {
$this->log_runtime=true;
}
// init database
$this->db = new DB_CDRTool;
$query=sprintf("delete from memcache where `key` = 'destinations_sip' or `key` = 'destinations'");
if (!$this->db->query($query)) {
$log = sprintf(
"Database error: %s (%s) for query %s",
$db->Error,
$db->Errno,
$query
);
syslog(LOG_NOTICE, $log);
}
// init CDR datasource
$CDR_class = $DATASOURCES[$RatingEngine['cdr_source']]['class'];
$this->CDRS = new $CDR_class($RatingEngine['cdr_source']);
// load Rating Tables
$this->CDRS->RatingTables = new RatingTables();
$this->CDRS->RatingTables->LoadRatingTables();
// init subscribers database
$this->db_subscribers_class = $this->CDRS->db_subscribers;
if (!class_exists($this->db_subscribers_class)) {
syslog(LOG_NOTICE, "Error: No database defined for SIP accounts");
return false;
}
$this->AccountsDB = new $this->db_subscribers_class;
$this->enableThor = $this->CDRS->enableThor;
$this->init_ok = true;
}
function reloadRatingTables()
{
$b=time();
//$query="delete from memcache where `key` in ('destinations','destinations_sip','ENUMtlds')";
$query = "delete from memcache where `key` in ('ENUMtlds')";
if (!$this->db->query($query)) {
$log = sprintf(
"Database error: %s (%s)",
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE,$log);
}
$this->CDRS->RatingTables->LoadRatingTables();
$e=time();
$d=$e-$b;
if ($d > 0 ) syslog(LOG_NOTICE, "Reloaded rating tables in $d seconds");
$b=time();
$this->CDRS->LoadDestinations();
$e=time();
$d=$e-$b;
if ($d > 0 ) syslog(LOG_NOTICE, "Reloaded destinations in $d seconds");
$this->db->query("update settings set var_value = '' where var_name = 'reloadRating'");
return 1;
}
function reloadCustomers($customerFilter)
{
return 1;
}
function reloadDomains()
{
return 1;
}
function reloadQuota($account)
{
if (!$account) return false;
$quota = $this->getQuota($account);
$blocked = $this->getBlockedByQuotaStatus($account);
$query = sprintf(
"update quota_usage set quota = '%s', blocked = '%s' where datasource = '%s' and account = '%s'",
$quota,
intval($blocked),
$this->CDRS->cdr_source,
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query '%s': %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
return 1;
}
function getBalanceHistory($account, $limit = 50)
{
list($username, $domain)=explode("@", $account);
if (!$username || !$domain) return 0;
$query = sprintf(
"select * from prepaid_history where username = '%s' and domain = '%s' order by id desc",
addslashes($username),
addslashes($domain)
);
if ($limit) $query.= sprintf(" limit %d", $limit);
if (!$this->db->query($query)) {
$log = sprintf(
"getBalanceHistory error: %s (%s)",
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
while ($this->db->next_record()) {
$history[] = array(
'account' => $account,
'action' => $this->db->f('action'),
'description' => $this->db->f('description'),
'value' => $this->db->f('value'),
'balance' => $this->db->f('balance')
);
}
$line = json_encode($history);
return $line;
}
function DebitBalanceAudio($account, $balance, $session_id, $duration, $force = false)
{
$this->old_session_count = 0;
$this->new_session_count = 0;
$els = explode(":", $account);
if (count($els) == 2) {
$account=$els[1];
}
if (!$account) {
syslog(LOG_NOTICE, "DebitBalanceAudio() error: missing account");
return 0;
}
if (!is_numeric($balance)) {
syslog(LOG_NOTICE, "DebitBalanceAudio() error: balance must be numeric");
return 0;
}
if (!$session_id) {
syslog(LOG_NOTICE, "DebitBalanceAudio() error: missing call id");
return 0;
}
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
if (!$this->db->num_rows()) {
$log = sprintf("DebitBalanceAudio() error: account %s does not exist", $account);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
$this->db->next_record();
if (strlen($this->db->f('active_sessions'))) {
// remove active session
$active_sessions = array();
$old_active_sessions = json_decode($this->db->f('active_sessions'), true);
$destination=$old_active_sessions[$session_id]['Destination'];
if (!$force) {
if (!in_array($session_id, array_keys($old_active_sessions))) {
$this->sessionDoesNotExist=true;
$log = sprintf(
"Error: session %s of %s does not exist",
$session_id,
$account
);
syslog(LOG_NOTICE, $log);
return 0;
}
}
foreach (array_keys($old_active_sessions) as $_key) {
if ($_key==$session_id) continue;
$active_sessions[$_key]=$old_active_sessions[$_key];
}
} else {
if (!$force) {
$this->sessionDoesNotExist=true;
$log = sprintf(
"Error: session %s for %s does not exist",
$session_id,
$account
);
syslog(LOG_NOTICE, $log);
return 0;
}
}
$next_balance = $this->db->f('balance') - $balance;
//get parallel calls and remaining_balance
$this->getActivePrepaidSessions($active_sessions, $next_balance, $account);
// calculate the updated maxsessiontime
$maxsessiontime = $this->getAggregatedMaxSessiontime(
$this->parallel_calls,
$this->remaining_balance,
$account
);
$this->old_session_count = count($old_active_sessions);
$this->new_session_count = count($active_sessions);
$query = sprintf(
"update %s
set balance = balance - '%s',
change_date = NOW(),
active_sessions = '%s',
session_counter = '%s'
where account = '%s'",
addslashes($this->prepaid_table),
addslashes($balance),
addslashes(json_encode($active_sessions)),
count($active_sessions),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
if ($balance > 0) {
list($prepaidUser, $prepaidDomain)=explode("@", $account);
if ($this->enableThor) {
$this->domain_table = "sip_domains";
} else {
$this->domain_table = "domain";
}
$query = sprintf(
"select * from %s where domain = '%s'",
addslashes($this->domain_table),
addslashes($prepaidDomain)
);
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%d) %s\n",
$this->AccountsDB->Error,
$this->AccountsDB->Errno,
$query
);
syslog(LOG_NOTICE, $log);
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_reseller=$this->AccountsDB->f('reseller_id');
} else {
$_reseller=0;
}
$query = sprintf(
"insert into prepaid_history
(username,domain,action,description,value,balance,date,session,duration,destination,reseller_id)
values
('%s','%s','Debit balance','Session to %s for %ds','-%s','%s',NOW(),'%s','%d','%s',%d)",
addslashes($prepaidUser),
addslashes($prepaidDomain),
addslashes($destination),
addslashes($duration),
addslashes($balance),
addslashes($next_balance),
addslashes($session_id),
addslashes($duration),
addslashes($destination),
addslashes($_reseller)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
}
}
return $maxsessiontime;
}
function DebitBalanceMessage($account, $destination, $balance, $session_id)
{
$els = explode(":", $account);
if (count($els) == 2) {
$account=$els[1];
}
if (!$account) {
syslog(LOG_NOTICE, "DebitBalanceMessage() error: missing account");
return 0;
}
if (!is_numeric($balance)) {
syslog(LOG_NOTICE, "DebitBalanceMessage() error: balance must be numeric");
return 0;
}
if (!$session_id) {
syslog(LOG_NOTICE, "DebitBalanceMessage() error: missing call id");
return 0;
}
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
if (!$this->db->num_rows()) {
$log = sprintf("DebitBalanceMessage() error: account %s does not exist", $account);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
$this->db->next_record();
if (strlen($this->db->f('active_sessions'))) {
$active_sessions = json_decode($this->db->f('active_sessions'), true);
}
$next_balance=$this->db->f('balance')-$balance;
//get parallel calls and remaining_balance
$this->getActivePrepaidSessions($active_sessions, $next_balance, $account);
// calculate the updated maxsessiontime
$maxsessiontime = $this->getAggregatedMaxSessiontime(
$this->parallel_calls,
$this->remaining_balance,
$account
);
$query = sprintf(
"update %s
set balance = balance - '%s',
change_date = NOW()
where account = '%s'",
addslashes($this->prepaid_table),
addslashes($balance),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
if ($balance > 0) {
list($prepaidUser, $prepaidDomain) = explode("@", $account);
if ($this->enableThor) {
$this->domain_table = "sip_domains";
} else {
$this->domain_table = "domain";
}
$query = sprintf(
"select * from %s where domain = '%s'",
addslashes($this->domain_table),
addslashes($prepaidDomain)
);
if (!$this->AccountsDB->query($query)) {
$log = sprintf(
"Database error: %s (%d) %s\n",
$this->AccountsDB->Error,
$this->AccountsDB->Errno,
$query
);
syslog(LOG_NOTICE, $log);
}
if ($this->AccountsDB->num_rows()) {
$this->AccountsDB->next_record();
$_reseller=$this->AccountsDB->f('reseller_id');
} else {
$_reseller=0;
}
$query = sprintf(
"insert into prepaid_history
(username,domain,action,description,value,balance,date,session,destination,reseller_id)
values
('%s','%s','Debit balance','Message to %s','-%s','%s',NOW(),'%s','%s',%d)",
addslashes($prepaidUser),
addslashes($prepaidDomain),
addslashes($destination),
addslashes($balance),
addslashes($next_balance),
addslashes($session_id),
addslashes($destination),
addslashes($_reseller)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
}
}
return true;
}
function CreditBalance($account, $balance)
{
if (!is_numeric($balance)) {
syslog(LOG_NOTICE, "CreditBalance() error: balance \"$balance\"is invalid");
return 0;
}
$els = explode(":", $account);
if (count($els) == 2) {
$account=$els[1];
}
if (!$account) {
syslog(LOG_NOTICE, "CreditBalance() error: missing account");
return 0;
}
list($prepaidUser, $prepaidDomain) = explode("@", $account);
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
if ($this->db->num_rows()) {
$this->db->next_record();
$current_balance = $this->db->f('balance');
$query = sprintf(
"update %s
set balance = balance + '%s',
change_date = NOW()
where account = '%s'",
addslashes($this->prepaid_table),
addslashes($balance),
addslashes($account)
);
$this->db->query($query);
if ($this->db->affected_rows()) {
$new_balance = $current_balance + $balance;
$log = sprintf("Prepaid account %s credited with %s", $account, $balance);
syslog(LOG_NOTICE, $log);
// log to prepaid_history
$query = sprintf(
"insert into prepaid_history
(username,domain,action,description,value,balance,date)
values
('%s','%s','Set balance','Manual update','%s','%s',NOW())",
addslashes($prepaidUser),
addslashes($prepaidDomain),
addslashes($balance),
addslashes($new_balance)
);
if (!$this->db->query($query)) {
$log = sprintf("Error: %s (%s)", $this->db->Error, $this->db->Errno);
syslog(LOG_NOTICE, $log);
}
return 1;
} else {
$log = sprintf(
"CreditBalance() error: failed to credit balance: %s (%s)",
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
} else {
$query = sprintf(
"insert into %s (balance, account, change_date) values ('%s','%s',NOW())",
addslashes($this->prepaid_table),
addslashes($balance),
addslashes($account)
);
$this->db->query($query);
if ($this->db->affected_rows()) {
$log = sprintf("Added prepaid account %s with balance=%s", $account, $balance);
syslog(LOG_NOTICE, $log);
// log to prepaid_history
$query = sprintf(
"insert into prepaid_history
(username,domain,action,description,value,balance,date)
values
('%s','%s','Set balance','Manual update','%s','%s',NOW())",
addslashes($prepaidUser),
addslashes($prepaidDomain),
addslashes($balance),
addslashes($balance)
);
if (!$this->db->query($query)) {
$log = sprintf("Error: %s (%s)", $this->db->Error, $this->db->Errno);
syslog(LOG_NOTICE, $log);
}
return 1;
} else {
$log = sprintf(
"CreditBalance() error: failed to credit balance: %s (%s)",
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
}
}
function DeleteBalance($account)
{
$els = explode(":", $account);
if (count($els) == 2) {
$account = $els[1];
}
if (!$account) {
syslog(LOG_NOTICE, "DeleteBalance() error: missing account");
return 0;
}
$query = sprintf(
"delete from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($account)
);
if (!$this->db->query($query)) {
$log = sprintf(
"DeleteBalance error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
$log = sprintf("Prepaid account %s has been deleted", $account);
syslog(LOG_NOTICE, $log);
return 1;
}
function DeleteBalanceHistory($account)
{
$account=trim($account);
$els = explode(":", $account);
if (count($els) == 2) {
$account=$els[1];
}
if (!$account) {
syslog(LOG_NOTICE, "DeleteBalanceHistory() error: missing account");
return 0;
}
list($username, $domain) = explode('@', $account);
$query = sprintf(
"delete from prepaid_history where username = '%s' and domain = '%s'",
addslashes($username),
addslashes($domain)
);
if (!$this->db->query($query)) {
$log = sprintf(
"DeleteBalanceHistory error for query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
$log = sprintf("History of prepaid account %s has been deleted", $account);
syslog(LOG_NOTICE, $log);
return 1;
}
function GetEntityProfiles($entity) {
if (!$entity) {
syslog(LOG_NOTICE, "GetEntityProfiles");
return 0;
}
$query = sprintf(
"select * from billing_customers
where subscriber = '%s' or domain = '%s' or gateway = '%s'",
addslashes($entity),
addslashes($entity),
addslashes($entity)
);
if (!$this->db->query($query)) {
$log = sprintf(
"GetEntityProfiles error: %s (%s)",
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return 0;
}
if ($this->db->num_rows() == 1) {
$this->db->next_record();
$entity = array(
'entity' => $entity,
'profileWeekday' => $this->db->f('profile_name1'),
'profileWeekdayAlt' => $this->db->f('profile_name1_alt'),
'profileWeekend' => $this->db->f('profile_name2'),
'profileWeekendAlt' => $this->db->f('profile_name2_alt'),
'timezone' => $this->db->f('timezone'),
'increment' => $this->db->f('increment'),
'min_duration' => $this->db->f('min_duration')
);
}
$line = json_encode($entity);
return $line;
}
function SetEntityProfiles($entity, $profiles)
{
if (!$entity) {
syslog(LOG_NOTICE, "SetEntityProfiles");
return 0;
}
}
function showHelp()
{
$help=
"Version\n".
"Help\n".
"ShowClients\n".
"MaxSessionTime CallId=6432622xvv@1 From=sip:123@example.com To=sip:0031650222333@example.com Duration=7200 Gateway=10.0.0.1 Lock=1\n".
"ShowPrice From=sip:123@example.com To=sip:0031650222333@example.com Gateway=10.0.0.1 Duration=59\n".
"DebitBalance CallId=6432622xvv@1 From=sip:123@example.com To=sip:0031650222333@example.com Gateway=10.0.0.1 Duration=59\n".
"AddBalance From=123@example.com Value=10.00\n".
"GetBalance From=123@example.com\n".
"GetBalanceHistory From=123@example.com\n".
"DeleteBalance From=123@example.com\n".
"DeleteBalanceHistory From=123@example.com\n".
"ReloadQuota Account=abc@example.com\n".
"GetEntityProfiles Entity=abc@example.com\n".
"DumpPrepaidSessions Account=123@example.com\n".
"ReloadRatingTables\n".
"ReloadDomains\n".
"ShowProfiles\n".
"ShowENUMtlds\n"
;
return $help;
}
function logRuntime()
{
if (!$this->log_runtime) return;
$t=0;
$log='';
foreach (array_keys($this->runtime) as $_key) {
$stamp=$this->runtime[$_key];
if ($prev_stamp) {
$_exec_time = $stamp - $prev_stamp;
$log .= sprintf("%s=%1.7f ", $_key, $_exec_time);
}
$prev_stamp = $stamp;
$t++;
}
syslog(LOG_NOTICE, $log);
}
function processNetworkInput($tinput)
{
// Read key=value pairs from input
// Strip any unnecessary spaces
$this->runtime = array();
$tinput = preg_replace("/\s+/", " ", $tinput);
if ($tinput == "/" and strlen($this->last_input)) {
$tinput = $this->last_input;
} else {
$this->last_input = $tinput;
}
$_els = explode(" ", trim($tinput));
$this->runtime['start']=microtime_float();
syslog(LOG_NOTICE, "Got command: $tinput");
if (!$_els[0]) return 0;
// read fields from input
unset($NetFields);
unset($seenField);
$i=0;
while ($i < count($_els)) {
$i++;
$_dict = explode("=", $_els[$i]);
$_key = strtolower(trim($_dict[0]));
if ($_key == 'callid') {
$_value = trim($_dict[1]);
} else {
$_value = strtolower(trim($_dict[1]));
}
if ($_key && $seenField[$_key]) {
$log = sprintf(
"Error: '$_key' attribute is present more than once in $tinput"
);
syslog(LOG_NOTICE, $log);
return 0;
} else {
if ($_key) {
$NetFields[$_key]=$_value;
$seenField[$_key]++;
}
}
}
$NetFields['action'] = strtolower($_els[0]);
$this->method = $NetFields['action'];
// begin processing
if ($NetFields['action']=="maxsessiontime") {
if (!$NetFields['from']) {
$log = "Error: missing From parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['to']) {
$log = "Error: missing To parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['gateway']) {
$log = "Error: missing gateway parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['callid']) {
$log = "Error: missing Call Id parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['duration'] && $this->settings['MaxSessionTime']) {
$NetFields['duration']=$this->settings['MaxSessionTime'];
}
$app_prefix = preg_replace('/[.].*$/', '', $NetFields['application']);
if (strlen($app_prefix)) {
if ($app_prefix == 'audio' || $app_prefix == 'sms') {
$application=$NetFields['application'];
} else {
$log = sprintf(
"Error: unsupported application %s",
$NetFields['application']
);
syslog(LOG_NOTICE, $log);
return $log;
}
} else {
$application='audio';
}
list($username_t, $domain_t) = explode("@", $NetFields['from']);
$CDRStructure = array(
$this->CDRS->CDRFields['callId'] => $NetFields['callid'],
$this->CDRS->CDRFields['aNumber'] => $NetFields['from'],
$this->CDRS->CDRFields['CanonicalURI'] => $NetFields['to'],
$this->CDRS->CDRFields['gateway'] => $NetFields['gateway'],
$this->CDRS->CDRFields['duration'] => floor($NetFields['duration']),
$this->CDRS->CDRFields['timestamp'] => time(),
$this->CDRS->CDRFields['domain'] => $domain_t,
$this->CDRS->CDRFields['application'] => $application,
'skip_fix_prepaid_duration' => true
);
$CDR = new $this->CDRS->CDR_class($this->CDRS, $CDRStructure);
$CDR->normalize();
$this->runtime['normalize_cdr'] = microtime_float();
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($CDR->BillingPartyId)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for query '%s': %s (%s), link_id =%s, query_id =%s",
$query,
$this->db->Error,
$this->db->Errno,
$this->db->Link_ID,
$this->db->Query_ID
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
$ret = sprintf(
"Error: database error for query '%s': %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
)."\n"."type=prepaid";
return $ret;
}
if (!$this->db->num_rows()) {
$log = sprintf(
"MaxSessionTime=unlimited Type=postpaid CallId=%s BillingParty=%s",
$NetFields['callid'],
$CDR->BillingPartyId
);
syslog(LOG_NOTICE, $log);
$ret="none"."\n"."type=postpaid";
return $ret;
}
$this->db->next_record();
$current_balance = $this->db->f('balance');
$old_session_counter = $this->db->f('session_counter');
$max_sessions = $this->db->f('max_sessions');
if (strlen($this->db->f('active_sessions'))) {
// load active sessions
$active_sessions = json_decode($this->db->f('active_sessions'), true);
if (count($active_sessions)) {
// purge stale sessions
$active_sessions_new=array();
$expired=0;
foreach (array_keys($active_sessions) as $_session) {
$expired_since = time() - $active_sessions[$_session]['timestamp'] - $active_sessions[$_session]['MaxSessionTime'];
if ($expired_since > 120) {
// this session has passed its maxsessiontime plus its reasonable setup time of 2 minutes,
// it could be stale
// because the call control module did not call debitbalance, so we purge it
$log = sprintf(
"Session %s for %s has expired since %d seconds",
$_session,
$active_sessions[$_session]['BillingPartyId'],
$expired_since
);
syslog(LOG_NOTICE, $log);
$expired++;
} else {
$active_sessions_new[$_session]=$active_sessions[$_session];
}
}
if ($expired) {
$active_sessions=$active_sessions_new;
}
}
} else {
$active_sessions=array();
}
if (!$current_balance) {
$log = "No balance found";
syslog(LOG_NOTICE, $log);
$this->logRuntime();
$ret="0"."\n"."type=prepaid";
return $ret;
}
if (preg_match("/^0[0-9]{1,}@/", $CDR->CanonicalURINormalized)) {
if (!$CDR->DestinationId) {
$log = sprintf(
"Error: cannot figure out the destination id for %s",
$CDR->CanonicalURI
);
$this->logRuntime();
syslog(LOG_NOTICE, $log);
$ret=$log."\n"."type=prepaid";
return $ret;
}
} else {
$log = sprintf(
"MaxSessionTime=unlimited Type=prepaid CallId=%s BillingParty=%s DestId=None",
$NetFields['callid'],
$CDR->BillingPartyId
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
$ret="none"."\n"."type=prepaid";
return $ret;
}
$session_counter=count($active_sessions);
if ($max_sessions && $session_counter >= $max_sessions) {
$log = sprintf(
"Locked: maximum number of concurrent calls %s reached, %s allowed",
$session_counter,
$max_sessions
);
syslog(LOG_NOTICE, $log);
$ret="Locked"."\n"."type=prepaid";
return $ret;
}
$maxduration=0;
// Build Rate dictionary containing normalized CDR fields plus customer Balance
if (count($active_sessions)) {
// set $this->remaining_balance and $this->parallel_calls for ongoing calls:
if (!$this->getActivePrepaidSessions($active_sessions, $current_balance, $CDR->BillingPartyId, array($CDR->callId))) {
$ret="0"."\n"."type=prepaid";
return $ret;
}
$this->runtime['get_parallel_calls']=microtime_float();
// add this new call to the list of parallel calls
$RateDictionary = array(
'duration' => $CDR->duration,
'callId' => $CDR->callId,
'Balance' => $this->remaining_balance,
'timestamp' => $CDR->timestamp,
'DestinationId' => $CDR->DestinationId,
'region' => $CDR->region,
'domain' => $CDR->domain,
'gateway' => $CDR->gateway,
'BillingPartyId' => $CDR->BillingPartyId,
'ENUMtld' => $CDR->ENUMtld,
'RatingTables' => $this->CDRS->RatingTables,
'application' => $application
);
$Rate = new Rate($this->settings, $this->db);
$_maxduration = round($Rate->MaxSessionTime($RateDictionary));
$log = sprintf(
"Maximum duration for new session %s of %s to destination %s having balance=%s is %s",
$CDR->callId,
$CDR->BillingPartyId,
$CDR->DestinationId,
$this->remaining_balance,
$_maxduration
);
syslog(LOG_NOTICE, $log);
if ($_maxduration > 0) {
$this->parallel_calls[$CDR->callId] = array(
'remainingBalancePerSecond' => $this->remaining_balance / $_maxduration
);
} else {
$log = sprintf(
"Maximum duration for new session %s of %s <=0",
$CDR->callId,
$CDR->BillingPartyId
);
syslog(LOG_NOTICE, $log);
$ret="0"."\n"."type=prepaid";
return $ret;
}
$this->parallel_calls[$CDR->callId]=array('remainingBalancePerSecond' => $this->remaining_balance/$_maxduration);
$maxduration=$this->getAggregatedMaxSessiontime($this->parallel_calls, $this->remaining_balance, $CDR->BillingPartyId);
} else {
$RateDictionary=array(
'duration' => $CDR->duration,
'callId' => $CDR->callId,
'Balance' => $current_balance,
'timestamp' => $CDR->timestamp,
'DestinationId' => $CDR->DestinationId,
'region' => $CDR->region,
'domain' => $CDR->domain,
'gateway' => $CDR->gateway,
'BillingPartyId' => $CDR->BillingPartyId,
'ENUMtld' => $CDR->ENUMtld,
'RatingTables' => $this->CDRS->RatingTables,
'application' => $application
);
$Rate = new Rate($this->settings, $this->db);
$this->runtime['instantiate_rate']=microtime_float();
$maxduration = round($Rate->MaxSessionTime($RateDictionary));
}
// add new active session
$active_sessions[$CDR->callId] = array(
'timestamp' => $CDR->timestamp,
'duration' => $CDR->duration,
'BillingPartyId' => $CDR->BillingPartyId,
'MaxSessionTime' => $maxduration,
'domain' => $CDR->domain,
'gateway' => $CDR->gateway,
'Destination' => $CDR->destinationPrint,
'DestinationId' => $CDR->DestinationId,
'region' => $CDR->region,
'connectCost' => $Rate->connectCost
);
if ($CDR->ENUMtld) {
$active_sessions[$CDR->callId]['ENUMtld']=$CDR->ENUMtld;
}
$this->runtime['calculate_maxduration']=microtime_float();
if ($maxduration < 0) {
$log = sprintf(
"Error: maxduration %s is negative",
$maxduration
);
syslog(LOG_NOTICE, $log);
$ret = $log."\n"."type=prepaid";
return $ret;
}
if ($Rate->min_duration && $maxduration < $Rate->min_duration) {
$log = sprintf(
"Notice: maxduration of %s is less then min_duration (%s)",
$maxduration,
$Rate->min_duration
);
syslog(LOG_NOTICE, $log);
$ret = "0"."\n"."type=prepaid";
return $ret;
}
if (!$Rate->billingTimezone) {
$log = sprintf("Error: cannot figure out the billing timezone")."\n"."type=prepaid";
syslog(LOG_NOTICE, $log);
$ret=$log."\n"."type=prepaid";
return $ret;
}
if (!$Rate->startTimeBilling) {
$log = sprintf("Error: cannot figure out the billing start time")."\n"."type=prepaid";
syslog(LOG_NOTICE, $log);
$ret = $log."\n"."type=prepaid";
return $ret;
}
$log = sprintf(
"MaxSessionTime=%s Type=prepaid CallId=%s BillingParty=%s DestId=%s Balance=%s Spans=%d Counter=%d->%d",
$maxduration,
$NetFields['callid'],
$CDR->BillingPartyId,
$CDR->DestinationId,
$RateDictionary['Balance'],
$Rate->MaxSessionTimeSpans,
$old_session_counter,
count($active_sessions)
);
syslog(LOG_NOTICE, $log);
if ($maxduration > 0) {
$query = sprintf(
"update %s
set
active_sessions = '%s',
session_counter = '%s'
where account = '%s'",
addslashes($this->prepaid_table),
addslashes(json_encode($active_sessions)),
count($active_sessions),
addslashes($CDR->BillingPartyId)
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$log= sprintf(
"Error: database error %s (%s)",
$this->db->Error,
$this->db->Errno
);
return $log;
}
}
$this->runtime['update_prepaid']=microtime_float();
$this->logRuntime();
$ret=$maxduration."\n"."type=prepaid";
return $ret;
} elseif ($NetFields['action'] == "dumpprepaidsessions") {
if (!$NetFields['account']) {
$log = "Error: missing account parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($NetFields['account'])
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
if (!$this->db->num_rows()) {
$log = sprintf("DebitBalanceAudio() Error: account %s does not exist", $account);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
$this->db->next_record();
return var_export(json_decode($this->db->f('active_sessions'), true), true);
} elseif ($NetFields['action'] == "debitbalance") {
if (!$NetFields['from']) {
$log = "Error: missing From parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['to']) {
$log = "Error: missing To parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
$app_prefix = preg_replace('/[.].*$/', '', $NetFields['application']);
if (!strlen($app_prefix) || (strlen($app_prefix) && $app_prefix == 'audio')) {
if (!strlen($NetFields['duration'])) {
$log= "Error: missing Duration parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
}
if (strlen($app_prefix)) {
if ($app_prefix == 'audio' || $app_prefix == 'sms') {
$application = $NetFields['application'];
} else {
$log = sprintf("Error: unsupported application %s", $NetFields['application']);
syslog(LOG_NOTICE, $log);
return $log;
}
} else {
$application = 'audio';
$app_prefix = 'audio';
}
if (!$NetFields['gateway']) {
$log = "Error: missing gateway parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if (!$NetFields['callid']) {
$log = "Error: missing Call Id parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
if ($NetFields['force']) {
$force = true;
} else {
$force = false;
}
$timestamp = time();
list($username_t, $domain_t) = explode("@", $NetFields['from']);
$CDRStructure = array(
$this->CDRS->CDRFields['callId'] => $NetFields['callid'],
$this->CDRS->CDRFields['aNumber'] => $NetFields['from'],
$this->CDRS->CDRFields['CanonicalURI'] => $NetFields['to'],
$this->CDRS->CDRFields['gateway'] => $NetFields['gateway'],
$this->CDRS->CDRFields['ENUMtld'] => $NetFields['enumtld'],
$this->CDRS->CDRFields['duration'] => floor($NetFields['duration']),
$this->CDRS->CDRFields['timestamp'] => time(),
$this->CDRS->CDRFields['domain'] => $domain_t,
$this->CDRS->CDRFields['application'] => $application,
'skip_fix_prepaid_duration' => true
);
// Init CDR
$CDR = new $this->CDRS->CDR_class($this->CDRS, $CDRStructure);
$CDR->normalize();
$this->runtime['normalize_cdr']=microtime_float();
// Build Rate dictionary containing normalized CDR fields plus customer Balance
$RateDictionary = array(
'callId' => $NetFields['callid'],
'timestamp' => $CDR->timestamp,
'duration' => $CDR->duration,
'DestinationId' => $CDR->DestinationId,
'region' => $CDR->region,
'domain' => $CDR->domain,
'gateway' => $CDR->gateway,
'BillingPartyId' => $CDR->BillingPartyId,
'ENUMtld' => $CDR->ENUMtld,
'RatingTables' => $this->CDRS->RatingTables,
'application' => $application
);
$Rate = new Rate($this->settings, $this->db);
$this->runtime['instantiate_rate']=microtime_float();
if ($app_prefix == 'audio') {
if ($Rate->calculateAudio($RateDictionary)) {
$this->runtime['calculate_rate'] = microtime_float();
$this->sessionDoesNotExist = false;
$result = $this->DebitBalanceAudio(
$CDR->BillingPartyId,
$Rate->price,
$NetFields['callid'],
$CDR->duration,
$force
);
if ($this->sessionDoesNotExist) {
return "Failed";
}
$this->runtime['debit_balance']=microtime_float();
$log = sprintf(
"DebitBalance=%s Duration=%s CallId=%s BillingParty=%s DestId=%s MaxSessionTime=%d Counter=%d->%d",
$Rate->price,
$CDR->duration,
$NetFields['callid'],
$CDR->BillingPartyId,
$CDR->DestinationId,
$result,
$this->old_session_count,
$this->new_session_count
);
syslog(LOG_NOTICE, $log);
$RateReturn = "Ok";
$RateReturn.= sprintf("\nMaxSessionTime=%d", $result);
if (strlen($Rate->price)) {
$RateReturn.="\n".$Rate->price;
if ($Rate->rateInfo) {
$RateReturn.="\n".trim($Rate->rateInfo);
}
}
return $RateReturn;
} else {
syslog(LOG_NOTICE, 'Failed to calculate rate in DebitBalance()');
return "Failed\n";
}
} elseif ($app_prefix == 'sms') {
// return Ok, No credit, Error
if ($Rate->calculateMessage($RateDictionary)) {
if ($this->DebitBalanceMessage($CDR->BillingPartyId, $CDR->destinationPrint, $Rate->price, $NetFields['callid'])) {
$log = sprintf(
"Price=%s CallId=%s BillingParty=%s DestId=%s Application=%s",
$Rate->price,
$NetFields['callid'],
$CDR->BillingPartyId,
$CDR->DestinationId,
$application
);
syslog(LOG_NOTICE, $log);
$RateReturn = "Ok";
if (strlen($Rate->price)) {
$RateReturn.="\n".$Rate->price;
if ($Rate->rateInfo) {
$RateReturn.="\n".trim($Rate->rateInfo);
}
}
return $RateReturn;
} else {
return "Failed";
}
} else {
return "Failed";
}
} else {
return false;
}
} elseif ($NetFields['action'] == "addbalance") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
if (!is_numeric($NetFields['value'])) {
$log = "Error: Missing Value parameter, it must be numeric";
syslog(LOG_NOTICE, $log);
return 0;
}
return $this->CreditBalance($NetFields['from'], $NetFields['value']);
} elseif ($NetFields['action'] == "deletebalance") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
return $this->DeleteBalance($NetFields['from']);
} elseif ($NetFields['action'] == "deletebalancehistory") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
return $this->DeleteBalanceHistory($NetFields['from']);
} elseif ($NetFields['action'] == "showprice") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
if (!$NetFields['to']) {
$log = "Error: Missing To parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
if (!strlen($NetFields['duration'])) {
$log = "Error: Missing Duration parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
if ($NetFields['timestamp']) {
$timestamp = $NetFields['timestamp'];
} else {
$timestamp = time();
}
if (!$NetFields['gateway']) {
$log = "Error: missing gateway parameter";
syslog(LOG_NOTICE, $log);
return $log;
}
$app_prefix = preg_replace('/[.].*$/', '', $NetFields['application']);
if (strlen($app_prefix)) {
if ($app_prefix == 'audio' || $app_prefix == 'sms') {
$application = $NetFields['application'];
} else {
$log = sprintf("Error: unsupported application %s", $NetFields['application']);
syslog(LOG_NOTICE, $log);
return $log;
}
} else {
$application = 'audio';
}
list($username_t, $domain_t) = explode("@", $NetFields['from']);
$CDRStructure=array (
$this->CDRS->CDRFields['callId'] => $NetFields['callid'],
$this->CDRS->CDRFields['aNumber'] => $NetFields['from'],
$this->CDRS->CDRFields['CanonicalURI'] => $NetFields['to'],
$this->CDRS->CDRFields['gateway'] => $NetFields['gateway'],
$this->CDRS->CDRFields['ENUMtld'] => $NetFields['enumtld'],
$this->CDRS->CDRFields['duration'] => floor($NetFields['duration']),
$this->CDRS->CDRFields['timestamp'] => time(),
$this->CDRS->CDRFields['domain'] => $domain_t,
$this->CDRS->CDRFields['application'] => $application,
'skip_fix_prepaid_duration' => true
);
$CDR = new $this->CDRS->CDR_class($this->CDRS, $CDRStructure);
$CDR->normalize();
$Rate = new Rate($this->settings, $this->db);
$RateDictionary=array(
'callId' => $CDR->callId,
'timestamp' => $CDR->timestamp,
'duration' => $CDR->duration,
'DestinationId' => $CDR->DestinationId,
'region' => $CDR->region,
'domain' => $CDR->domain,
'gateway' => $CDR->gateway,
'BillingPartyId' => $CDR->BillingPartyId,
'ENUMtld' => $CDR->ENUMtld,
'RatingTables' => $this->CDRS->RatingTables,
'application' => $application
);
$Rate->calculateAudio($RateDictionary);
$this->runtime['calculate_rate'] = microtime_float();
if (strlen($Rate->price)) {
$RateReturn=$Rate->price;
if ($Rate->rateInfo) {
$RateReturn.="\n".trim($Rate->rateInfo);
}
} else {
$RateReturn="0";
}
return $RateReturn;
} elseif ($NetFields['action'] == "getbalance") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
$query = sprintf(
"select * from %s where account = '%s'",
addslashes($this->prepaid_table),
addslashes($NetFields['from'])
);
if (!$this->db->query($query)) {
$log = sprintf(
"Database error for %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
$this->logRuntime();
return 0;
}
if ($this->db->num_rows()) {
$this->db->next_record();
return number_format($this->db->f('balance'), 4, ".", "");
} else {
return sprintf("%0.4f", 0);
}
} elseif ($NetFields['action'] == "getbalancehistory") {
if (!$NetFields['from']) {
$log = "Error: Missing From parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
$history=$this->getBalanceHistory($NetFields['from']);
return trim($history);
} elseif ($NetFields['action'] == "getentityprofiles") {
if (!$NetFields['entity']) {
$log = "Error: Missing Entity parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
$entity=$this->GetEntityProfiles($NetFields['entity']);
return trim($entity);
} elseif ($NetFields['action'] == "showprofiles") {
return trim($this->CDRS->RatingTables->showProfiles());
} elseif ($NetFields['action'] == "showenumtlds") {
return trim($this->CDRS->RatingTables->showENUMtlds());
} elseif ($NetFields['action'] == "version") {
$version_file=$this->CDRS->CDRTool['Path']."/version";
$version="CDRTool version ".trim(file_get_contents($version_file));
return $version;
} elseif ($NetFields['action'] == "help") {
return $this->showHelp();
} elseif ($NetFields['action'] == "reloadratingtables") {
return $this->reloadRatingTables();
} elseif ($NetFields['action'] == "keepalive") {
return $this->keepAlive();
} elseif ($NetFields['action'] == "reloadquota") {
if (!$NetFields['account']) {
$log = "Error: Missing Account parameter";
syslog(LOG_NOTICE, $log);
return 0;
}
return $this->reloadQuota($NetFields['account']);
} elseif ($NetFields['action'] == "reloaddomains") {
return $this->CDRS->LoadDomains();
} elseif ($NetFields['action'] == "reloadcustomers") {
if ($NetFields['customer'] && $NetFields['type']) {
$_customerFilter = array(
'customer' => $NetFields['customer'],
'type' => $NetFields['type']
);
}
return $this->reloadCustomers($_customerFilter);
} else {
$log = "Error: Invalid request";
syslog(LOG_NOTICE, $log);
return 0;
}
}
function getQuota($account)
{
if (!$account) return;
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 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 (!$account) return 0;
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 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 getActivePrepaidSessions($active_sessions, $current_balance, $BillingPartyId, $exceptSessions = array())
{
$this->parallel_calls=array();
$this->remaining_balance=$current_balance;
$ongoing_rates=array();
foreach (array_keys($active_sessions) as $_session) {
if (in_array($_session, $exceptSessions)) {
/*
$log = sprintf ("Ongoing prepaid session %s for %s updated",
$_session,
$BillingPartyId
);
syslog(LOG_NOTICE, $log);
*/
continue;
}
$Rate_session = new Rate($this->settings, $this->db);
$passed_time = time() - $active_sessions[$_session]['timestamp'];
$active_sessions[$_session]['passed_time'] = $passed_time;
$RateDictionary_session = array(
'duration' => $passed_time,
'callId' => $_session,
'timestamp' => $active_sessions[$_session]['timestamp'],
'DestinationId' => $active_sessions[$_session]['DestinationId'],
'region' => $active_sessions[$_session]['region'],
'domain' => $active_sessions[$_session]['domain'],
'BillingPartyId' => $active_sessions[$_session]['BillingPartyId'],
'ENUMtld' => $active_sessions[$_session]['ENUMtld'],
'RatingTables' => $this->CDRS->RatingTables
);
$Rate_session->calculateAudio($RateDictionary_session);
$log = sprintf(
"Active sessions %s for %s to %s: duration=%s, price=%s ",
$_session,
$BillingPartyId,
$active_sessions[$_session]['Destination'],
$passed_time,
$Rate_session->price
);
syslog(LOG_NOTICE, $log);
$ongoing_rates[$_session] = array(
'duration' => $passed_time,
'price' => $Rate_session->price
);
}
if (count($ongoing_rates)) {
// calculate the virtual balance of the user at this moment in time
$due_balance=0;
foreach (array_keys($ongoing_rates) as $_o) {
$due_balance = $due_balance + $ongoing_rates[$_o]['price'];
}
$this->remaining_balance = $this->remaining_balance-$due_balance;
$log = sprintf(
"Balance for %s having %d active sessions: database=%s, due=%s, real=%s",
$BillingPartyId,
count($ongoing_rates),
sprintf("%0.4f", $current_balance),
sprintf("%0.4f", $due_balance),
sprintf("%0.4f", $this->remaining_balance)
);
syslog(LOG_NOTICE, $log);
}
foreach (array_keys($active_sessions) as $_session) {
if (in_array($_session, $exceptSessions)) {
continue;
}
$RateDictionary_session = array(
'callId' => $_session,
'timestamp' => time(),
'Balance' => $this->remaining_balance,
'DestinationId' => $active_sessions[$_session]['DestinationId'],
'region' => $active_sessions[$_session]['region'],
'domain' => $active_sessions[$_session]['domain'],
'BillingPartyId' => $active_sessions[$_session]['BillingPartyId'],
'ENUMtld' => $active_sessions[$_session]['ENUMtld'],
'RatingTables' => $this->CDRS->RatingTables,
'skipConnectCost' => true
);
if ($active_sessions[$_session]['duration']) {
$RateDictionary_session['duration'] = $active_sessions[$_session]['duration']-$active_sessions[$_session]['passed_time'];
}
$Rate = new Rate($this->settings, $this->db);
$_maxduration = round($Rate->MaxSessionTime($RateDictionary_session));
$log = sprintf(
"Remaining duration for active session %s of %s to destination %s having balance=%s is %s",
$_session,
$BillingPartyId,
$active_sessions[$_session]['DestinationId'],
$this->remaining_balance,
$_maxduration
);
syslog(LOG_NOTICE, $log);
if ($_maxduration > 0) {
$this->parallel_calls[$_session] = array(
'remainingBalancePerSecond' => $this->remaining_balance / $_maxduration
);
} else {
/*
$log = sprintf ("Maxduration for session %s of %s will be negative",$_session,$active_sessions[$_session]['BillingPartyId']);
syslog(LOG_NOTICE, $log);
*/
}
}
return 1;
}
function getAggregatedMaxSessiontime($parallel_calls = array(), $balance, $BillingPartyId)
{
$maxduration=0;
$sum_remaining_balance_per_second=0;
foreach (array_keys($parallel_calls) as $_call) {
$sum_remaining_balance_per_second = $sum_remaining_balance_per_second + $parallel_calls[$_call]['remainingBalancePerSecond'];
}
if ($sum_remaining_balance_per_second > 0) {
$maxduration = intval($balance / $sum_remaining_balance_per_second);
if (count($parallel_calls) > 1) {
$log = sprintf("Maximum agregated duration for %s is %s", $BillingPartyId, $maxduration);
syslog(LOG_NOTICE, $log);
}
} else {
/*
$log = sprintf ("Error: sum_remaining_balance_per_second for %s is negative",$BillingPartyId);
syslog(LOG_NOTICE, $log);
*/
$maxduration = 0;
}
return round($maxduration);
}
function keepAlive()
{
$query = sprintf("select * from auth_user");
if (!$this->db->query($query) || !$this->db->num_rows()) {
$log = sprintf(
"Database error for keepalive query %s: %s (%s)",
$query,
$this->db->Error,
$this->db->Errno
);
syslog(LOG_NOTICE, $log);
return false;
}
$log = sprintf("Keepalive successful");
syslog(LOG_NOTICE, $log);
return true;
}
}
function reloadRatingEngineTables()
{
global $RatingEngine;
global $DATASOURCES;
if (strlen($RatingEngine['socketIP']) && $RatingEngine['socketPort']) {
if ($RatingEngine['socketIP']=='0.0.0.0' || $RatingEngine['socketIP'] == '0') {
$RatingEngine['socketIPforClients']= '127.0.0.1';
} else {
$RatingEngine['socketIPforClients']=$RatingEngine['socketIP'];
}
// init CDR datasource
$CDR_class = $DATASOURCES[$RatingEngine['cdr_source']]['class'];
$CDRS = new $CDR_class($RatingEngine['cdr_source']);
$CDRS->CacheDestinations();
if ($fp = fsockopen($RatingEngine['socketIPforClients'], $RatingEngine['socketPort'], $errno, $errstr, 2)) {
fputs($fp, "ReloadRatingTables\n");
fclose($fp);
return true;
}
}
return false;
}
function keepAliveRatingEngine()
{
global $RatingEngine;
if (strlen($RatingEngine['socketIP']) && $RatingEngine['socketPort']) {
if ($RatingEngine['socketIP']=='0.0.0.0' || $RatingEngine['socketIP'] == '0') {
$RatingEngine['socketIPforClients']= '127.0.0.1';
} else {
$RatingEngine['socketIPforClients']=$RatingEngine['socketIP'];
}
if ($fp = fsockopen($RatingEngine['socketIPforClients'], $RatingEngine['socketPort'], $errno, $errstr, 2)) {
fputs($fp, "KeepAlive\n");
fclose($fp);
return true;
}
}
return false;
}
function testRatingTables()
{
global $RatingEngine;
if (!strlen($RatingEngine['socketIP']) || !$RatingEngine['socketPort']) {
return false;
}
if ($RatingEngine['socketIP']=='0.0.0.0' || $RatingEngine['socketIP'] == '0') {
$RatingEngine['socketIPforClients']= '127.0.0.1';
} else {
$RatingEngine['socketIPforClients']=$RatingEngine['socketIP'];
}
$i=0;
$b=time();
while ($i < 1000) {
if (!$fp = fsockopen($RatingEngine['socketIPforClients'], $RatingEngine['socketPort'], $errno, $errstr, 2)) {
print "Error connecting to rating engine\n";
break;
}
$i++;
$number='00'.RandomNumber(1, true).RandomNumber(12).'@example.com';
$duration=RandomNumber(3, true);
$command = sprintf(
"ShowPrice From=sip:123@example.com To=sip:%s Gateway=10.0.0.1 Duration=%d\n",
$number,
$duration
);
fputs($fp, $command, strlen($command));
$response = fgets($fp, 8192);
fclose($fp);
}
$e = time();
$d = $e - $b;
if ($d) {
printf("Commands=%d, Time=%s seconds, Speed=%s cps\n", $i, $d, number_format($i / $d, 1));
}
}
?>
diff --git a/library/sip_settings.php b/library/sip_settings.php
index f2998a8..108b832 100644
--- a/library/sip_settings.php
+++ b/library/sip_settings.php
@@ -1,13119 +1,12961 @@
<?php
/**
* Copyright (c) 2007-2020 AG Projects
* https://ag-projects.com
* Author Adrian Georgescu
*
* This library provide the functions for managing properties
* of SIP Accounts retrieved from NGNPro
*
*/
require_once("ngnpro_client.php");
class SipSettings {
var $soapTimeout = 5;
var $login_type = 'subscriber';
var $soapClassSipPort = 'WebService_NGNPro_SipPort';
var $soapClassEnumPort = 'WebService_NGNPro_EnumPort';
var $soapClassRatingPort = 'WebService_NGNPro_RatingPort';
var $soapClassVoicemailPort = 'WebService_NGNPro_VoicemailPort';
var $soapClassCustomerPort = 'WebService_NGNPro_CustomerPort';
var $showSoapConnectionInfo = false;
var $store_clear_text_passwords=true;
// these variables can be overwritten per soap engine
// and subsequently by reseller properties
// (in ngnpro_soap_engines.inc)
var $templates_path = './templates';
var $support_company = "Example company";
var $cdrtool_address = "https://cdrtool.example.com/CDRTool";
var $support_web = "https://www.example.com/help";
var $support_email = "Support <support@example.com>";
var $billing_email = "Billing <billing@example.com>";
var $sip_settings_page = "https://cdrtool.example.com/sip_settings.phtml";
var $xcap_root = "https://cdrtool.example.com/xcap-root";
var $pstn_access = false;
var $sms_access = false;
var $pstn_changes_allowed = false;
var $prepaid_changes_allowed = false;
var $sip_proxy = "proxy.example.com";
var $sip_outbound_proxy = "";
var $sip_mobile_outbound_proxy = "";
var $voicemail_server = "vm.example.com";
var $absolute_voicemail_uri = false; // use <voice-mailbox>
var $enable_thor = false;
var $currency = "&euro;";
// access numbers
var $voicemail_access_number = "1233";
var $FUNC_access_number = "*21*";
var $FNOL_access_number = "*22*";
var $FNOA_access_number = "*23*";
var $FBUS_access_number = "*23*";
var $change_privacy_access_number = "*67";
var $check_privacy_access_number = "*68";
var $reject_anonymous_access_number = "*69";
var $show_barring_tab = false;
var $show_payments_tab = false;
var $show_tls_section = false;
var $show_support_tab = false;
var $show_did_tab = false;
var $show_directory = false;
var $notify_on_sip_account_changes = false;
var $first_tab = 'calls';
var $auto_refesh_tab = 0; // number of seconds after which to refresh tab content in the web browser
var $payment_processor_class = false;
var $did_processor_class = false;
var $show_download_tab = 'Blink'; // set it to name of the tab or false to disable it
var $digest_settings_page = "https://blink.sipthor.net/settings.phtml";
// end variables
var $tab = "settings";
var $phonebook_img = "<img src=images/pb.gif border=0>";
var $call_img = "<div style=\"font-size: 14px;\"><i class=\"icon-phone\"></i>";
var $delete_img = "<img src=images/del_pb.gif border=0 alt='Delete'>";
var $plus_sign_img = "<img src=images/plus_sign.png border=0 alt='Add Contact'>";
var $embedded_img = "<img src=images/blink.png border=0>";
var $groups = array();
var $form_elements = array(
'mailto',
'free-pstn',
'blocked',
'sip_password',
'web_password',
'yubikey',
'first_name',
'last_name',
'quota',
'language',
'quota_deblock',
'voicemail',
'anonymous',
'advanced',
'rpid',
'timezone',
'accept',
'accept_temporary_group',
'accept_temporary_remain',
'web_timestamp',
'web_password_reset',
'acceptDailyStartTime',
'acceptDailyStopTime',
'acceptDailyGroup',
'quickdial',
'delete_voicemail',
'voicemail_password',
'region',
'timeout',
'owner',
'mobile_number',
'extra_groups',
'show_barring_tab',
'ip_access_list',
'callLimit'
);
var $disable_extra_groups=true;
var $prepaid = 0;
var $emergency_regions = array();
var $FNOA_timeoutDefault = 35;
var $enums = array();
var $barring_prefixes = array();
var $SipUAImagesPath = "images";
var $SipUAImagesFile = "phone_images.php";
var $balance_history = array();
var $enrollment_url = false;
var $sip_settings_api_url= false;
var $journalEntries = array();
- var $chat_replication_backend = 'mysql'; // mongo or mysql
+ var $chat_replication_backend = 'mysql';
var $owner_information =array();
var $languages=array("en"=>array('name'=>"English",
'timezone'=>''
),
"ro"=>array('name'=>"Română",
'timezone' => 'Europe/Bucharest'
),
"nl"=>array('name'=>"Nederlands",
'timezone' => 'Europe/Amsterdam'
),
"es"=>array('name'=>"Español",
'timezone' => 'Europe/Madrid'
),
"de"=>array('name'=>"Deutsch",
'timezone' => 'Europe/Berlin'
)
);
var $pstn_termination_price_page = 'sip_rates_body.html';
var $append_domain_to_xcap_root = false;
var $blink_download_url = "https://blink.sipthor.net/download.phtml?download";
var $ownerCredentials = array();
var $localGroups = array();
var $max_credit_per_day = 40;
var $enrollment_configuration = "/etc/cdrtool/enrollment/config.ini";
var $require_proof_of_identity = true;
var $call_limit_may_by_changed_by = 'reseller'; #subscriber, reseller, admin
var $ip_access_list_may_by_changed_by = 'reseller'; #subscriber, reseller, admin
var $create_certificate = false;
function SipSettings($account,$loginCredentials=array(),$soapEngines=array()) {
//define_syslog_variables();
$this->platform_call_limit = _('unlimited');
$this->soapEngines = $soapEngines;
$debug=sprintf("<font color=blue><p><b>Initialize %s(%s)</b></font>",get_class($this),$account);
dprint($debug);
//dprint_r($loginCredentials);
$this->loginCredentials = &$loginCredentials;
if ($this->isEmbedded()) {
$this->login_type = 'subscriber';
} else {
if ($loginCredentials['login_type']) {
$this->login_type = $loginCredentials['login_type'];
} else {
$this->login_type = 'subscriber';
}
}
$this->reseller = $loginCredentials['reseller'];
$this->customer = $loginCredentials['customer'];
if (strlen($loginCredentials['sip_engine'])) {
$this->sip_engine=$loginCredentials['sip_engine'];
} else {
print _("Error: missing sip_engine in login credentials");
return false;
}
$this->settingsPage = $_SERVER['PHP_SELF'];
if ($_REQUEST['tab']) {
$this->tab = $_REQUEST['tab'];
} else {
$this->tab = $this->first_tab;
}
$this->initSoapClient();
$this->getAccount($account);
if ($this->tab=='calls' && !$_REQUEST['export']) {
$this->auto_refesh_tab=180;
}
$this->admin_url = $this->settingsPage."?account=$this->account&adminonly=1&reseller=$this->reseller&sip_engine=$this->sip_engine";
$this->reseller_url = $this->settingsPage."?account=$this->account&reseller=$this->reseller&sip_engine=$this->sip_engine";
$this->admin_url_absolute = $this->sip_settings_page."?account=$this->account&adminonly=1&reseller=$this->reseller&sip_engine=$this->sip_engine";
if ($this->login_type == "admin") {
$this->url=$this->admin_url;
$this->hiddenElements="
<input type=hidden name=account value=\"$this->account\">
<input type=hidden name=reseller value=$this->reseller>
<input type=hidden name=sip_engine value=$this->sip_engine>
<input type=hidden name=adminonly value=1>
";
} else if ($this->login_type == "reseller" || $this->login_type == "customer") {
$this->url=$this->reseller_url;
$this->hiddenElements="
<input type=hidden name=account value=\"$this->account\">
<input type=hidden name=reseller value=$this->reseller>
<input type=hidden name=sip_engine value=$this->sip_engine>
";
} else {
$this->url=$this->settingsPage;
if (!$this->isEmbedded()) {
$this->url.="?account=$this->account";
} else {
$this->url.=sprintf("?1=1&realm=%s",urlencode($_REQUEST['realm']));
if ($_REQUEST['user_agent']) {
$this->url.=sprintf("&user_agent=%s",urlencode($_REQUEST['user_agent']));
}
}
$this->hiddenElements=sprintf("
<input type=hidden name=account value='%s'>
<input type=hidden name=sip_engine value='%s'>
<input type=hidden name=user_agent value='%s'>
<input type=hidden name=realm value='%s'>
",
$this->account,
$this->sip_engine,
$_REQUEST['user_agent'],
$_REQUEST['realm']
);
}
$this->setLanguage();
if (!$this->username) {
dprint ("Record not found.");
return false;
}
$this->availableGroups['blocked'] = array("Group"=>"blocked",
"WEBName" =>sprintf(_("Status")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>0,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
$this->availableGroups['trunking'] = array("Group"=>"trunking",
"WEBName" =>sprintf(_("Trunking")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>0,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
$this->availableGroups['deny-password-change'] = array("Group"=>"deny-password-change",
"WEBName" =>sprintf(_("Deny password change")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>0,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
$this->getResellerSettings();
$this->getCustomerSettings();
if ($this->reject_anonymous_access_number) {
$_comment = sprintf(_("Dial %s to change"), $this->reject_anonymous_access_number);
} else {
$_comment = '';
}
$this->availableGroups['anonymous-reject']=array("Group"=>$this->anonymous-reject,
"WEBName" =>sprintf (_("Reject Anonymous")),
"WEBComment"=>$_comment,
"SubscriberMaySeeIt"=>1,
"SubscriberMayEditIt"=>1,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
$this->availableGroups['missed-calls']=array("Group"=>'missed-calls',
"WEBName" =>sprintf (_("Email Missed Calls")),
"WEBComment"=>'',
"SubscriberMaySeeIt"=>1,
"SubscriberMayEditIt"=>1,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
$this->availableGroups=array_merge($this->availableGroups, $this->localGroups);
$this->pstnChangesAllowed();
$this->smsChangesAllowed();
$this->prepaidChangesAllowed();
$this->tabs=array('identity'=>_('Identity'),
'devices'=>_('Devices'),
'settings'=>_('Settings'),
'calls'=>_('History'),
);
if (!in_array("trunking",$this->groups)) {
$this->tabs['diversions']=_('Forwarding');
$this->tabs['accept']=_('Accept');
$this->tabs['contacts']=_('Contacts');
}
if (in_array("free-pstn",$this->groups)) {
if ($this->show_barring_tab || $this->Preferences['show_barring_tab']) {
$this->tabs['barring']=_("Barring");
}
}
if ($this->show_did_tab && !in_array("trunking",$this->groups)) {
$this->tabs['did']=_("DID");
}
if (!$this->isEmbedded() && $this->show_download_tab && !in_array("trunking",$this->groups)) {
$this->tabs['download'] = $this->show_download_tab;
}
$this->acceptDailyProfiles=array('127' => _('Every day'),
'31' => _('Weekday'),
'96' => _('Weekend'),
'1' => _('Monday'),
'2' => _('Tuesday'),
'4' => _('Wednesday'),
'8' => _('Thursday'),
'16' => _('Friday'),
'32' => _('Saturday'),
'64' => _('Sunday')
);
$this->PhonebookGroups=array(
"vip" =>sprintf(_("VIP")),
"business" =>sprintf(_("Business")),
"coworkers" =>sprintf(_("Coworkers")),
"friends" =>sprintf(_("Friends")),
"family" =>sprintf(_("Family"))
);
$this->diversionType=array(
"FUNC"=>sprintf(_("All Calls")),
"FNOL"=>sprintf(_("If Not-Online")),
"FBUS"=>sprintf(_("If Busy")),
"FNOA"=>sprintf(_("If No-Answer")),
"FUNV"=>sprintf(_("If Unavailable"))
);
$this->diversionTypeUNV=array(
"FUNV"=>sprintf(_("If Unavailable"))
);
$this->VoicemaildiversionType=array(
"FNOL"=>sprintf(_("If Not-Online")),
"FBUS"=>sprintf(_("If Busy")),
"FNOA"=>sprintf(_("If No-Answer")),
"FUNV"=>sprintf(_("If Unavailable"))
);
$this->access_numbers=array("FUNC"=>$this->FUNC_access_number,
"FNOA"=>$this->FNOA_access_number,
"FBUS"=>$this->FBUS_access_number,
"FNOL"=>$this->FNOL_access_number
);
if ($this->prepaid && $this->pstn_access) {
$this->tabs['credit']=_("Credit");
}
$_protocol=preg_match("/^(https?:\/\/)/",$_SERVER['SCRIPT_URI'],$m);
$this->absolute_url=$m[1].$_SERVER['HTTP_HOST'].$this->url;
if ($this->prepaid && $this->show_payments_tab) {
$this->tabs['payments']=_("Payments");
}
if ($this->show_support_tab) {
$this->tabs['support'] = 'Support';
}
}
function initSoapClient() {
dprint("initSoapClient()");
// Sip, Voicemail and Customer ports share same login
$this->SOAPurl=$this->soapEngines[$this->sip_engine]['url'];
$this->SOAPversion=$this->soapEngines[$this->sip_engine]['version'];
if ($this->soapEngines[$this->sip_engine]['enrollment_url']) {
$this->enrollment_url =$this->soapEngines[$this->sip_engine]['enrollment_url'];
}
if ($this->soapEngines[$this->sip_engine]['chat_replication_backend']) {
$this->chat_replication_backend = $this->soapEngines[$this->sip_engine]['chat_replication_backend'];
}
- if ($this->soapEngines[$this->sip_engine]['mongo_db']) {
- $this->mongo_db = $this->soapEngines[$this->sip_engine]['mongo_db'];
- }
-
if ($this->soapEngines[$this->sip_engine]['sip_settings_api_url']) {
$this->sip_settings_api_url =$this->soapEngines[$this->sip_engine]['sip_settings_api_url'];
}
if (strlen($this->loginCredentials['soapUsername'])) {
$this->SOAPlogin = array(
"username" => $this->loginCredentials['soapUsername'],
"password" => $this->loginCredentials['soapPassword'],
"admin" => false
);
$this->soapUsername = $this->loginCredentials['soapUsername'];
} else {
$this->SOAPlogin = array(
"username" => $this->soapEngines[$this->sip_engine]['username'],
"password" => $this->soapEngines[$this->sip_engine]['password'],
"admin" => true,
"impersonate" => intval($this->customer)
);
$this->soapUsername = $this->soapEngines[$this->sip_engine]['username'];
}
$this->SoapAuth = array('auth', $this->SOAPlogin , 'urn:AGProjects:NGNPro', 0, '');
//print_r($this->SoapAuth);
$this->SOAPloginAdmin = array(
"username" => $this->soapEngines[$this->sip_engine]['username'],
"password" => $this->soapEngines[$this->sip_engine]['password'],
"admin" => true
);
$this->SoapAuthAdmin = array('auth', $this->SOAPloginAdmin , 'urn:AGProjects:NGNPro', 0, '');
if (strlen($this->loginCredentials['customer_engine'])) {
$this->customer_engine=$this->loginCredentials['customer_engine'];
} else if (strlen($this->soapEngines[$this->sip_engine]['customer_engine'])) {
$this->customer_engine=$this->soapEngines[$this->sip_engine]['customer_engine'];
} else {
$this->customer_engine=$this->sip_engine;
}
if (strlen($this->loginCredentials['voicemail_engine'])) {
$this->voicemail_engine=$this->loginCredentials['voicemail_engine'];
} else if (strlen($this->soapEngines[$this->sip_engine]['voicemail_engine'])) {
$this->voicemail_engine=$this->soapEngines[$this->sip_engine]['voicemail_engine'];
} else {
$this->voicemail_engine=$this->sip_engine;
}
if (strlen($this->loginCredentials['enum_engine'])) {
$this->enum_engine=$this->loginCredentials['enum_engine'];
} else if (strlen($this->soapEngines[$this->sip_engine]['enum_engine'])) {
$this->enum_engine=$this->soapEngines[$this->sip_engine]['enum_engine'];
} else {
$this->enum_engine=$this->sip_engine;
}
if (strlen($this->loginCredentials['rating_engine'])) {
$this->rating_engine=$this->loginCredentials['rating_engine'];
} else if (strlen($this->soapEngines[$this->sip_engine]['rating_engine'])) {
$this->rating_engine=$this->soapEngines[$this->sip_engine]['rating_engine'];
} else {
$this->rating_engine=$this->sip_engine;
}
// overwrite default settings
if (strlen($this->soapEngines[$this->sip_engine]['sip_proxy'])) {
$this->sip_proxy = $this->soapEngines[$this->sip_engine]['sip_proxy'];
}
if (strlen($this->soapEngines[$this->sip_engine]['sip_outbound_proxy'])) {
$this->sip_outbound_proxy = $this->soapEngines[$this->sip_engine]['sip_outbound_proxy'];
}
if (strlen($this->soapEngines[$this->sip_engine]['support_company'])) {
$this->support_company = $this->soapEngines[$this->sip_engine]['support_company'];
}
if (strlen($this->soapEngines[$this->sip_engine]['support_web'])) {
$this->support_web = $this->soapEngines[$this->sip_engine]['support_web'];
}
if (strlen($this->soapEngines[$this->sip_engine]['support_email'])) {
$this->support_email = $this->soapEngines[$this->sip_engine]['support_email'];
}
if (strlen($this->soapEngines[$this->sip_engine]['billing_email'])) {
$this->billing_email = $this->soapEngines[$this->sip_engine]['billing_email'];
}
if (strlen($this->soapEngines[$this->sip_engine]['sip_settings_page'])) {
$this->sip_settings_page = $this->soapEngines[$this->sip_engine]['sip_settings_page'];
}
if (strlen($this->soapEngines[$this->sip_engine]['digest_settings_page'])) {
$this->digest_settings_page = $this->soapEngines[$this->sip_engine]['digest_settings_page'];
}
if (strlen($this->soapEngines[$this->sip_engine]['xcap_root'])) {
$this->xcap_root = $this->soapEngines[$this->sip_engine]['xcap_root'];
}
if (strlen($this->soapEngines[$this->sip_engine]['cdrtool_address'])) {
$this->cdrtool_address = $this->soapEngines[$this->sip_engine]['cdrtool_address'];
}
if (strlen($this->soapEngines[$this->sip_engine]['msrp_relay'])) {
$this->msrp_relay = $this->soapEngines[$this->sip_engine]['msrp_relay'];
}
if ($this->soapEngines[$this->sip_engine]['emergency_regions']) {
$this->emergency_regions = $this->soapEngines[$this->sip_engine]['emergency_regions'];
}
if ($this->soapEngines[$this->sip_engine]['pstn_access']) {
$this->pstn_access = $this->soapEngines[$this->sip_engine]['pstn_access'];
}
if ($this->soapEngines[$this->sip_engine]['call_limit']) {
$this->platform_call_limit = $this->soapEngines[$this->sip_engine]['call_limit'];
}
if ($this->soapEngines[$this->sip_engine]['sms_access']) {
$this->sms_access = $this->soapEngines[$this->sip_engine]['sms_access'];
}
if ($this->soapEngines[$this->sip_engine]['voicemail_server']) {
$this->voicemail_server = $this->soapEngines[$this->sip_engine]['voicemail_server'];
}
if ($this->soapEngines[$this->sip_engine]['currency']) {
$this->currency = $this->soapEngines[$this->sip_engine]['currency'];
}
if ($this->soapEngines[$this->sip_engine]['voicemail_access_number']) {
$this->voicemail_access_number = $this->soapEngines[$this->sip_engine]['voicemail_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['FUNC_access_number']) {
$this->FUNC_access_number = $this->soapEngines[$this->sip_engine]['FUNC_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['FNOA_access_number']) {
$this->FNOA_access_number = $this->soapEngines[$this->sip_engine]['FNOA_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['FBUS_access_number']) {
$this->FBUS_access_number = $this->soapEngines[$this->sip_engine]['FBUS_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['FNOL_access_number']) {
$this->FNOL_access_number = $this->soapEngines[$this->sip_engine]['FNOL_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['payment_processor_class']) {
$this->payment_processor_class = $this->soapEngines[$this->sip_engine]['payment_processor_class'];
}
if ($this->soapEngines[$this->sip_engine]['change_privacy_access_number']) {
$this->change_privacy_access_number = $this->soapEngines[$this->sip_engine]['change_privacy_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['check_privacy_access_number']) {
$this->check_privacy_access_number = $this->soapEngines[$this->sip_engine]['check_privacy_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['reject_anonymous_access_number']) {
$this->reject_anonymous_access_number = $this->soapEngines[$this->sip_engine]['reject_anonymous_access_number'];
}
if ($this->soapEngines[$this->sip_engine]['show_directory']) {
$this->show_directory = $this->soapEngines[$this->sip_engine]['show_directory'];
}
if (isset($this->soapEngines[$this->sip_engine]['absolute_voicemail_uri'])) {
$this->absolute_voicemail_uri = $this->soapEngines[$this->sip_engine]['absolute_voicemail_uri'];
}
if (isset($this->soapEngines[$this->sip_engine]['enable_thor'])) {
$this->enable_thor=$this->soapEngines[$this->sip_engine]['enable_thor'];
}
if (isset($this->soapEngines[$this->sip_engine]['sip_accounts_lite'])) {
$this->sip_accounts_lite=$this->soapEngines[$this->sip_engine]['sip_accounts_lite'];
}
if (strlen($this->soapEngines[$this->sip_engine]['timeout'])) {
$this->soapTimeout=intval($this->soapEngines[$this->sip_engine]['timeout']);
}
if (strlen($this->soapEngines[$this->sip_engine]['store_clear_text_passwords'])) {
$this->store_clear_text_passwords=$this->soapEngines[$this->sip_engine]['store_clear_text_passwords'];
}
if (isset($this->soapEngines[$this->sip_engine]['show_download_tab'])) {
$this->show_download_tab=$this->soapEngines[$this->sip_engine]['show_download_tab'];
}
if (strlen($this->soapEngines[$this->sip_engine]['show_barring_tab'])) {
$this->show_barring_tab=$this->soapEngines[$this->sip_engine]['show_barring_tab'];
}
if (isset($this->soapEngines[$this->sip_engine]['disable_extra_groups'])) {
$this->disable_extra_groups=$this->soapEngines[$this->sip_engine]['disable_extra_groups'];
}
if (strlen($this->soapEngines[$this->sip_engine]['notify_on_sip_account_changes'])) {
//dprint($this->soapEngines[$this->sip_engine]['notify_on_sip_account_changes']);
$this->notify_on_sip_account_changes=$this->soapEngines[$this->sip_engine]['notify_on_sip_account_changes'];
}
if ($this->loginCredentials['templates_path']) {
$this->templates_path = $this->loginCredentials['templates_path'];
} else if ($this->soapEngines[$this->sip_engine]['templates_path']) {
$this->templates_path = $this->soapEngines[$this->sip_engine]['templates_path'];
}
// Instantiate the SOAP clients
// sip
$this->SipPort = new $this->soapClassSipPort($this->SOAPurl);
$this->SipPort->_options['timeout'] = $this->soapTimeout;
$this->SipPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->SipPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if ($this->showSoapConnectionInfo) {
printf ("<p>%s at <a href=%swsdl target=wsdl>%s</a> as %s ",$this->soapClassSipPort,$this->SOAPurl,$this->SOAPurl,$this->soapUsername);
}
// voicemail
$this->SOAPurlVoicemail = $this->soapEngines[$this->voicemail_engine]['url'];
$this->SOAPloginVoicemail = array(
"username" => $this->soapEngines[$this->voicemail_engine]['username'],
"password" => $this->soapEngines[$this->voicemail_engine]['password'],
"admin" => true,
"impersonate" => intval($this->customer)
);
$this->SoapAuthVoicemail = array('auth', $this->SOAPloginVoicemail , 'urn:AGProjects:NGNPro', 0, '');
$this->VoicemailPort = new $this->soapClassVoicemailPort($this->SOAPurlVoicemail);
if (strlen($this->soapEngines[$this->voicemail_engine]['timeout'])) {
$this->VoicemailPort->_options['timeout'] = intval($this->soapEngines[$this->voicemail_engine]['timeout']);
} else {
$this->VoicemailPort->_options['timeout'] = $this->soapTimeout;
}
$this->VoicemailPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->VoicemailPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if ($this->showSoapConnectionInfo && $this->SOAPurlVoicemail != $this->SOAPurl) {
printf ("<br>%s at <a href=%swsdl target=wsdl>%s</a> as %s ",$this->soapClassVoicemailPort,$this->SOAPurlVoicemail,$this->SOAPurlVoicemail,$this->soapEngines[$this->voicemail_engine]['username']);
}
// enum
$this->SOAPurlEnum = $this->soapEngines[$this->enum_engine]['url'];
$this->SOAPloginEnum = array(
"username" => $this->soapEngines[$this->enum_engine]['username'],
"password" => $this->soapEngines[$this->enum_engine]['password'],
"admin" => true,
"impersonate" => intval($this->customer)
);
$this->SoapAuthEnum = array('auth', $this->SOAPloginEnum , 'urn:AGProjects:NGNPro', 0, '');
$this->EnumPort = new $this->soapClassEnumPort($this->SOAPurlEnum);
if (strlen($this->soapEngines[$this->enum_engine]['timeout'])) {
$this->EnumPort->_options['timeout'] = intval($this->soapEngines[$this->enum_engine]['timeout']);
} else {
$this->EnumPort->_options['timeout'] = $this->soapTimeout;
}
$this->EnumPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->EnumPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if ($this->showSoapConnectionInfo && $this->SOAPurlEnum != $this->SOAPurl) {
printf ("<br>%s at <a href=%swsdl target=wsdl>%s</a> as %s ",$this->soapClassEnumPort,$this->SOAPurlEnum,$this->SOAPurlEnum,$this->soapEngines[$this->enum_engine]['username']);
}
// rating
$this->SOAPurlRating = $this->soapEngines[$this->rating_engine]['url'];
$this->SOAPloginRating = array(
"username" => $this->soapEngines[$this->rating_engine]['username'],
"password" => $this->soapEngines[$this->rating_engine]['password'],
"admin" => true,
"impersonate" => intval($this->customer)
);
$this->SoapAuthRating = array('auth', $this->SOAPloginRating , 'urn:AGProjects:NGNPro', 0, '');
$this->RatingPort = new $this->soapClassRatingPort($this->SOAPurlRating);
if (strlen($this->soapEngines[$this->rating_engine]['timeout'])) {
$this->RatingPort->_options['timeout'] = intval($this->soapEngines[$this->rating_engine]['timeout']);
} else {
$this->RatingPort->_options['timeout'] = $this->soapTimeout;
}
$this->RatingPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->RatingPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if ($this->showSoapConnectionInfo && $this->SOAPurlRating != $this->SOAPurl) {
printf ("<br>%s at <a href=%swsdl target=wsdl>%s</a> as %s ",$this->soapClassRatingPort,$this->SOAPurlRating,$this->SOAPurlRating,$this->soapEngines[$this->rating_engine]['username']);
}
// customer
$this->SOAPurlCustomer = $this->soapEngines[$this->customer_engine]['url'];
$this->SOAPloginCustomer = array(
"username" => $this->soapEngines[$this->customer_engine]['username'],
"password" => $this->soapEngines[$this->customer_engine]['password'],
"admin" => true
);
$this->SoapAuthCustomer = array('auth', $this->SOAPloginCustomer , 'urn:AGProjects:NGNPro', 0, '');
$this->CustomerPort = new $this->soapClassCustomerPort($this->SOAPurlCustomer);
if (strlen($this->soapEngines[$this->customer_engine]['timeout'])) {
$this->CustomerPort->_options['timeout'] = intval($this->soapEngines[$this->customer_engine]['timeout']);
} else {
$this->CustomerPort->_options['timeout'] = $this->soapTimeout;
}
$this->CustomerPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$this->CustomerPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
if ($this->showSoapConnectionInfo && $this->SOAPurlCustomer != $this->SOAPurl) {
printf ("<br>%s at <a href=%swsdl target=wsdl>%s</a> as %s ",$this->soapClassCustomerPort,$this->SOAPurlCustomer,$this->SOAPurlCustomer,$this->soapEngines[$this->customer_engine]['username']);
}
}
- function getMongoJournalTable() {
- $this->mongo_table_ro = NULL;
- $this->mongo_table_rw = NULL;
- $this->mongo_exception = 'Mongo exception';
-
- if (is_array($this->mongo_db)) {
- $mongo_uri = $this->mongo_db['uri'];
- $mongo_replicaSet = $this->mongo_db['replicaSet'];
- $mongo_database = $this->mongo_db['database'];
- $mongo_table = $this->mongo_db['table'];
- try {
- $mongo_connection = new Mongo("mongodb://$mongo_uri", array("replicaSet" => $mongo_replicaSet));
- $mongo_db = $mongo_connection->selectDB($mongo_database);
- $this->mongo_table_ro = $mongo_db->selectCollection($mongo_table);
- $this->mongo_table_ro->setSlaveOkay(true);
- $this->mongo_table_rw = $mongo_db->selectCollection($mongo_table);
- return true;
- } catch (MongoException $e) {
- $this->mongo_exception=$e->getMessage();
- return false;
- } catch (MongoConnectionException $e) {
- $this->mongo_exception=$e->getMessage();
- return false;
- } catch (Exception $e) {
- $this->mongo_exception=$e->getMessage();
- return false;
- }
- }
- return false;
- }
-
function getAccount($account) {
dprint("getAccount($account, engine=$this->sip_engine)");
list($username,$domain)=explode("@",trim($account));
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getAccount(array("username" =>$username,"domain" =>$domain));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
//print "<pre>";
dprint_r($result);
$this->owner = $result->owner;
if (!is_array($result->properties)) $result->properties=array();
if (!is_array($result->groups)) $result->groups=array();
if (!$result->quota) $result->quota=0;
foreach ($result->properties as $_property) {
$this->Preferences[$_property->name]=$_property->value;
}
//dprint_r($this->Preferences);
if (!$this->Preferences['language']) {
$this->Preferences['language'] ='en';
}
if ( $this->Preferences['blocked_by'] && !in_array("blocked",$result->groups)) {
$this->Preferences['blocked_by']='';
}
$this->username = $result->id->username;
$this->domain = $result->id->domain;
$this->password = $result->password;
$this->firstName = $result->firstName;
$this->lastName = $result->lastName;
$this->rpid = $result->rpid;
$this->owner = $result->owner;
$this->timezone = $result->timezone;
$this->email = $result->email;
$this->groups = $result->groups;
$this->createDate = $result->createDate;
$this->web_password = $this->Preferences['web_password'];
$this->quickdial = $result->quickdialPrefix;
$this->timeout = intval($result->timeout);
$this->quota = $result->quota;
$this->prepaid = intval($result->prepaid);
$this->region = $result->region;
$this->account = $this->username."@".$this->domain;
$this->fullName = $this->firstName." ".$this->lastName;
$this->name = $this->firstName; // used by smarty
$this->yuibikey = $result->Preferences['yubikey'];
if ($this->soapEngines[$this->sip_engine]['call_limit']) {
if ($result->callLimit) {
$this->callLimit = $result->callLimit;
} else {
$this->callLimit = '';
}
}
if ($this->soapEngines[$this->sip_engine]['ip_access_list']) {
if (is_array($result->acl) and count($result->acl)) {
foreach (array_keys($result->acl) as $key) {
$this->ip_access_list .= sprintf("%s/%s ",$result->acl[$key]->ip, $result->acl[$key]->mask);
}
$this->ip_access_list = trim($this->ip_access_list);
} else {
$this->ip_access_list = $this->soapEngines[$this->sip_engine]['ip_access_list'];
}
}
$this->sipId=array("username" => $this->username,
"domain" => $this->domain
);
if (!$this->timeout) {
$this->timeoutWasNotSet=1;
$this->timeout=intval($this->FNOA_timeoutDefault);
}
if ($this->timeout > 900 ) {
$this->timeoutWasNotSet=1;
$this->timeout=intval(900);
}
$this->getOwnerSettings($this->owner);
$this->getDomainOwner($this->domain);
$this->getMobileNumber();
if ($this->append_domain_to_xcap_root) {
$this->xcap_root = rtrim($this->xcap_root,'/')."@".$this->domain."/";
}
$this->result = $result;
}
function showAccount() {
dprint('showAccount()');
if (!$this->account) {
print "<tr><td>";
print _("Error: SIP Account information cannot be retrieved. ");
return 0;
print "</td></tr>";
}
print "
<SCRIPT>
var _action = '';
function checkForm(form) {
if (_action=='send' && form.mailto.value=='') {
window.alert('Please fill in the Email address');
form.mailto.focus();
return false;
} else {
return true;
}
}
function saveHandler(elem) {
_action = 'save';
}
function sendHandler(elem) {
_action = 'send';
}
</SCRIPT>
";
$this->showHeader();
$this->chapterTableStart();
$this->showAboveTabs();
$this->showTabs();
$this->showUnderTabs();
$this->showTitleBar();
if (!array_key_exists($this->tab,$this->tabs)) $this->tab="settings";
// show tab
$tabFunctionName='show'.ucfirst($this->tab).'Tab';
$this->$tabFunctionName();
$this->showFooter();
$this->chapterTableStop();
}
function getDomainOwner ($domain='') {
dprint("getdomainOwner($domain)");
if (!$domain) return;
// Filter
$filter=array('domain' => $domain);
// Range
$range=array('start' => 0,
'count' => 1
);
$orderBy = array('attribute' => 'changeDate',
'direction' => 'DESC'
);
// Compose query
$Query=array('filter' => $filter,
'orderBy' => $orderBy,
'range' => $range
);
//dprint_r($Query);
// Call function
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getDomains($Query);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error %s: %s (%s): %s</font>",$this->SoapEngine->SOAPurl,$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
if ($result->domains[0]) {
$this->reseller = $result->domains[0]->reseller;
$this->customer = $result->domains[0]->customer;
}
}
}
function getMobileNumber() {
//dprint('getMobileNumber()');
$this->mobile_number='';
if ($this->Preferences['mobile_number']) {
$this->mobile_number=$this->Preferences['mobile_number'];
} else if ($this->owner_information['mobile']) {
$this->mobile_number=$this->owner_information['mobile'];
}
}
function setLanguage() {
dprint("setLanguage()");
if ($this->login_type == 'reseller' || $this->login_type == 'customer') {
$lang = $this->ResellerLanguage;
} else if ($this->login_type == 'subscriber') {
if (!$this->Preferences['language']) {
foreach (array_keys($this->languages) as $_lang) {
if ($this->languages[$_lang]['timezone'] == $this->timezone) {
$lang=$_lang;
break;
}
}
}
$lang = $this->Preferences['language'];
} else {
$lang = "en";
}
//print("Set language to $lang");
$this->changeLanguage($lang);
}
function getOwnerSettings($owner='') {
dprint("getOwnerSettings($owner)");
if (!$owner) {
return false;
}
$this->CustomerPort->addHeader($this->SoapAuthCustomer);
$result = $this->CustomerPort->getAccount($owner);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (CustomerPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
$this->owner_information=array(
"username" => $result->username,
"password" => $result->password,
"firstName" => $result->firstName,
"lastName" => $result->lastName,
"organization" => $result->organization,
"timezone" => $result->timezone,
"address" => $result->address,
"billingAddress" => $result->billingAddress,
"city" => $result->city,
"state" => $result->state,
"country" => $result->country,
"postcode" => $result->postcode,
"tel" => $result->tel,
"enum" => $result->enum,
"mobile" => $result->mobile,
"fax" => $result->fax,
"email" => $result->email,
"web" => $result->web
);
//dprint_r($this->owner_information);
}
function getAliases() {
// Get Aliases
dprint("getAliases()");
$this->aliases=array();
$this->SipPort->addHeader($this->SoapAuth);
// Filter
$filter=array('targetUsername' => $this->username,
'targetDomain' => $this->domain
);
// Range
$range=array('start' => 0,
'count' => 20
);
// Order
$orderBy = array('attribute' => 'aliasUsername',
'direction' => 'ASC'
);
// Compose query
$Query=array('filter' => $filter,
'orderBy' => $orderBy,
'range' => $range
);
// Call function
$result = $this->SipPort->getAliases($Query);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
//dprint_r($result);
foreach ($result->aliases as $_alias) {
$this->aliases[]=$_alias->id->username.'@'.$_alias->id->domain;
}
}
function getRatingEntityProfiles() {
dprint("getRatingEntityProfiles()");
$this->EntityProfiles=array();
$this->RatingPort->addHeader($this->SoapAuthRating);
$entity="subscriber://".$this->username."@".$this->domain;
$result = $this->RatingPort->getEntityProfiles($entiry);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (RatingPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
$this->EntityProfiles=$result;
}
function setAliases() {
dprint("setAliases()");
$aliases_new=$_REQUEST['aliases'];
$this->getAliases();
$aliases_old=$this->aliases;
$addAliases = array_unique(array_diff($aliases_new,$aliases_old));
$deleteAliases = array_unique(array_diff($aliases_old,$aliases_new));
foreach ($addAliases as $_alias) {
$_alias=trim(strtolower($_alias));
if (!preg_match("/^[a-z0-9-_.@]+$/i",$_alias)) continue;
$els=explode("@",$_alias);
if (count($els) ==1 ) {
$_alias_username=$_alias;
$_alias_domain=$this->domain;
} else if (count($els) ==2) {
$_alias_username=$els[0];
$_alias_domain=$this->domain;
} else {
continue ;
}
$_aliasObject=array("id"=>array("username"=>strtolower($_alias_username),
"domain"=>strtolower($_alias_domain)
),
"owner"=>intval($this->owner),
"target"=>$this->sipId
)
;
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->addAlias($_aliasObject);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
foreach ($deleteAliases as $_alias) {
$_alias=trim($_alias);
if (!strlen($_alias)) continue;
$els=explode("@",$_alias);
if (count($els) ==1 ) {
$_alias_username=$_alias;
$_alias_domain=$this->domain;
} else if (count($els) == 2) {
$_alias_username=$els[0];
$_alias_domain=$els[1];
} else {
continue ;
}
$_aliasObject=array("username"=>$_alias_username,
"domain" =>$_alias_domain
);
dprint_r($_aliasObject);
dprint("deleteAlias");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->deleteAlias($_aliasObject);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
unset($this->aliases);
}
function getVoicemail () {
dprint("getVoicemail()");
$this->VoicemailPort->addHeader($this->SoapAuthVoicemail);
$result = $this->VoicemailPort->getAccount($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "2000" && $error_fault->detail->exception->errorcode != "1010") {
printf ("<p><font color=red>Error (VoicemailPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
return true;
}
}
if (!$result->mailbox) {
dprint ("No voicemail account found");
return false;
}
$this->voicemail['Mailbox'] = $result->mailbox;
$this->voicemail['Password'] = $result->password;
$this->voicemail['Name'] = $result->name;
$this->voicemail['Email'] = $result->email;
$this->voicemail['Info'] = $result->info;
$this->voicemail['Options'] = $result->options;
$this->voicemail['Account'] = $result->mailbox.'@'.$this->voicemail_server;
// used by template system
$this->voicemailMailbox = $result->mailbox;
//dprint_r($this->voicemail);
return true;
}
function showTitleBar() {
print "<div class='row-fluid'>
<div class='alert alert-info span12' style='min-height:10px'>
<div class='row-fluid'>
<span style='min-height:10px'>";
printf (("%s &lt;sip:%s@%s&gt;"),$this->fullName,$this->username,$this->domain);
print "</span>
<span class='pull-right' style='min-height:10px'>";
if ($this->login_type == 'subscriber' && !$this->isEmbedded()) {
print "<a href=sip_logout.phtml>";
print _("Logout");
print "</a>";
} else {
if ($this->enable_thor) {
print " ";
if ($this->isEmbedded()) {
print "<i class=\"icon-home icon-white\"></i> ";
print _("Home Node");
} else {
print "<a href=\"http://www.ag-projects.com/SIPThor.html\" target=_new>";
print _("SIP Thor Node");
print "</a>";
}
if ($this->homeNode=getSipThorHomeNode($this->account,$this->sip_proxy)) {
printf (" <font color=green>%s</font>",$this->homeNode);
} else {
print " <font color=red>";
print _("Unknown");
print "</font>";
}
}
}
print "</span></div></div>
</div>
";
}
function getDivertTargets () {
dprint("getDivertTargets()");
$this->divertTargets[] = array("name" => _("No diversion"),
"value" => "",
"description" => "Disabled"
);
if ($this->voicemail['Account']) {
$vmf=$this->getVoicemailForwarding();
if (is_array($vmf)) {
$this->divertTargets[]=$vmf;
}
}
if ($this->owner) {
if (in_array("free-pstn",$this->groups)) {
if ($this->owner_information['tel']) {
$tel = preg_replace("/[^\d+]/", "", $this->owner_information['tel']);
$tel_enum = str_replace("+", "00", $tel);
$telf = $tel_enum . "@" . $this->domain;
if (!$seen[$tel_enum] && !in_array($tel_enum,$this->enums)) {
$this->divertTargets[]=array("name" => sprintf (_("Tel %s"),$tel),
"value" => $telf,
"description" => "Tel");
}
$seen[$tel_enum]++;
}
if ($this->owner_information['enum']) {
$tel = preg_replace("/[^\d+]/", "", $this->owner_information['enum']);
$tel_enum = str_replace("+", "00", $tel);
$telf = $tel_enum . "@" . $this->domain;
if (!$seen[$tel_enum] && !in_array($tel_enum,$this->enums)) {
$this->divertTargets[]=array("name" => sprintf (_("Tel %s"),$tel),
"value" => $telf,
"description" => "ENUM");
}
$seen[$tel_enum]++;
}
}
}
if ($this->mobile_number) {
$tel = preg_replace("/[^\d+]/", "", $this->mobile_number);
$tel_enum = str_replace("+", "00", $tel);
$telf = $tel_enum . "@" . $this->domain;
if (!$seen[$tel_enum] && !in_array($tel_enum,$this->enums)) {
$this->divertTargets[] = array("name" => sprintf (_("Mobile %s"),$tel),
"value" => $telf,
"description" => "Mobile"
);
}
$seen[$tel_enum]++;
}
$this->divertTargets[]=array("name" => sprintf (_("Other")),
"value" => "",
"description" => "Other"
);
//print_r($this->divertTargets);
}
function pstnChangesAllowed() {
dprint("pstnChangesAllowed()");
if ($this->login_type == 'subscriber') {
$this->pstn_changes_allowed = false;
return;
} else {
if ($this->login_type == 'admin') {
$this->pstn_changes_allowed = true;
return;
// for a reseller we need to check if a subaccount is allowed
} else if ($this->loginCredentials['customer'] == $this->loginCredentials['reseller']) {
if ($this->resellerProperties['pstn_changes']) {
dprint("is reseller");
$this->pstn_changes_allowed = true;
}
return;
} else if ($this->customerImpersonate == $this->loginCredentials['reseller']) {
if ($this->resellerProperties['pstn_changes']) {
dprint("impersonate reseller");
$this->pstn_changes_allowed = true;
}
return;
} else if ($this->resellerProperties['pstn_changes'] && $this->customerProperties['pstn_changes']) {
$this->pstn_changes_allowed = true;
return;
}
}
$this->pstn_changes_allowed = false;
return;
}
function smsChangesAllowed() {
dprint("smsChangesAllowed()");
if ($this->login_type == 'subscriber') {
$this->sms_changes_allowed = false;
return;
} else {
// for a reseller we need to check if a subaccount is allowed
if ($this->loginCredentials['customer'] == $this->loginCredentials['reseller']) {
if ($this->resellerProperties['sms_access']) {
dprint("is reseller");
$this->sms_changes_allowed = true;
}
return;
} else if ($this->customerImpersonate == $this->loginCredentials['reseller']) {
if ($this->resellerProperties['sms_access']) {
dprint("impersonate reseller");
$this->sms_changes_allowed = true;
}
return;
} else if ($this->resellerProperties['sms_access'] && $this->customerProperties['sms_access']) {
$this->sms_changes_allowed = true;
return;
}
}
$this->sms_changes_allowed = false;
return;
}
function prepaidChangesAllowed() {
dprint("prepaidChangesAllowed()");
if ($this->login_type == 'subscriber') {
$this->prepaid_changes_allowed = false;
return;
} else {
if ($this->login_type == 'admin') {
$this->prepaid_changes_allowed = true;
return;
// for a reseller we need to check if a subaccount is allowed
} else if ($this->loginCredentials['customer'] == $this->loginCredentials['reseller']) {
dprint("is reseller");
if ($this->resellerProperties['prepaid_changes']) {
$this->prepaid_changes_allowed = true;
}
return;
} else if ($this->customerImpersonate == $this->loginCredentials['reseller']) {
dprint("impersonate reseller");
if ($this->resellerProperties['prepaid_changes']) {
$this->prepaid_changes_allowed = true;
}
return;
} else if ($this->resellerProperties['prepaid_changes'] && $this->customerProperties['prepaid_changes']) {
$this->prepaid_changes_allowed = true;
return;
}
}
$this->prepaid_changes_allowed = false;
return;
}
function getCustomerSettings () {
dprint("getCustomerSettings()");
if (!$this->loginCredentials['customer']) return;
$id=$this->loginCredentials['customer'];
$this->CustomerPort->addHeader($this->SoapAuthCustomer);
$result = $this->CustomerPort->getAccount(intval($this->loginCredentials['customer']));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (CustomerPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
foreach ($result->properties as $_property) {
$this->customerProperties[$_property->name]=$_property->value;
}
$this->customerImpersonate=$result->impersonate;
//dprint_r($this->customerProperties);
}
function getResellerSettings () {
dprint("getResellerSettings()");
$this->logoFile = $this->getFileTemplate("logo","logo");
$this->headerFile = $this->getFileTemplate("header.phtml");
$this->footerFile = $this->getFileTemplate("footer.phtml");
$this->cssFile = $this->getFileTemplate("main.css");
if (!$this->reseller) {
if ($this->pstn_access) {
$this->availableGroups['free-pstn'] = array(
"Group" => "free-pstn",
"WEBName" => sprintf(_("PSTN Access")),
"WEBComment" => sprintf(_("Caller-ID")),
"SubscriberMayEditIt" => 0,
"SubscriberMaySeeIt" => 1,
"ResellerMayEditIt" => 1,
"ResellerMaySeeIt" => 1
);
if ($this->change_privacy_access_number) {
$_comment = sprintf(_("Dial %s to change"), $this->change_privacy_access_number);
} else {
$_comment = '';
}
$this->availableGroups['anonymous'] = array(
"Group" => "anonymous",
"WEBName" => sprintf (_("PSTN Privacy")),
"WEBComment" => $_comment,
"SubscriberMaySeeIt" => 1,
"SubscriberMayEditIt" => 1,
"ResellerMayEditIt" => 1,
"ResellerMaySeeIt" => 1
);
if ($this->pstn_access) {
$this->availableGroups['rate-on-net'] = array("Group"=>"rate-on-net",
"WEBName" =>sprintf(_("Rate on net")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>0,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
if ($this->sms_access) {
$this->availableGroups['sms'] = array("Group"=>"sms",
"WEBName" =>sprintf(_("Mobile SMS")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>1,
"ResellerMayEditIt"=>0,
"ResellerMaySeeIt"=>1
);
}
}
if ($this->require_proof_of_identity) {
$this->availableGroups['payments'] = array("Group"=>"payments",
"WEBName" =>sprintf(_("CC Payments")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>0,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
}
}
return true;
}
$this->CustomerPort->addHeader($this->SoapAuthCustomer);
$result = $this->CustomerPort->getAccount(intval($this->reseller));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (CustomerPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
foreach ($result->properties as $_property) {
$this->resellerProperties[$_property->name]=$_property->value;
}
$this->resellerProperties['language'] = $result->language;
$this->resellerProperties['timezone'] = $result->timezone;
// overwrite settings from soap engine
if ($this->resellerProperties['sip_proxy']) {
$this->sip_proxy = $this->resellerProperties['sip_proxy'];
}
if ($this->resellerProperties['sip_outbound_proxy']) {
$this->sip_outbound_proxy = $this->resellerProperties['sip_outbound_proxy'];
}
if ($this->resellerProperties['push_notifications_server']) {
$this->sip_mobile_outbound_proxy = $this->resellerProperties['push_notifications_server'];
}
if (!$this->sip_outbound_proxy) {
$this->sip_outbound_proxy = $this->sip_proxy;
}
if (!$this->sip_mobile_outbound_proxy) {
$this->sip_mobile_outbound_proxy = $this->sip_outbound_proxy;
}
if ($this->resellerProperties['store_clear_text_passwords']) {
$this->store_clear_text_passwords = $this->resellerProperties['store_clear_text_passwords'];
}
if ($this->resellerProperties['support_company']) {
$this->support_company = $this->resellerProperties['support_company'];
}
if ($this->resellerProperties['support_web']) {
$this->support_web = $this->resellerProperties['support_web'];
}
if ($this->resellerProperties['support_email']) {
$this->support_email = $this->resellerProperties['support_email'];
}
if ($this->resellerProperties['billing_email']) {
$this->billing_email = $this->resellerProperties['billing_email'];
}
if (!$this->billing_email) {
$this->billing_email=$this->support_email;
}
if ($this->resellerProperties['sip_settings_page']) {
$this->sip_settings_page = $this->resellerProperties['sip_settings_page'];
}
if ($this->resellerProperties['digest_settings_page']) {
$this->digest_settings_page = $this->resellerProperties['digest_settings_page'];
}
if ($this->resellerProperties['xcap_root']) {
$this->xcap_root = rtrim($this->resellerProperties['xcap_root'],'/');
if ($this->append_domain_to_xcap_root) {
$this->xcap_root .= "@".$this->domain."/";
}
}
if ($this->resellerProperties['cdrtool_address']) {
$this->cdrtool_address = $this->resellerProperties['cdrtool_address'];
}
if ($this->resellerProperties['msrp_relay']) {
$this->msrp_relay = $this->resellerProperties['msrp_relay'];
}
if (isset($this->resellerProperties['voicemail_server'])) {
$this->voicemail_server = $this->resellerProperties['voicemail_server'];
}
if (isset($this->resellerProperties['voicemail_access_number'])) {
$this->voicemail_access_number = $this->resellerProperties['voicemail_access_number'];
}
if (isset($this->resellerProperties['currency'])) {
$this->currency = $this->resellerProperties['currency'];
}
if (isset($this->resellerProperties['FUNC_access_number'])) {
$this->FUNC_access_number = $this->resellerProperties['FUNC_access_number'];
}
if (isset($this->resellerProperties['FNOA_access_number'])) {
$this->FNOA_access_number = $this->resellerProperties['FNOA_access_number'];
}
if (isset($this->resellerProperties['FBUS_access_number'])) {
$this->FBUS_access_number = $this->resellerProperties['FBUS_access_number'];
}
if (isset($this->resellerProperties['FNOL_access_number'])) {
$this->FNOL_access_number = $this->resellerProperties['FNOL_access_number'];
}
if (isset($this->resellerProperties['payment_processor_class'])) {
$this->payment_processor_class = $this->resellerProperties['payment_processor_class'];
}
if (isset($this->resellerProperties['change_privacy_access_number'])) {
$this->change_privacy_access_number = $this->resellerProperties['change_privacy_access_number'];
}
if (isset($this->resellerProperties['check_privacy_access_number'])) {
$this->check_privacy_access_number = $this->resellerProperties['check_privacy_access_number'];
}
if (isset($this->resellerProperties['reject_anonymous_access_number'])) {
$this->reject_anonymous_access_number = $this->resellerProperties['reject_anonymous_access_number'];
}
if (isset($this->resellerProperties['absolute_voicemail_uri'])) {
$this->absolute_voicemail_uri = $this->resellerProperties['absolute_voicemail_uri'];
}
if (isset($this->resellerProperties['pstn_access'])) {
$this->pstn_access = $this->resellerProperties['pstn_access'];
}
if (isset($this->resellerProperties['sms_access'])) {
$this->sms_access = $this->resellerProperties['sms_access'];
}
if ($this->pstn_access) {
$this->availableGroups['free-pstn'] = array("Group"=>"free-pstn",
"WEBName" => sprintf(_("PSTN Access")),
"WEBComment"=> sprintf(_("Caller-ID")),
"SubscriberMayEditIt" => "0",
"SubscriberMaySeeIt" => 1,
"ResellerMayEditIt"=>1,
"ResellerMaySeeIt"=>1
);
if ($this->change_privacy_access_number) {
$_comment = sprintf(_("Dial %s to change"), $this->change_privacy_access_number);
} else {
$_comment = '';
}
$this->availableGroups['anonymous'] = array(
"Group" => "anonymous",
"WEBName" => sprintf (_("PSTN Privacy")),
"WEBComment" => $_comment,
"SubscriberMaySeeIt" => 1,
"SubscriberMayEditIt" => 1,
"ResellerMayEditIt" => 1,
"ResellerMaySeeIt" => 1
);
$this->availableGroups['rate-on-net'] = array(
"Group" => "rate-on-net",
"WEBName" => sprintf(_("Rate on net")),
"SubscriberMayEditIt" => 0,
"SubscriberMaySeeIt" => 0,
"ResellerMayEditIt" => 1,
"ResellerMaySeeIt" => 1
);
if ($this->sms_access) {
$this->availableGroups['sms'] = array("Group"=>"sms",
"WEBName" =>sprintf(_("Mobile SMS")),
"SubscriberMayEditIt"=>0,
"SubscriberMaySeeIt"=>1,
"ResellerMayEditIt"=>0,
"ResellerMaySeeIt"=>1
);
}
}
}
function getDiversions() {
dprint("getDiversions()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCallDiversions($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
//print_r($result);
reset($this->diversionType);
foreach(array_keys($this->diversionType) as $condition) {
$uri=$result->$condition;
if (($uri == "<voice-mailbox>" || $uri == "voice-mailbox") && $this->absolute_voicemail_uri) {
$uri = $this->voicemail['Account'];
} else if ($uri == "voice-mailbox") {
$uri = "<voice-mailbox>";
}
if (preg_match("/^(sip:|sips:)(.*)$/i",$uri,$m)) {
$uri=$m[2];
}
$this->diversions[$condition]=$uri;
}
//print_r($this->diversions);
}
function getDeviceLocations() {
dprint("getDeviceLocations()");
require_once($this->SipUAImagesFile);
$this->userAgentImages = $userAgentImages;
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getSipDeviceLocations(array($this->sipId));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
foreach ($result[0]->locations as $locationStructure) {
$contact=$locationStructure->address.":".$locationStructure->port;
if ($locationStructure->publicAddress) {
$publicContact=$locationStructure->publicAddress.":".$locationStructure->publicPort;
} else {
$publicContact=$contact;
}
$this->locations[]=array("contact" => $contact,
"publicContact" => $publicContact,
"expires" => $locationStructure->expires,
"user_agent" => $locationStructure->userAgent,
"transport" => $locationStructure->transport
);
}
}
}
function getVoicemailForwarding () {
dprint("getVoicemailForwarding()");
if (!$this->voicemail['Account']) {
return;
}
if ($this->absolute_voicemail_uri) {
$value=$this->voicemail['Account'];
} else {
$value="<voice-mailbox>";
}
return array("name" => sprintf (_("Voice Mailbox")),
"value" => $value,
"description" => "Voicemail");
}
function showAboveTabs() {
print "
<div class='row-fluid'>
<div class='span12'>
";
print "
</div>
</div>
";
}
function showTabs() {
print "<div class='pull-left'>";
if ($this->isEmbedded()) {
print $this->embedded_img;;
}
print "</div>
<div class='pull-right'>
<ul class=\"nav nav-tabs\">
";
$items=0;
while (list($k,$v)= each($this->tabs)) {
if ($this->tab==$k) {
$_class='active selected_tab';
} else {
$_class='tabs';
}
print "
<li class=$_class><a href='$this->url&tab=$k'>$v</a></li>";
}
print "
</ul>
";
print "</div>";
}
function showUnderTabs() {
print "
<div class='row-fluid'>
";
print "
</div>
";
}
function addInvoice($cardProcessor) {
// called after CC payment sucessfull
}
function showPaymentsTab() {
if (!$this->show_payments_tab) {
return false;
}
if ($this->login_type == 'subscriber' && in_array("blocked",$this->groups)) {
return false;
}
if ($_REQUEST['task'] == 'showprices') {
$chapter=sprintf(_("Price list"));
$this->showChapter($chapter);
include($this->pstn_termination_price_page);
return true;
}
$chapter=sprintf(_("Payments"));
$this->showChapter($chapter);
if (!$this->owner) {
print "
<tr>
<td colspan=3>
<p>";
print _("You must set the Owner to enable Credit Card Payments. ");
print "
</td>
</tr>
";
return false;
}
$this->getBalanceHistory();
$today_summary = $this->getTodayBalanceSummary();
if ($today_summary['credit'] >= $this->max_credit_per_day) {
print "
<tr>
<td colspan=3>
";
if ($account->login_type!='subscriber') {
print "<p>";
printf ("<font color=red>Daily Credit Exceeded</font>");
} else {
print _("Page Not Available");
$log=sprintf("CC transaction is not allowed from %s for %s (%s)",$_SERVER['REMOTE_ADDR'],$account->account,$this->fraud_reason);
syslog(LOG_NOTICE, $log);
}
print "</td>
</tr>
";
return false;
}
if (!count($this->balance_history)) {
$this->first_transaction=true;
} else {
$this->first_transaction=false;
}
print "
<tr>
<td colspan=3>
";
print "<p>";
printf (_("Calling to telephone numbers is possible at the costs set forth in the <a href=%s&tab=payments&task=showprices>Price List</a>. "),$this->url);
//printf (_("You can purchase credit with a <a href=%s&tab=payments&method=creditcard>Credit Card</a> or <a href=%s&tab=payments&method=btc>Bitcoin</a>. "),$this->url, $this->url);
//print "<p>";
//printf (_("You can purchase credit using <a href=http://bitcoin.org target=_new>Bitcoin</a>. "), $this->url);
print "<br><br>";
print "
</td>
</tr>
";
$credit_amount = 20;
//$method = 'btc';
if ($method == 'btc') {
print "<p>Select an amount and click submit to go the Bitcoin payment page.";
printf("<form action='https://mdns.sipthor.net/bitcoin/' target=_new method='POST'>
<input type='hidden' name='account' value='%s'>
Amount <input class=span1 type='text' name='amount' value='20'> USD
<p><input class=btn type=submit value='Submit'>
</form>
", $this->account);
} else {
$chapter=sprintf(_("Credit Card"));
$this->showChapter($chapter);
if ($this->require_proof_of_identity) {
if ($this->login_type == 'subscriber') {
if (!in_array("payments",$this->groups)) {
$this->showIdentityProof();
}
} else {
$this->showIdentityProof();
}
if (!in_array("payments",$this->groups)) {
return false;
}
}
$payment_processor = new $this->payment_processor_class($this);
if ($payment_processor->fraudDetected()) {
$chapter=sprintf(_("Payments"));
$this->showChapter($chapter);
print "
<tr>
<td colspan=3>
";
if ($account->login_type!='subscriber') {
print "<p>";
printf ("<font color=red>%s</font>",$this->fraud_reason);
} else {
print _("Page Not Available");
$log=sprintf("CC transaction is not allowed from %s for %s (%s)",$_SERVER['REMOTE_ADDR'],$account->account,$this->fraud_reason);
syslog(LOG_NOTICE, $log);
}
print "</td>
</tr>
";
return false;
}
$basket = array('pstn_credit'=>array('price' => $credit_amount,
'description' => _('Prepaid Credit'),
'unit' => 'credit',
'duration' => 'N/A',
'qty' => 1
)
);
// print "<pre>";
// print_r($payment_processor);
// print "</pre>";
$payment_processor->doDirectPayment($basket);
//print "<pre>";
//
//print_r($payment_processor);
//print "</pre>";
if ($payment_processor->transaction_results['success']) {
// add PSTN credit
$this->addBalanceReseller($credit_amount,sprintf("CC transaction %s",$payment_processor->transaction_results['id']));
}
if ($this->first_transaction && $payment_processor->make_credit_checks) {
// block account temporary to check the user
// $transaction_data= $payment_processor->['CardProcessor']['transaction_data'];
// if ( $this->email != $transaction_data['USER_EMAIL'] ||
// $this->
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->removeFromGroup(array("username" => $this->username,"domain"=> $this->domain),"free-pstn");
}
}
}
function showIdentityProof () {
$max_file_size=1024000;
$this->db = new DB_CDRTool();
$chapter=sprintf(_("Proof of Identity"));
$this->showChapter($chapter);
if ($_REQUEST['task'] == 'upload') {
if (!$_FILES['tmpfile']['tmp_name']) {
print "<font color=red>";
printf (_("Error: Please specify a file"));
print "</font>";
} else if (!$_REQUEST['name']) {
print "<font color=red>";
printf (_("Error: Please enter the name printed on the Credit Card"));
print "</font>";
} else if (!preg_match("/^\d{4}$/",$_REQUEST['last_digits'])) {
print "<font color=red>";
printf (_("Error: Last digits must be numeric"));
print "</font>";
} else if (!preg_match("/^\+[1-9][0-9]{7,14}$/",$_REQUEST['mobile_number'])) {
print "<font color=red>";
printf (_("Error: Mobile Number must be in international format starting with +"));
print "</font>";
} else if ($_FILES['tmpfile']['size']['size'] > $max_file_size) {
print "<font color=red>";
printf (_("Error: Maximum file size is %s"),$max_file_size);
print "</font>";
} else {
$fp=fopen($_FILES['tmpfile']['tmp_name'], "r");
$content=fread($fp, $_FILES['tmpfile']['size']);
fclose($fp);
$query=sprintf("insert into subscriber_docs (
`name`,
`username`,
`domain`,
`document`,
`file_content`,
`file_name`,
`file_size`,
`file_type`,
`file_date`,
`last_digits`,
`mobile_number`
) values (
'%s',
'%s',
'%s',
'identity',
'%s',
'%s',
'%s',
'%s',
NOW(),
'%s',
'%s'
)",
addslashes($_REQUEST['name']),
addslashes($this->username),
addslashes($this->domain),
addslashes($content),
addslashes($_FILES['tmpfile']['name']),
addslashes($_FILES['tmpfile']['size']),
addslashes($_FILES['tmpfile']['type']),
addslashes($_REQUEST['last_digits']),
addslashes($_REQUEST['mobile_number'])
);
if (!$this->db->query($query)) {
print "<font color=red>";
printf ("Error: Failed to save identity document %s (%s)", $this->db->Error,$this->db->Errno);
print "</font>";
}
// send mail
include_once('Mail.php');
include_once('Mail/mime.php');
$subject=sprintf ("%s requested CC Payments",$this->account);
$hdrs = array(
'From' => $this->email,
'Subject' => $subject
);
$crlf = "\n";
$mime = new Mail_mime($crlf);
$mime->setTXTBody($subject);
$mime->setHTMLBody($subject);
$mime->addAttachment($content, $_FILES['tmpfile']['type'],$_FILES['tmpfile']['name'],'false');
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
$mail->send($this->billing_email, $hdrs, $body);
}
}
if ($this->login_type != 'subscriber' && $_REQUEST['task'] == 'delete_identity_proof' && $_REQUEST['confirm']) {
$query=sprintf("delete from subscriber_docs
where username = '%s'
and domain = '%s'
and document = 'identity'",
addslashes($this->username),
addslashes($this->domain)
);
if (!$this->db->query($query)) {
print "<font color=red>";
printf ("Error deleting record: %s (%s)", $this->db->Error,$this->db->Errno);
print "</font>";
}
}
$query=sprintf("select * from subscriber_docs
where username = '%s'
and domain = '%s'
and document = 'identity'",
addslashes($this->username),
addslashes($this->domain)
);
if (!$this->db->query($query)) {
print "<font color=red>";
printf ("Error for database query: %s (%s)", $this->db->Error,$this->db->Errno);
print "</font>";
}
if ($this->db->num_rows()) {
print "
<div class=row-fluid>
<table class='table table-condensed table-striped'>";
if (!in_array("payments",$this->groups)) {
print "<p>";
print _("Credit Card payments will be activated after your identity is verified. ");
}
printf ("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>",
_("Name"),
_("Document"),
_("Type"),
_("Size"),
_("Date"),
_("Last digits"),
_("Mobile Number")
);
if ($this->login_type != 'subscriber') {
print "<td>";
print _("Actions");
print "</td>";
}
printf ("</tr>");
$this->db->next_record();
$download_url=$this->url.'&action=export_identity_proof';
printf ("<tr> <td>%s</td><td><a href=%s>%s</a></td> <td>%s</td> <td>%s KB</td> <td>%s</td><td align=right>%s</td><td align=right>%s</td>",
$this->db->f('name'),
$download_url,
$this->db->f('file_name'),
$this->db->f('file_type'),
number_format($this->db->f('file_size')/1024,2),
$this->db->f('file_date'),
$this->db->f('last_digits'),
$this->db->f('mobile_number')
);
if ($this->login_type != 'subscriber') {
if ($_REQUEST['task'] == 'delete_identity_proof' && !$_REQUEST['confirm']){
$delete_url=$this->url.'&tab=payments&task=delete_identity_proof&confirm=1';
printf ("<td align=right><a href='%s'>%s</a></td>",$delete_url,_("Confirm"));
} else {
$delete_url=$this->url.'&tab=payments&task=delete_identity_proof';
printf ("<td align=right><a href='%s'>%s</a></td>",$delete_url,$this->delete_img);
}
}
printf ("</tr>");
print "
</table>
</div>
";
} else {
print "
<div class=row-fluid>
";
print "<p>";
print _("Credit Card payments are available only to verified customers. ");
print "<p>";
printf (_("To become verified, upload a copy of your passport or driving license that matches the Credit Card owner. "),$this->billing_email, $this->account, $this->billing_email);
print "<p>";
printf (_("This copy will be kept on your profile until the credit card transaction has been approved. "));
print "
</td>
</tr>
";
print "
<form action=$this->url method='post' enctype='multipart/form-data'>
<input type='hidden' name='tab' value='payments'>
<input type='hidden' name='task' value='upload'>
<input type='hidden' name='MAX_FILE_SIZE' value=$max_file_size>
";
print "
<table class='table table-condensed table-striped'>";
print "
<tr>
<td>";
print _("Name printed on the Credit Card");
print "
</td>
<td colspan=2>
";
printf ("<input type=text size=35 name='name' value='%s'>",$_REQUEST['name']);
print "
</td>
</tr>
";
print "
<tr>
<td>";
print _("Scanned copy of your Passport or Driver License");
print "
</td>
<td colspan=2>
";
printf ("<input type='file' name='tmpfile'>");
print "
</td>
</tr>
";
if (in_array("free-pstn",$this->groups)) {
print "
<tr>
<td>";
print _("Mobile Number");
print "
</td>
<td colspan=2>
";
printf("<input type=text size=15 name='mobile_number' value='%s'> %s",$_REQUEST['mobile_number'],_("International format starting with +"));
print "
</td>
</tr>
";
}
print "
<tr>
<td>";
print _("Last 4 digits on your Credit Card");
print "
</td>
<td colspan=2>
";
printf("<input type=text size=5 name='last_digits' value='%s'>",$_REQUEST['last_digits']);
print "
</td>
</tr>
";
print "
<tr>
<td colspan=3>
";
print "
<input type=submit value=";
print _("Save");
print ">
</table>
</div>
</form>
";
}
}
function exportIdentityProof() {
$this->db = new DB_CDRTool();
$query=sprintf("select * from subscriber_docs
where username = '%s'
and domain = '%s'
and document = 'identity'",
addslashes($this->username),
addslashes($this->domain)
);
if (!$this->db->query($query)) {
print "<font color=red>";
printf ("Error for database query: %s (%s)", $this->db->Error,$this->db->Errno);
print "</font>";
}
if ($this->db->num_rows()) {
$this->db->next_record();
$h=sprintf("Content-type: %s",$this->db->f('file_type'));
Header($h);
$h=sprintf("Content-Disposition: attachment; filename=%s",$this->db->f('file_name'));
Header($h);
$h=sprintf("Content-Length: %s",$this->db->f('file_size'));
Header($h);
$this->db->p('file_content');
}
}
function showIdentityTab() {
$this->getEnumMappings();
$this->getAliases();
$chapter=sprintf(_("SIP Account"));
$this->showChapter($chapter);
print "
<div class='row-fluid'>
<div class=span12>
<table class='table table-condensed table-striped'>
<tr>
<td style=\"width: 20%\">";
print _("SIP Address");
print "</td>
<td>sip:$this->account</td>
</tr>";
/*
print "
<tr>
<td>";
print _("Full Name");
print "
</td>
<td>$this->fullName
</td>
</tr>
";
*/
print "
<tr>
<td>";
print _("Username");
print "</td>
<td>$this->username</td>
</tr>";
print "
<tr>
<td>";
print _("Domain/Realm");
print "</td>
<td>$this->domain</td>
</tr>";
print "
<tr>
<td>";
print _("Outbound Proxy");
print "</td>
<td>$this->sip_outbound_proxy</td>
</tr>
";
if ($this->xcap_root && !in_array("trunking", $this->groups)) {
print "
<tr>
<td>";
print _("XCAP Root");
print "
</td>
<td>$this->xcap_root
</td>
</tr>
";
}
print "</table></div></div>";
if ($this->pstn_access && $this->rpid) {
$chapter=sprintf(_("PSTN"));
$this->showChapter($chapter);
print "
<div class=row-fluid>
<div class=span12>
<table class='table table-condensed table-striped'><tr><td style=\"width: 20%\">";
print _("Caller-ID");
print "</td>
<td>$this->rpid</td>
</tr>
";
$t=0;
foreach($this->enums as $e) {
$t++;
$rr=floor($t/2);
$mod=$t-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "
<tr>
<td>";
print _("Phone Number");
print "</td>
<td>$e</td>
</tr>
";
}
print "</table></div></div>";
}
if (!in_array("trunking",$this->groups)) {
$chapter=sprintf(_("Aliases"));
$this->showChapter($chapter);
print "
<div class=row-fluid>
<div class=span12>";
printf (_("You may create new aliases for incoming calls"));
printf ("
</div>
</div>
");
$t=0;
print "
<form class=form-horizontal method=post name=sipsettings onSubmit=\"return checkForm(this)\">
";
foreach($this->aliases as $a) {
$t++;
$rr=floor($t/2);
$mod=$t-$rr*2;
if ($mod ==0) {
$_class='even';
} else {
$_class='odd';
}
print "
<div class='control-group $_class'>
<label for=aliases[] class=control-label>";
print _("SIP Alias");
print "
</label>
<div class='controls'><input type=text size=35 name=aliases[] value=\"$a\">
</div>
</div>
";
}
print "
<div class='control-ground $_class'>
<label for=aliases[] class=control-label>";
print _("New SIP Alias");
print "
</label>";
print "
<div class=controls>
<input type=hidden name=action value=\"set aliases\">
";
print '
<input name=aliases[] size="35" type="text">
</div><div class=form-actions>
<input class="btn" type="submit" value="';
print _("Save aliases");
print '" onClick=saveHandler(this)>
</div>
</div>
';
print $this->hiddenElements;
print "
</form>
";
}
if (!$this->isEmbedded() && $this->show_tls_section) {
if ($this->enrollment_url) {
include($this->enrollment_configuration);
if (is_array($enrollment)) {
$chapter=sprintf(_("TLS Certificate"));
$this->showChapter($chapter);
print "
<tr>
<td>";
print _("X.509 Format");
printf ("
</td>
<td><a href=%s&action=get_crt>Certificate</a>
</td>
</tr>
",$this->url);
/*
print "
<tr>
<td>";
print _("PKCS#12 store format");
printf ("
</td>
<td><a href=%s&action=get_p12>Certificate</a>
</td>
</tr>
<tr>
<td height=3 colspan=2></td>
</tr>",$this->url);
*/
}
}
}
print "
<form method=post>";
print "
<div class=well>
";
if ($this->email) {
printf (_("Email SIP Account information to %s"),$this->email);
print "
<input type=hidden name=action value=\"send email\">
<button class='btn btn-primary' type=submit>
<i class=\"icon-envelope icon-white\"> </i> ";
print _("Send");
print "</button>";
}
if ($this->sip_settings_page && $this->login_type != 'subscriber') {
print "<p>";
printf (_("Login using SIP credentials at <a href=%s>%s</a>"),$this->sip_settings_page,$this->sip_settings_page);
print "</p>";
}
print $this->hiddenElements;
print "
</div></form>
";
if($this->sip_settings_page) {
$this->getbalancehistory();
if (count($this->balance_history) == "0" || $this->login_type != 'subscriber') {
print "<form method=post><p>";
print "<input type=hidden name=action value=\"delete account\">";
$date1= new datetime($this->Preferences['account_delete_request']);
$today= new datetime('now');
if ($this->Preferences['account_delete_request'] && $this->login_type != 'subscriber' ) {
print "<p>User made a deletion request on: ";
print $this->Preferences['account_delete_request'];
print "</p>";
}
if ($date1->diff($today)->d >= '2' || $this->Preferences['account_delete_request'] == '' || $this->login_type != 'subscriber' ) {
print '<button data-original-title="';
print _("Delete request");
print "\" data-trigger=\"hover\" data-toggle=\"popover button\" data-content=\"";
print " You may request the deletion of your account here. An email confirmation is required to validate the request.\"";
print " rel='popover' class='btn btn-warning' type='submit'>";
print _("Delete request");
} else {
//print "<button rel='popover' class='btn btn-disabled'disabled type='submit'>";
//printf (_("Account remove request is active"));
print "A deletion request has been made on: ";
print $this->Preferences['account_delete_request'];
}
print "</button></p>";
}
print $this->hiddenElements;
print "
</form>
";
}
}
function showDownloadTab() {
if (in_array("trunking",$this->groups)) {
return false;
}
$chapter=sprintf(_("SIP Client download"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
$this->render_download_applet();
print "
</td>
</tr>
";
}
function showDIDTab() {
if (class_exists($this->did_processor_class)) {
$did_processor = new $this->did_processor_class();
}
if (!$_REQUEST['ddi_action']) {
$chapter=sprintf(_("Registered Numbers"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
$numbers=$did_processor->getOrders($this->account);
if (count($numbers)) {
print "<table border=0>";
printf ("<tr bgcolor=lightgray><td>Number</td><td>Country</td><td>Expire Date</td><td>Order</td><td>Action</td></tr>");
foreach (array_keys($numbers) as $_number) {
$t++;
$rr=floor($t/2);
$mod=$t-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
$form=sprintf("
<select name=period>");
$form.=sprintf ("<option value=1>1 %s",_("Month"));
$form.=sprintf ("<option value=3>3 %s",_("Months"));
$form.=sprintf ("<option value=6>6 %s",_("Months"));
$form.=sprintf ("<option value=12>12 %s",_("Months"));
$form.=sprintf ("<option value=24>24 %s",_("Months"));
$form.="</select>";
$form.=$this->hiddenElements;
$form.=sprintf ("<input type=hidden name='number' value='%s'>",$_number);
$form.=sprintf ("<input type=submit name='ddi_action' value='Renew'>");
$form.=sprintf ("<input type=submit name='ddi_action' value='Drop'>");
printf ("<tr class=$_class><td valign=top>+%s</td><td valign=top>%s</td><td valign=top>%s</td><td valign=top>%s</td><form method=post><td>%s</td></form></tr>",$_number,$numbers[$_number]['country_name'],$numbers[$_number]['did_expire_date_gmt'],$numbers[$_number]['order_id'],$form);
}
print "</table>";
}
print "
</td>
</tr>
";
}
if ($prefixes = $did_processor->getPrefixes()) {
if ($_REQUEST['ddi_action'] == 'register' && $_REQUEST['prefix'] && $_REQUEST['period']) {
$chapter=sprintf(_("Register New Number"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
$total=$prefixes[$_REQUEST['prefix']]['setup']+$prefixes[$_REQUEST['prefix']]['monthly']* $_REQUEST['period'];
$basket = array('ddi_number' => array('price' => sprintf("%.2f",$total),
'description' => sprintf(_('Telephone Number (+%s %s) for %d months'),$_REQUEST['prefix'],$prefixes[$_REQUEST['prefix']]['country_name'],$_REQUEST['period']),
'unit' => 'number',
'duration' => 'N/A',
'qty' => 1
)
);
$this->hiddenElements=sprintf("
<input type=hidden name=prefix value='%s'>
<input type=hidden name=period value='%s'>
<input type=hidden name=ddi_action value='register'>
",
$_REQUEST['prefix'],
$_REQUEST['period']
);
$data=array('customer_id' => $this->owner,
'country_iso' => $prefixes[$_REQUEST['prefix']]['country_iso'],
'city_prefix' => $prefixes[$_REQUEST['prefix']]['city_prefix'],
'period' => $_REQUEST['period'],
'map_data' => array(
'map_type' => 'URI',
'map_proto' => 'SIP',
'map_detail' => $this->account,
'map_pref_server' => 1
),
'prepaid_funds' => "0",
'uniq_hash' => md5(mt_rand())
);
$did_processor->createOrder($data);
/*
if (class_exists($this->payment_processor_class)) {
$payment_processor = new $this->payment_processor_class($this,$basket);
}
if ($payment_processor->transaction_results['success']) {
if ($did_processor->createOrder($data)) {
// add ENUM entry
} else {
// notify admin about payment without service fullfilment
}
}
*/
print "
</td>
</tr>
";
} else if ($_REQUEST['ddi_action'] == 'Renew' && $_REQUEST['number'] && $_REQUEST['period']) {
$chapter=sprintf(_("Renew Number"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
$data=array('customer_id' => $this->owner,
'did_number' => $_REQUEST['number'],
'period' => $_REQUEST['period'],
'uniq_hash' => md5(mt_rand())
);
print "Renewing number....";
$did_processor->renewOrder($data);
print "
</td>
</tr>
";
} else if ($_REQUEST['ddi_action'] == 'Drop' && $_REQUEST['number']) {
$chapter=sprintf(_("Cancel Number"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
$data=array('customer_id' => $this->owner,
'did_number' => $_REQUEST['number']
);
$did_processor->cancelOrder($data);
print "
</td>
</tr>
";
} else {
$chapter=sprintf(_("Register New Number"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
print "
<form method=post>";
print _("Select a region where you want to have a telephone number: ");
print "<p>";
print "<select name=prefix>";
foreach (array_keys($prefixes) as $prefix) {
if (!$found_country && $this->owner_information['country'] == $prefixes[$prefix]['country_iso']) {
$selected='selected';
$found_country=true;
} else {
$selected='';
}
if ($prefixes[$prefix]['setup']) {
printf ("<option value='%s' %s>%s %s (+%s) - Setup %s USD, Monthy %s USD",$prefix,$selected,$prefixes[$prefix]['country_name'],$prefixes[$prefix]['city_name'],$prefix,$prefixes[$prefix]['setup'],$prefixes[$prefix]['monthly']);
} else {
printf ("<option value='%s' %s>%s %s (+%s) - Monthy %s USD",$prefix,$selected,$prefixes[$prefix]['country_name'],$prefixes[$prefix]['city_name'],$prefix,$prefixes[$prefix]['monthly']);
}
}
print "</select>";
print "<p>";
print _("Select the duration for which you want to use the telephone number: ");
print "<p>";
print "<select name=period>";
printf ("<option value=1>1 %s",_("Month"));
printf ("<option value=3>3 %s",_("Months"));
printf ("<option value=6>6 %s",_("Months"));
printf ("<option value=12>12 %s",_("Months"));
printf ("<option value=24>24 %s",_("Months"));
print "</select>";
print $this->hiddenElements;
print "<p>";
print "<input type=hidden name='ddi_action' value='register'>";
print "<input type=submit value='Purchase'>";
print "
</form>
";
}
print "
</td>
</tr>
";
} else {
print "<p><font color=red>Error fetching DDI prefixes</font>";
}
print "
</td>
</tr>
";
}
function showSupportTab() {
$chapter=sprintf(_("Support"));
$this->showChapter($chapter);
print "
<tr class=odd>
<td colspan=2>";
print "<p>";
printf (_("To request support you may send an e-mail to %s"),$this->support_email);
if ($this->support_web) {
print "<p>";
printf (_("For more information visit %s"),$this->support_web);
}
print "
</td>
</tr>
";
}
function render_download_applet() {
$this->valid_os=array('nt','mac');
require("browser.php");
$os=browser_detection('os');
if ($this->create_certificate) {
if ($_passport = $this->generateCertificate()) {
$_account['passport'] = $_passport;
}
}
$_account['sip_address'] = $this->account;
$_account['display_name'] = sprintf("%s %s",$this->firstName,$this->lastName);
$_account['password'] = $this->password;
$_account['web_password'] = $this->Preferences['web_password'];
$_account['email'] = $this->email;
$_account['settings_url'] = $this->digest_settings_page;
$_account['xcap_root'] = $this->xcap_root;
$_account['outbound_proxy'] = $this->sip_proxy;
if ($this->enrollment_url) {
include($this->enrollment_configuration);
if (is_array($enrollment)) {
$_account['msrp_relay'] = $enrollment['msrp_relay'];
$_account['conference_server'] = $enrollment['conference_server'];
$_account['settings_url'] = $enrollment['settings_url'];
if ($enrollment['ldap_hostname']) {
$_account['ldap_hostname'] = $enrollment['ldap_hostname'];
}
if ($enrollment['ldap_dn']) {
$_account['ldap_dn'] = $enrollment['ldap_dn'];
}
}
}
if ($this->store_clear_text_passwords=='false') {
$match_password=false;
if ($_REQUEST['password']) {
$str=$this->result->id->username.":".$this->result->id->domain.":".$_REQUEST['password'];
if (md5($str) == $this->result->ha1) {
$_account['password']=$_REQUEST['password'];
$match_password=true;
}
}
if (!$match_password){
print "<form method='POST' id='password_download' class='form-horizontal' action='$this->url'><p>";
print _("Please enter your SIP account password: ");
if ($_REQUEST['password'] || $_REQUEST['continue']) {
print "</p><div id='pass_group' class='control-group error'>";
} else {
print "</p><div id='pass_group' class=control-group>";
}
print "<label class=control-label>";
print _("Password");
print "</label>";
print "<div id='controls_password' class=controls>";
print "<input class='input' type='password' id='password' name='password' placeholder='";
print _("Enter your password");
print "'' value='";
print $_REQUEST['password'];
print "'>";
if ($_REQUEST['password'] || $_REQUEST['continue']) {
print "<span id=\"help-text\" class=\"help-inline\">Entered password does not match your account</span>";
}
print "</div></div>";
print "<input type='hidden' name='tab' value='download'>";
print "<div class='form-actions'>";
print "<input type=submit value='Continue' class='btn btn-primary'>";
print "<input type='hidden' name='continue' value='1'>";
print "</div></form>";
$class='hide';
}
}
print "<div class=$class id='java_buttons'><table border=0>";
if (in_array($os,$this->valid_os)) {
print "<tr><td>";
printf (_("Download and install <a href=%s target=blink>%s</a> preconfigured with your SIP account:"), $this->blink_download_url, $this->show_download_tab);
print "</td></tr>";
print "<tr><td>";
printf ("<applet code='com.agprojects.apps.browserinfo.BlinkConfigure' archive='blink_download.jar?version=%s' name='BlinkDownload' height='35' width='250' align='left'>
<param name='label_text' value='Download'>
<param name='click_label_text' value='Downloading...'>
<param name='download_url' value='%s'>
<param name='file_name' value=''>
<param name='file_content' value='%s'>
</applet>",
rand(),
$this->blink_download_url,
rawurlencode(json_encode($_account))
);
print "</td></tr>";
} else {
print "<tr><td>";
print "<p>";
printf (_("To download %s visit <a href='%s' target=blink>%s</a>"),$this->show_download_tab, $this->blink_download_url, $this->blink_download_url);
print "</td></tr>";
}
print "<tr><td>";
printf (_("If you have already installed %s, you can configure it to use your SIP account:"), $this->show_download_tab);
print "</td></tr>";
print "<tr><td>";
printf ("<applet code='com.agprojects.apps.browserinfo.BlinkConfigure' archive='blink_download.jar?version=%s' name='BlinkConfigure' height='35' width='250' align='left'>
<param name='label_text' value='Configure this account'>
<param name='click_label_text' value='Please restart %s now!'>
<param name='download_url' value=''>
<param name='file_name' value=''>
<param name='file_content' value='%s'>
</applet>",
rand(),
$this->show_download_tab,
urlencode(json_encode($_account))
);
print "</td></tr>";
print "</table>";
print "<p>";
printf ("Notes. ");
print _("<a href='http://www.java.com/en/download/manual.jsp'>Java Runtime Environment</a> (JRE) must be activated in the web browser. ");
print "</div>";
}
function showFooter() {
print "
<div class='pull-right'>";
if ($this->footerFile) {
include ("$this->footerFile");
} else {
print "<a href=http://ag-projects.com target=agprojects><img src=images/PoweredbyAGProjects.png border=0></a>";
}
print "</div>
";
}
function showSettingsTab() {
$use_yubikey=0;
/*
if (stream_resolve_include_path('Auth/Yubico.php')) {
require_once 'Auth/Yubico.php';
$use_yubikey=1;
}
*/
$this->getVoicemail();
print "
<form class=form-horizontal method=post name=sipsettings onSubmit=\"return checkForm(this)\">
";
$chapter=sprintf(_("SIP Account"));
$this->showChapter($chapter);
if ($this->login_type != "subscriber" ) {
print "
<div class='control-group even'>
<label class='control-label' for='first_name'>";
print _("First Name");
print "
</label>";
print "<div class=\"controls\"><input class=input-medium type=text size=15 name=first_name value=\"$this->firstName\">";
print "
</div>
</div>
";
print "
<div class='control-group odd'>
<label class='control-label' for='last_name'>";
print _("Last Name");
print "</label>
<div class='controls'>";
print "<input class=input-medium type=text size=15 name=last_name value=\"$this->lastName\">";
print "
</div>
</div>
";
}
print "
<div class='control-group even'>
<label class='control-label' for='sip_password'>";
print _("Password");
print "
</label>
<div class='controls'>";
if ($this->login_type == 'subscriber' && in_array("deny-password-change",$this->groups)) {
print _("Password can be changed only by the operator");
} else {
print '<input class=input-medium type=password size=15 name=sip_password rel="popover" title="" data-original-title="';
print _("Password");
print "\" data-trigger=\"focus\" data-toggle=\"popover\" data-content=\"";
print _("Enter text to change the current password");
print "\">";
printf ("\n\n<!-- \nSIP Account password: %s\n -->\n\n",$this->password);
}
print "</span>
</div>
</div>
";
print "
<div class='control-group odd'>
<label class='control-label' for='web_password'>";
print _("Web Password");
print "
</label>
<div class='controls'><div>";
print '<input class=input-medium type=password size=15 name=web_password rel="popover" title="" data-original-title="';
print _("Web Password");
print "\" data-trigger=\"focus\" data-toggle=\"popover button\" data-content=\"";
print _("Enter text to change the password to access this web page");
print "\">";
// print '<span class=help-inline>';
print ' <label class="checkbox inline">';
print '<input type="checkbox" name="web_password_reset" value="1"> ';
print 'Remove web password';
print '</label>';
//print _("Enter text to change the password to access this web page");
print "
</div></div>
</div>
";
if ($use_yubikey == 1 && !$this->isEmbedded()) {
print "
<div class='control-group odd'>
<label class='control-label' for='yubykey'>";
print _("Yubikey");
print "
</label>
<div class=controls>";
print "<input class=input-medium type=text size=12 maxlength=12 rel='popover' title=\"\" data-original-title='";
print _("Yubikey");
print "' data-trigger=\"focus\" data-toggle=\"popover\" data-content=\"";
print _("Enter <strong>Yubikey id</strong> to allow SIP Account + Yubikey login to access this webpage.<br /><br/>The Yubikey id is the first 12 digits of the string generated by the key.<br /><br/>It can be set by clicking in this text field and pressing your Yubikey.");
printf ("\"name=yubikey value=\"%s\"><span class=help-inline>",$this->Preferences['yubikey']) ;
print _("Enter Yubikey id");
print "</span>
</div>
</div>
";
//print '<pre>';
//print($this->Preferences['yubikey']);
//print_r($this);
//print '</pre>';
}
print "
<div class='control-group even'>
<label class='control-label' for='language'>";
print _("Language");
print "
</label>
<div class=controls>";
print "
<select class=input-medium name=language>
";
$selected_lang[$this->Preferences['language']]="selected";
foreach (array_keys($this->languages) as $_lang) {
printf ("<option value='%s' %s>%s\n",$_lang,$selected_lang[$_lang],$this->languages[$_lang]['name']);
}
print "
</select>
</div></div>
";
print "
<div class='control-group odd'>
<label class='control-label' for='timezone'>";
print _("Timezone");
print "
</label>
<div class=controls>
";
$this->showTimezones('timezone',$this->timezone);
print " ";
$timestamp=time();
$LocalTime=getLocalTime($this->timezone,$timestamp);
print "<span class=help-inline>";
print _("Local Time");
print ": $LocalTime";
//dprint_r($this->availableGroups);
print "</span>
</div>
</div>
";
if (count($this->emergency_regions) > 0) {
print "
<div class='control-group'>
<label class='control-label' for='region'>";
print _("Location");
print "
</label>
<div class=controls>
";
print "<select name=region>";
$selected_region[$this->region]="selected";
foreach (array_keys($this->emergency_regions) as $_region) {
printf ("<option value=\"%s\" %s>%s",$_region,$selected_region[$_region],$this->emergency_regions[$_region]);
}
print "</select>";
print "
</div>
</div>
";
}
if ($this->pstn_access) {
if (in_array("free-pstn",$this->groups)) {
if (in_array("quota",$this->groups)) {
$_class="alert alert-error";
} else {
$_class="";
}
if ($this->pstn_changes_allowed) {
print "
<div class='control-group'>
<div class='$_class'>
<label class=control-label>";
print _("Quota");
print "
</label>
<div class='controls'><div class='input-prepend'>";
printf ("<span class='add-on'>%s</span><input class=input-medium type=text size=6 maxsize=6 name=quota value='%s'></div><span class='help-inline muted'>",$this->currency,$this->quota);
//print "<div class=span10>";
if ($this->quota || in_array("quota",$this->groups)) {
$this->getCallStatistics();
if ($this->thisMonth['price']) {
printf (_("This month usage: %.2f %s"),$this->thisMonth['price'], $this->currency);
printf (" / %d ",$this->thisMonth['calls']);
print _("Calls ");
}
}
print "</span> ";
if ($this->pstn_changes_allowed) {
print "<label class='checkbox inline'>";
print "
<input type=checkbox name=quota_deblock value=1> ";
print _("Un-block");
print "</label>";
}
print "</div></div>
</div>
";
} else if ($this->quota) {
print "
<div class='control-group'>
<label class=control-label>";
print _("Quota");
print "
</label>
<div class='controls $_class'>
<span style='padding-top:5px; margin-bottom:5px;display:block;'>
";
printf ("%s %s ",$this->quota,$this->currency);
$this->getCallStatistics();
if ($this->thisMonth['price']) {
printf (_("This month usage: %.2f %s"),$this->thisMonth['price'], $this->currency);
printf (" / %d ",$this->thisMonth['calls']);
print _("Calls");
}
print "</span></div>
</div>
";
}
}
if ($this->prepaid) $checked_box_prepaid="checked";
if (!$this->prepaid_changes_allowed) $disabled_box_prepaid = "disabled=true";
print "
<div class='control-group'>
<label class=control-label for=prepaid>";
print _("Prepaid");
print "</label>
<div class=controls>
<label class=checkbox>
<input type=checkbox value=1 name=prepaid $checked_box_prepaid $disabled_box_prepaid>
</label>
</div>
</div>
";
}
foreach (array_keys($this->availableGroups) as $key) {
unset($disabled_box);
if ($this->login_type == 'subscriber' && !$this->availableGroups[$key]['SubscriberMaySeeIt']) {
continue;
}
if ($this->login_type == 'reseller' && !$this->availableGroups[$key]['ResellerMaySeeIt']) {
continue;
}
if (in_array($key,$this->groups)) {
$checked_box[$key]="checked";
}
$elementName = $this->availableGroups[$key]["WEBName"];
$elementComment = $this->availableGroups[$key]["WEBComment"];
if ($this->login_type == 'subscriber') {
if ($this->availableGroups[$key]['SubscriberMayEditIt']) {
$disabled_box = "";
} else {
$disabled_box = "disabled=true";
}
} elseif ($this->login_type == 'reseller') {
if ($this->availableGroups[$key]['ResellerMayEditIt']) {
$disabled_box = "";
} else {
$disabled_box = "disabled=true";
}
}
if ($key=="free-pstn" && !$this->pstn_changes_allowed) {
$disabled_box = "disabled=true";
}
if ($key=="blocked" && $checked_box[$key]) {
$_class="alert alert-error";
$_class1="error";
} else {
$_class="";
$_class1='';
}
print "
<div class='control-group $_class1'>
<label class=control-label>$elementName</label>
<div class='controls $_class'>
";
if ($key=="blocked") {
if ($this->Preferences['blocked_by']) {
$selected_blocked_by[$this->Preferences['blocked_by']]='selected';
} else if ($checked_box[$key]) {
$selected_blocked_by['reseller']='selected';
}
if ($this->login_type == 'admin' || $this->login_type == 'reseller') {
if ($this->customer != $this->reseller || $selected_blocked_by['customer']) {
printf ("
<select name=%s>
<option value=''>Active
<option value='customer' %s> %s (%d)
<option value='reseller' %s> %s (%d)
</select>
",
$key,
$selected_blocked_by['customer'],
_("Blocked by Customer"),
$this->customer,
$selected_blocked_by['reseller'],
_("Blocked by Reseller"),
$this->reseller
);
} else if ($this->reseller) {
printf ("
<select name=%s>
<option value=''>%s
<option value='reseller' %s> %s (%d)
</select>
",
$key,
_("Active"),
$selected_blocked_by['reseller'],
_("Blocked by Reseller"),
$this->reseller
);
} else {
printf ("
<select name=%s>
<option value=''>%s
<option value='reseller' %s> %s
</select>
",
$key,
_("Active"),
$selected_blocked_by['reseller'],
_("Blocked")
);
}
} else if ($this->login_type == 'customer' ) {
if (in_array($key,$this->groups)) {
if ($this->Preferences['blocked_by'] != 'reseller') {
printf ("
<select name=%s>
<option value=''>%s
<option value='customer' %s> %s
</select>
",
$key,
_("Active"),
$selected_blocked_by['customer'],
_("Blocked")
);
} else {
print _("Blocked by Reseller");
}
} else {
printf ("
<select name=%s>
<option value=''>%s
<option value='customer' %s> %s
</select>
",
$key,
_("Active"),
$selected_blocked_by['customer'],
_("Blocked")
);
}
} else {
if (in_array($key,$this->groups)) {
print _("Blocked");
} else {
print _("Active");
}
}
} else if ($key=="free-pstn") {
if ($this->pstn_changes_allowed) {
print "<label class='checkbox inline' style=\"padding-top: 1px; line-height:14px\">
<input type='checkbox' value=1 class='inline' name=$key $checked_box[$key] $disabled_box>
";
print "$elementComment";
print "</label> <input id='rpid_input'style='display:inline-block' class=input-medium type=text size=15 maxsize=15 name=rpid value=\"$this->rpid\">";
} else {
print "<label class='checkbox inline' style=\"padding-top: 5px; line-height:14px\">
<input type='checkbox' value=1 class='inline' name=$key $checked_box[$key] $disabled_box>
";
if ($this->rpid) {
print "$elementComment: $this->rpid </label>";
} else {
print "$elementComment</label>";
}
}
} else {
print "
<label class=checkbox><input type=checkbox value=1 name=$key $checked_box[$key] $disabled_box>$elementComment</label>
";
}
print "
</div>
</div>
";
}
$this->showExtraGroups();
$this->showOwner();
$this->showQuickDial();
$this->showMobileNumber();
$this->showIPAccessList();
$this->showCallLimit();
print "
<div class='control-group even'>
<label for=timeout class=control-label>";
print _("No-answer Timeout");
printf ("
</label>
<div class='controls'>
<div class='input-append'>
");
print "<input rel='popover' class=input-medium name=timeout title=\"\" data-original-title='";
print _("No-answer Timeout");
print "' data-trigger=\"focus\" data-toggle=\"popover\" data-content=\"";
print _("Used to determined after how many seconds the Forwarding action for this condition will occur");
printf ("\" value='%d' size=3 type=number max=\"900\"><span class='add-on'>s</span>",$this->timeout);
print "
</div>
</div>
</div>
";
if (in_array("free-pstn",$this->groups) && !$this->show_barring_tab) {
print "
<div class='row-fluid odd'>
<label for=extra class=control-label>";
print _("Tabs");
print "
</label>
<div id='extra' class=controls>";
if ($this->Preferences['show_barring_tab']){
$check_show_barring_tab="checked";
} else {
$check_show_barring_tab="";
}
printf ("<label class='checkbox'><input type=checkbox %s value=1 name='show_barring_tab'>%s</label>\n",$check_show_barring_tab,_("Barring"));
print "
</div>
</div>
";
}
$this->showVoicemail();
$this->showBillingProfiles();
$chapter=sprintf(_("Notifications Address"));
$this->showChapter($chapter);
print "
<div class='control-group even'>
<label for=mailto class=control-label>";
print _("Email Address");
print "
</label>
<div class=controls>
<input class=span3 type=text size=40 maxsize=255 name=mailto value=\"$this->email\">
</div>
</div>
";
print "
<input type=hidden name=action value=\"save settings\">
";
print "<div class='form-actions'>
<input class='btn' type=submit value=\"";
print _("Save");
print "\"
onClick=saveHandler(this)>
";
print "
</div>
";
print $this->hiddenElements;
print "
</form>
";
}
function showDiversionsTab () {
if (in_array("trunking",$this->groups)) {
return false;
}
$this->getVoicemail();
$this->getEnumMappings();
$this->getDivertTargets();
$this->getDiversions();
print "
<form class=form-horizontal method=post name=sipsettings onSubmit=\"return checkForm(this)\">
";
$chapter=sprintf(_("Call Forwarding"));
$this->showChapter($chapter);
$this->showDiversions();
print "
<div class=form-actions>
<input type=hidden name=action value=\"set diversions\">
";
print "
<input class='btn' type=submit value=\"";
print _("Save");
print "\"
onClick=saveHandler(this)>
";
print "
</div>
";
print $this->hiddenElements;
print "
</form>
";
}
function showVoicemail() {
if ($this->voicemail['Account']) {
$checked_voicemail="checked";
}
$chapter=sprintf(_("Voice Mailbox"));
$this->showChapter($chapter);
print "
<div class='control-group even'>
<label for=voicemail class=control-label>";
print _("Enable");
print "</label>
<div class=controls>
<label class=checkbox>
<input type=checkbox value=1 name=voicemail $checked_voicemail $disabled_box>";
if ($this->voicemail['Account'] &&
($this->login_type != 'subscriber')) {
print " (";
print _("Mailbox");
printf (" %s) ",$this->voicemail['Account']);
}
print "</label>
</div>
</div>
";
if ($this->voicemail['Account']) {
print "
<div class='control-group odd'>
<label for=delete_voicemail class=control-label>";
print _("Delivery");
print "</label>
<div class='controls'>
";
if ($this->voicemail['Options']->delete=="True") {
$checked_delete_voicemail="checked";
$selected_store_voicemail['email'] ="selected";
$selected_store_voicemail['server'] ="";
} else {
$selected_store_voicemail['email'] ="";
$selected_store_voicemail['server'] ="selected";
}
if (!$this->voicemail['DisableOptions']) {
print "<select class=span6 name=delete_voicemail>";
$_text=sprintf(_("Send voice messages by e-mail to %s"),$this->email);
printf ("<option value=1 %s>%s",$selected_store_voicemail['email'],$_text);
printf ("<option value=0 %s>%s",$selected_store_voicemail['server'],_("Send messages by e-mail and store messages on the server"));
print "</select>";
} else {
printf (_("Voice messages are sent by email to %s"),$this->email);
}
print "
</div>
</div>
";
if (!$this->voicemail['DisableOptions']) {
print "
<div class='control-group even'>
<label for=voicemail_password class=control-label>";
print _("Password");
print "</label>
<div class=controls>
";
printf ("<input class=input-medium type=text size=15 name=voicemail_password value=\"%s\">",$this->voicemail['Password']);
print "
</div>
</div>
";
if ($this->voicemail_access_number) {
print "
<div class=row-fluid>
<div class=span1></div>
<div class='offset1 span10'>
<div class=\"alert alert-info\">";
printf(_("Dial %s to listen to your messages or change preferences. "),$this->voicemail_access_number);
print "</div></div>
</div>
";
}
}
}
}
function showOwner() {
if ($this->login_type == 'subscriber') {
//print "<input type=hidden name=owner value=\"$this->owner\">";
return true;
}
print "
<div class='control-group'>
<label for=owner class=control-label>";
print _("Owner");
print "</label>
<div class=controls>
<input class=input-medium type=text name=owner size=7 rel='popover' title data-original-title='";
print _("Owner");
print "' data-trigger=\"focus\" data-toggle=\"popover\" data-content=\"";
print _("Used to link the SIP account to the customer details stored in another database like the platform customer database. Only integer values are allowed.");
print "\" value=\"$this->owner\">";
print "
</div>
</div>
";
}
function showDevicesTab() {
$this->getDeviceLocations();
if (count($this->locations)) {
$chapter=sprintf(_("SIP Devices"));
$this->showChapter($chapter);
$j=0;
print "
<div class=row-fluid>
<table class='table table-condensed table-striped'>";
foreach (array_keys($this->locations) as $location) {
$j++;
$contact = $this->locations[$location]['contact'];
$publicContact = $this->locations[$location]['publicContact'];
$expires = normalizeTime($this->locations[$location]['expires']);
$user_agent = $this->locations[$location]['user_agent'];
$transport = $this->locations[$location]['transport'];
$UAImage = $this->getImageForUserAgent($user_agent);
$rr=floor($j/2);
$mod=$j-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "<tr><td align=center>";
printf ("<img src='%s/30/%s' border=0>",$this->SipUAImagesPath,$UAImage);
print "</td>";
print "<td>";
print "<i>$user_agent</i>";
if ($transport == 'tls') print "&nbsp;<i class='icon-lock'></i>";
print "<br><span class='label label-info'>";
print _("Location");
print "</span>";
print " ";
if (strlen($transport)) print "$transport:";
print "$contact ";
if ($publicContact != $contact) {
print " ($publicContact) ";
}
if ($publicContact) {
$_els=explode(":",$publicContact);
if ($_loc=geoip_record_by_name($_els[0])) {
$this->geo_location=$_loc['country_name'].'/'.utf8_encode($_loc['city']);
} else if ($_loc=geoip_country_name_by_name($_els[0])) {
$this->geo_location=$_loc;
} else {
$this->geo_location='';
}
printf ("%s",$this->geo_location);
}
print "</td><td>$expires</td>";
print "</tr>";
}
print "</table></div>";
}
}
function getBarringPrefixes() {
dprint("getBarringPrefixes()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getBarringPrefixes($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
$this->barring_prefixes=$result;
return true;
}
function setBarringPrefixes() {
dprint("setBarringPrefixes");
$prefixes=array();
$barring_prefixes=$_REQUEST['barring_prefixes'];
foreach ($barring_prefixes as $_prefix) {
if (preg_match("/^\+[1-9][0-9]*$/",$_prefix)) {
$prefixes[]=$_prefix;
}
}
dprint("setBarringPrefixes");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setBarringPrefixes($this->sipId,$prefixes);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
function showBarringTab() {
$chapter=sprintf(_("Barred Destinations"));
$this->showChapter($chapter);
print "
<form class=form-horizontal method=post name=sipsettings onSubmit=\"return checkForm(this)\">
";
print "
<div class=row-fluid>
<div class=span12>";
print _("You can deny outbound calls to unwanted PSTN prefixes. ");
print "</div></div>";
print "
<div class=control-group>
<label class=control-label for=barring_prefixes[]>";
print _("Destination Prefix");
print "</label>";
print "<div class=controls>
<input type=text name=barring_prefixes[]>
";
print "<span class=help-inline>";
print _("Example");
print ": +31900";
print "
</span>
</div></div>
";
if ($this->getBarringPrefixes()) {
foreach ($this->barring_prefixes as $_prefix) {
$found++;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod == 0) {
$_class='odd';
} else {
$_class='even';
}
print "
<div class='control-group $_class'>";
print "<label for=barring_prefixes[] class=control-label>";
print _("Destination Prefix");
print "</label>";
print "<div class=controls>
<input type=text name=barring_prefixes[] value=\"$_prefix\">
</div>";
print "</div>";
}
}
print "
<input type=hidden name=action value=\"set barring\">
";
print "<div class=form-actions>
<input class=btn type=submit value=\"";
print _("Save");
print "\"
onClick=saveHandler(this)>
";
print "</div>
</div>
</div>
";
print $this->hiddenElements;
print "
</form>
";
}
function saveSettings() {
$this->getVoicemail();
/*
$this->getEnumMappings();
$this->getDivertTargets();
$this->getDiversions();
*/
$this->changedFields=array();
$this->sendCEmail=0;
foreach ($this->form_elements as $el) {
${$el} = $_REQUEST[$el];
}
$newACLarray = array();
$result = $this->result;
if (!is_array($result->properties)) $result->properties=array();
if (!is_array($result->groups)) $result->groups=array();
if ($mailto && $this->email != $mailto) {
$result->email=$mailto;
$this->email=$mailto;
$this->somethingChanged=1;
$this->voicemailOptionsHaveChanged=1;
$this->sendCEmail=1;
array_push($this->changedFields,"Email Address");
}
if ($this->login_type != "subscriber") {
if ($first_name && $this->firstName != $first_name) {
$result->firstName = $first_name;
$this->firstName = $first_name;
$this->somethingChanged=1;
$this->voicemailOptionsHaveChanged=1;
}
if ($last_name && $this->lastName != $last_name) {
$result->lastName = $last_name;
$this->lastName = $last_name;
$this->somethingChanged=1;
}
}
$this->properties=$result->properties;
$this->availableGroups['voicemail']=array("Group"=>"voicemail",
"WEBName" =>sprintf (_("Voice Mailbox")),
"SubscriberMayEditIt"=>"1",
"SubscriberMaySeeIt"=>0
);
if (!$this->voicemail['Account'] && $voicemail) {
if ($this->addVoicemail()) {
$this->setVoicemailDiversions();
$this->createdVoicemailnow=1;
}
} else if ($this->voicemail['Account'] && !$voicemail) {
if ($this->deleteVoicemail()) {
$this->voicemail['Account']="";
$this->removeVoicemailDiversions();
}
}
if ($this->pstn_changes_allowed) {
if (strcmp($quota,$this->quota) != 0) {
if (!$quota) $quota=0;
$result->quota=intval($quota);
dprint ("change the quota");
$this->somethingChanged=1;
}
if ($quota_deblock) {
$result->groups = array_unique(array_diff($this->groups,array('quota')));
$this->somethingChanged=1;
$this->SipPort->addHeader($this->SoapAuth);
$this->SipPort->removeFromGroup(array("username" => $this->username,"domain"=> $this->domain), "quota");
}
$rpid=trim($rpid);
if (strcmp($rpid,$this->rpid) != 0) {
dprint ("change the rpid");
$result->rpid=$rpid;
$this->somethingChanged=1;
}
if ($this->CallLimitChangePolicy()) {
if ($this->soapEngines[$this->sip_engine]['call_limit']) {
if (isset($callLimit) && $this->callLimit != $callLimit) {
$result->callLimit=intval($callLimit);
$this->somethingChanged=1;
}
}
}
}
$owner=intval($owner);
if ($owner != $this->owner && $this->login_type != 'subscriber') {
dprint ("change the owner");
$result->owner=$owner;
$this->somethingChanged=1;
} else {
$result->owner=$this->owner;
}
if ($this->prepaid_changes_allowed) {
if(!$result->prepaid && $_REQUEST['prepaid']){
if ($result->quota) {
$this->somethingChanged=1;
}
$this->somethingChanged=1;
} else if ($result->prepaid && !$_REQUEST['prepaid']) {
$this->somethingChanged=1;
}
$result->prepaid=intval($_REQUEST['prepaid']);
}
reset($this->availableGroups);
foreach (array_keys($this->availableGroups) as $key) {
// $val is set to 1 if web checkbox is ticked
$val = $_REQUEST[$key];
if ($this->login_type != 'subscriber' || $this->availableGroups[$key]['SubscriberMayEditIt']) {
if ($key == 'free-pstn') {
if (in_array($key,$this->groups) && !$val) {
if ($this->quota) {
// we save quota for later use when pstn access is re-granted
$this->somethingChanged=1;
$this->setPreference('last_sip_quota',"$this->quota");
}
$this->somethingChanged=1;
} else if (!in_array($key,$this->groups) && $val) {
if (!$this->prepaid_changes_allowed) {
$this->somethingChanged=1;
$result->prepaid=1;
}
}
if (!in_array($key,$this->groups) && $val) {
$this->setPreference('last_sip_quota',strval($this->quota));
$last_sip_quota=$this->Preferences['last_sip_quota'];
if ($last_sip_quota) {
$result->quota=intval($last_sip_quota);
$this->somethingChanged=1;
}
}
if ($this->pstn_changes_allowed) {
if ($val) $newACLarray[]=trim($key);
} else {
if (in_array($key,$this->groups)) {
$newACLarray[]=trim($key);
}
}
} else if ($key == 'trunking') {
if ($this->login_type == 'admin' || $this->login_type == 'reseller') {
if (!$val && in_array($key,$this->groups)) {
# TODO remove diversions
}
}
if ($val) $newACLarray[]=trim($key);
} else if ($key == 'blocked') {
if ($this->login_type == 'admin' || $this->login_type == 'reseller') {
if ($val && $val != $this->Preferences['blocked_by']) {
$this->setPreference('blocked_by',$val);
$this->somethingChanged=1;
} else if (!$val && in_array($key,$this->groups)) {
$this->somethingChanged=1;
$this->setPreference('blocked_by','');
}
if ($val) $newACLarray[]=trim($key);
} else if ($this->login_type == 'customer' ) {
if ($this->Preferences['blocked_by'] != 'reseller') {
if ($val && ($val != $this->Preferences['blocked_by'] || !in_array($key,$this->groups) )) {
$this->setPreference('blocked_by',$val);
$this->somethingChanged=1;
$newACLarray[]=trim($key);
} else if (!$val && in_array($key,$this->groups)) {
$this->somethingChanged=1;
$this->setPreference('blocked_by','');
}
if ($val) $newACLarray[]=trim($key);
} else {
// copy old setting if exists
if (in_array($key,$this->groups)) {
$newACLarray[]=trim($key);
}
}
}
} else if ($key == 'sms') {
if ($this->sms_changes_allowed) {
if (!$val && in_array($key,$this->groups)) {
$this->somethingChanged=1;
} else if ($val && !in_array($key,$this->groups)) {
$this->somethingChanged=1;
}
if ($val) $newACLarray[]=trim($key);
} else {
// copy old setting if exists
if (in_array($key,$this->groups)) {
$newACLarray[]=trim($key);
}
}
} else {
if ($val) $newACLarray[]=trim($key);
}
} else {
// copy old setting if exists
if (in_array($key,$this->groups)) {
$newACLarray[]=trim($key);
}
}
}
$foundGroupInAvailableGroups=array();
$extra_groups=explode(' ',$_REQUEST['extra_groups']);
foreach ($extra_groups as $_grp) {
if (!in_array($_grp,array_keys($this->availableGroups))) {
$newACLarray[]=$_grp;
}
}
$grantACLarray = array_unique(array_diff($newACLarray,$this->groups));
$revokeACLarray = array_unique(array_diff($this->groups,$newACLarray));
/*
dprint_r($this->groups);
dprint_r($newACLarray);
dprint_r($grantACLarray);
dprint_r($revokeACLarray);
*/
if (count($revokeACLarray) || count($grantACLarray)) {
$result->groups=$newACLarray;
$this->somethingChanged=1;
}
if ($language && $language != $this->Preferences['language'] ) {
if ($this->login_type == 'subscriber') {;
//print("Set lang $language");
$this->changeLanguage($language);
}
$this->setPreference("language",$language);
$this->somethingChanged=1;
}
if ($show_barring_tab != $this->Preferences['show_barring_tab'] ) {
$this->setPreference("show_barring_tab",$show_barring_tab);
$this->somethingChanged=1;
}
if ($this->Preferences['account_delete_request'] ) {
$this->setPreference("account_delete_request",date('m/d/Y h:i:s a', time()));
$this->somethingChanged=1;
}
if ($this->login_type == 'subscriber' && in_array("deny-password-change",$this->groups)) {
} else if ($sip_password) {
if ($this->store_clear_text_passwords) {
$result->password=$sip_password;
} else {
$md1=strtolower($this->username).':'.strtolower($this->domain).':'.$sip_password;
$md2=strtolower($this->username).'@'.strtolower($this->domain).':'.strtolower($this->domain).':'.$sip_password;
$result->password=md5($md1).':'.md5($md2);
}
$this->sendCEmail=1;
array_push($this->changedFields,"Password");
$this->somethingChanged=1;
}
if ($web_password) {
if ($this->store_clear_text_passwords) {
$web_password_new=$web_password;
} else {
$md1=strtolower($this->username).':'.strtolower($this->domain).':'.$web_password;
$md2=strtolower($this->username).'@'.strtolower($this->domain).':'.strtolower($this->domain).':'.$web_password;
$web_password_new=md5($md1).':'.md5($md2);
}
$this->setPreference('web_password',$web_password_new);
$this->sendCEmail=1;
array_push($this->changedFields,"Web password");
$this->somethingChanged=1;
}
if ($web_password_reset) {
$this->setPreference('web_password','remove');
$this->somethingChanged=1;
}
if ($this->Preferences['yubikey'] != $yubikey && !$this->isEmbedded()) {
$this->setPreference('yubikey',$yubikey);
$this->somethingChanged=1;
}
if (is_array($result->acl) and count($result->acl)) {
foreach (array_keys($result->acl) as $key) {
if (isset($result->acl[$key]->tag) && $result->acl[$key]->tag == '') {
unset($result->acl[$key]->tag);
}
}
}
if ($this->IPAccessListChangePolicy()) {
if (isset($ip_access_list) and $this->ip_access_list != $ip_access_list) {
$ip_access_list=preg_replace("/\s+/","\n", trim($ip_access_list));
$list=explode("\n", trim($ip_access_list));
$ip_access_list=array();
foreach ($list as $el) {
list($ip,$mask) = explode("/",$el);
if ($mask <0 or $mask > 32) {
continue;
}
if (!preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/",$ip)) {
continue;
}
$ip_access_list[]=array('ip'=>$ip, 'mask'=>intval($mask));
}
$result->acl=$ip_access_list;
$this->somethingChanged=1;
}
}
if (!$result->password) unset($result->password);
if ($timezone && $timezone != $this->timezone) {
$result->timezone=$timezone;
$this->somethingChanged=1;
}
if ($region != $this->region) {
$result->region=$region;
$this->somethingChanged=1;
}
if (strcmp($quickdial,$this->quickdial) != 0) {
$result->quickdialPrefix=$quickdial;
$this->somethingChanged=1;
}
$mobile_number = preg_replace("/[^\+0-9]/","",$mobile_number);
if ($mobile_number && !preg_match("/^\+/",$mobile_number)) {
$mobile_number='+'.$mobile_number;
}
if ($this->Preferences['mobile_number'] != $mobile_number) {
$this->setPreference('mobile_number',$mobile_number);
$this->somethingChanged=1;
}
if (!$this->createdVoicemailnow) {
// moved to its own tab
//$this->setDiversions();
}
if ($this->timeoutWasNotSet || $timeout != $this->timeout) {
$this->somethingChanged=1;
$result->timeout=intval($timeout);
}
if ($result->owner == '') {
$this->somethingChanged=1;
$result->owner=0;
}
if ($result->callLimit == '') {
$this->somethingChanged=1;
$result->callLimit=0;
}
if ($result->quota == '') {
$this->somethingChanged=1;
$result->quota=0;
}
if ($result->timeout == '') {
$this->somethingChanged=1;
$result->timeout=35;
}
if ($result->timeout > 900) {
$this->somethingChanged=1;
$result->timeout=900;
}
if ($this->somethingChanged) {
$result->properties=$this->properties;
if (!$result->quota) $result->quota=0;
//dprint_r($result);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->updateAccount($result);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
dprint("Call updateAccount");
if ($this->sendCEmail && $this->notify_on_sip_account_changes) {
$this->sendChangedEmail(False,$this->changedFields);
}
}
}
if ($this->voicemail['Account'] && !$this->createdVoicemailnow) {
$delete_voicemail = $_REQUEST['delete_voicemail'];
//$log=sprintf("delete_voicemail_orig=%s",$this->voicemail['Options']->delete);
//dprint($log);
if (($delete_voicemail && !$this->voicemail['Options']->delete) ||
(!$delete_voicemail && $this->voicemail['Options']->delete)) {
$this->voicemail['Options']=array("delete"=>intval($delete_voicemail));
$this->voicemailOptionsHaveChanged=1;
}
$voicemail_password=preg_replace("/[^0-9]/","",$voicemail_password);
if ($this->voicemail['Password'] != $voicemail_password) {
$this->voicemailOptionsHaveChanged=1;
$this->voicemail['Password']=$voicemail_password;
}
if ($this->voicemailOptionsHaveChanged) {
$this->updateVoicemail();
}
}
$this->updateBillingProfiles();
}
function setDiversions() {
dprint ("setDiversions()");
$this->getVoicemail();
$this->getEnumMappings();
$this->getDivertTargets();
$this->getDiversions();
foreach (array_keys($this->diversionType) as $condition) {
$select_name = $condition."_select";
$selectedIdx = $_REQUEST[$select_name];
$textboxURI = $_REQUEST[$condition];
if ($textboxURI && $textboxURI != "<voice-mailbox>" && !preg_match("/@/",$textboxURI)) {
$textboxURI=$textboxURI."@".$this->domain;
}
if (preg_match("/^([\+|0].*)@/",$textboxURI,$m)) {
$textboxURI=$m[1]."@".$this->domain;
}
$uri_description = $this->divertTargets[$selectedIdx]['description'];
if ($uri_description == 'Other' || $textboxURI == "<voice-mailbox>") {
$selectedURI = $textboxURI;
} else {
$selectedURI = $this->divertTargets[$selectedIdx]['value'];
}
$uri = $selectedURI;
if (!$this->voicemail['Account'] && $uri_description == 'Voicemail') {
dprint("No voicemail account found");
$uri_description='Disabled';
}
if ($this->diversions[$condition]) {
if ($uri_description=='Disabled' && $this->CallPrefUriType[$condition]!='Disabled') {
$diversions[$condition]="";
} else if ($uri_description != 'Disabled' && $selectedURI) {
if (checkURI($selectedURI)) {
if ($this->CallPrefUriType[$condition]=='Disabled') {
$diversions[$condition]="";
} else {
if ($this->diversions[$condition] != $uri) {
$diversions[$condition]=$uri;
} else {
$diversions[$condition]=$this->diversions[$condition];
}
}
} else {
$diversions[$condition]=$this->diversions[$condition];
dprint("Failed to check address $selectedURI");
}
}
} else if ($uri_description!='Disabled' && $selectedURI) {
if (checkURI($selectedURI)) {
$diversions[$condition]=$uri;
} else {
dprint("Failed to check address $condition=\"$selectedURI\"");
$diversions[$condition]=$this->diversions[$condition];
}
}
if (!$uri_description) $uri_description="Other";
if ($uri_description == 'Other') {
$last_other=$uri;
} else {
$last_other = $this->CallPrefLastOther[$condition];
}
$_prefLast = $condition."_lastOther";
if ($uri_description=='Other' && $this->Preferences[$_prefLast] != $last_other ) {
$this->setPreference($_prefLast,$last_other);
}
}
foreach(array_keys($this->diversions) as $key) {
if ($this->diversions[$key] != $diversions[$key]) {
//$log=sprintf("Diversion %s changed from %s to %s",$key,htmlentities($this->diversions[$key]),htmlentities($diversions[$key]));
dprint($log);
$divert_changed=1;
}
if ($diversions[$key]) {
if ($diversions[$key] == "<voice-mailbox>") {
if ($this->absolute_voicemail_uri) {
$diversionsSOAP[$key] = 'sip:'.$this->voicemail['Account'];
} else {
$diversionsSOAP[$key] = $diversions[$key];
}
} else {
$diversionsSOAP[$key]='sip:'.$diversions[$key];
}
} else {
if ($diversions[$key]) $diversionsSOAP[$key]=$diversions[$key];
}
}
if (!is_array($diversionsSOAP) || count($diversionsSOAP) == 0) {
$diversionsSOAP=array("nocondition"=>"empty");
}
if ($divert_changed) {
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setCallDiversions($this->sipId,$diversionsSOAP);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error2 (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
$this->diversions=$diversions;
}
}
}
function setDiversion($condition,$uri) {
dprint ("setDiversion($condition,$uri)");
$condition=trim($condition);
$uri=trim($uri);
$this->getVoicemail();
$this->getDivertTargets();
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCallDiversions($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
$_uri_saved=$uri;
if ($_uri_saved == "voicemail") {
$uri="";
foreach ($this->divertTargets as $target) {
if ($target['description'] == 'Voicemail') {
$uri=$target['value'];
break;
}
}
}
if ($_uri_saved == "mobile") {
$uri="";
foreach ($this->divertTargets as $target) {
dprint_r($target);
if ($target['description'] == 'Mobile') {
$uri=$target['value'];
break;
}
}
}
if ($_uri_saved == "other" && $this->CallPrefLastOther[$condition]) {
$uri=$this->CallPrefLastOther[$condition];
}
if (strlen($uri)) {
if ($uri != "<voice-mailbox>") {
if (!preg_match("/^(sip:|sips:)/",$uri)) $uri="sip:".$uri;
}
} else {
$uri=NULL;
}
reset($this->diversionType);
foreach(array_keys($this->diversionType) as $_condition) {
$uri=$result->$_condition;
if ($this->absolute_voicemail_uri && $uri == "<voice-mailbox>") {
$uri = $this->voicemail['Account'];
}
if (preg_match("/^(sip:|sips:)(.*)$/i",$uri,$m)) {
$uri=$m[2];
}
//if (!$uri) $uri=NULL;
$this->diversions[$condition]=$uri;
}
dprint_r($this->diversions);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setCallDiversions($this->sipId,$result);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
function setVoicemailDiversions() {
dprint ("setVoicemailDiversions()");
if ($this->getVoicemail()) {
if (!$this->absolute_voicemail_uri) {
$diversions['FBUS']="<voice-mailbox>";
$diversions['FNOA']="<voice-mailbox>";
$diversions['FNOL']="<voice-mailbox>";
} else {
$diversions['FBUS']="sip:".$this->voicemail['Account'];
$diversions['FNOA']="sip:".$this->voicemail['Account'];
$diversions['FNOL']="sip:".$this->voicemail['Account'];
}
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setCallDiversions($this->sipId,$diversions);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
}
function removeVoicemailDiversions() {
dprint ("removeVoicemailDiversions()");
$this->getDiversions();
$diversions=array();
foreach (array_keys($this->diversionType) as $key) {
if ($this->diversions[$key]=="<voice-mailbox>" || preg_match("/voicemail_server/",$this->diversions[$key])) {
$diversions_have_changed=true;
} else {
if ($this->diversions[$key]) {
$diversions[$key]=$this->diversions[$key];
}
}
}
if (!count($diversions)) {
$diversions['nocondition']='empty';
}
if ($diversions_have_changed) {
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setCallDiversions($this->sipId,$diversions);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
} else {
return true;
}
}
function updateVoicemail() {
dprint("updateVoicemail()");
$account=array("sipId" => $this->sipId,
"email" => $this->email,
"name" => $this->firstName.' '.$this->lastName,
"password" => $this->voicemail['Password'],
"options" => $this->voicemail['Options']
);
dprint_r($account);
$this->VoicemailPort->addHeader($this->SoapAuthVoicemail);
$result = $this->VoicemailPort->updateAccount($account);
if ((new PEAR)->isError($result)) {
$error_msg=$result->getMessage();
$error_fault=$result->getFault();
$error_code=$result->getCode();
print "$error_msg\n";
printf ("<p><font color=red>Error (VoicemailPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
return true;
}
function addVoicemail() {
dprint("addVoicemail()");
$password=$this->RandomPassword();
$_account = array("sipId" => $this->sipId,
"name" => $this->fullName,
"password" => $password,
"email" => $this->email,
"options" => array("delete"=>1)
);
$this->VoicemailPort->addHeader($this->SoapAuthVoicemail);
$result = $this->VoicemailPort->addAccount($_account);
if ((new PEAR)->isError($result)) {
$error_msg=$result->getMessage();
$error_fault=$result->getFault();
$error_code=$result->getCode();
print "$error_msg\n";
printf ("<p><font color=red>Error (VoicemailPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
return true;
}
function deleteVoicemail() {
dprint("deleteVoicemail()");
$this->VoicemailPort->addHeader($this->SoapAuthVoicemail);
$result = $this->VoicemailPort->deleteAccount($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg=$result->getMessage();
$error_fault=$result->getFault();
$error_code=$result->getCode();
print "$error_msg\n";
printf ("<p><font color=red>Error (VoicemailPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
return true;
}
function setPreference($name,$value) {
dprint("setPreference($name,$value)");
if (!$name) return;
if (!is_array($this->properties)) {
$this->properties=array();
}
foreach (array_keys($this->properties) as $_key) {
$_prop=$this->properties[$_key];
if ($_prop->name == $name) {
if (strlen($value)) {
if ($value != 'remove') {
$newProperties[]=array('name'=> $name,
'value' => $value);
}
}
$found=1;
} else {
$newProperties[]=$_prop;
}
}
if (!$found) {
$newProperties[]=array('name' => $name,
'value' => $value);
}
if ($this->properties!=$newProperties) $this->somethingChanged=1;
if (!$newProperties) $newProperties = array();
$this->properties=$newProperties;
//dprint_r($this->properties);
}
function showCreditTab() {
if ($this->login_type == 'subscriber' && in_array("blocked",$this->groups)) {
return false;
}
$task = $_REQUEST['task'];
$issuer = $_REQUEST['issuer'];
$prepaidCard = $_REQUEST['prepaidCard'];
$prepaidId = $_REQUEST['prepaidId'];
$_done = false;
if ($issuer) {
print "
<tr>
<td colspan=2 align=left> ";
if ($issuer=='subscriber'){
if ($prepaidCard && $prepaidId) {
if ($result = $this->addBalanceSubscriber($prepaidCard,$prepaidId)) {
print "<p><font color=green>";
printf (_("Old balance was %s, new balance is %s. "),$result->old_balance, $result->new_balance);
print "</font>";
$_done=true;
}
}
} else if ($issuer=='reseller' || $issuer=='admin') {
if ($_REQUEST['task'] == 'change_balance') {
$description = $_REQUEST['description'];
$value = $_REQUEST['value'];
if (strlen($value) && $result = $this->addBalanceReseller($value,$description)) {
print "<p><font color=green>";
printf (_("Old balance was %s, new balance is %s. "),$result->old_balance, $result->new_balance);
print "</font>";
$_done=true;
}
} else if ($_REQUEST['task'] == 'refund') {
$transaction = json_decode(base64_decode($_REQUEST['transaction']));
printf ("Refunding transaction id %s in value of %s", $transaction->id, $transaction->value);
require('cc_processor.php');
$ccp = new CreditCardProcessor();
$refund_results = $ccp->refundPayment($transaction->id);
if(count($refund_results['error']) > 0 ){
printf ("<p><font color=red>Error %d: %s (%s)</font>",$refund_results['error']['error_code'], $refund_results['error']['desc'], $refund_results['error']['short_message']);
} else {
printf ("<p>Transaction %s refunded with %s: %s",$transaction->id, $refund_results['success']['desc']->RefundTransactionID,$refund_results['success']['desc']->GrossRefundAmount->_value);
$description=sprintf("Refund %s with %s",$transaction->id, $refund_results['success']['desc']->RefundTransactionID);
if ($result = $this->addBalanceReseller(-$transaction->value,$description)) {
print "<p><font color=green>";
printf (_("Old balance was %s, new balance is %s. "),$result->old_balance, $result->new_balance);
print "</font>";
$_done=true;
}
}
}
}
if ($_done && $_REQUEST['notify']) {
$subject=sprintf ("SIP Account %s balance update",$this->account);
$body="Your SIP Account balance has been updated. ".
"For more details go to $this->sip_settings_page?tab=credit";
if (mail($this->email, $subject, $body, "From: $this->support_email")) {
printf (_("Subscriber has been notified at %s."), $this->email);
}
}
print "
</td>
</tr>
";
}
$this->getPrepaidStatus();
if ($this->prepaidAccount) {
$chapter=sprintf(_("Current Balance"));
$this->showChapter($chapter);
print "
<div class=row-fluid>
<div class=span12>";
print _("Your current balance is");
print ": ";
printf ("%.2f %s ",$this->prepaidAccount->balance,$this->currency);
print "</div>
</div>
";
$this->showChangeBalanceReseller();
$this->showChangeBalanceSubscriber();
$this->showBalanceHistory();
}
}
function showChangeBalanceReseller () {
if (!$this->prepaid_changes_allowed) return false;
$chapter=sprintf(_("Add Balance"));
$this->showChapter($chapter);
print "
<form class=form-inline action=$this->url method=post>
<input type=hidden name=tab value=credit>
<input type=hidden name=issuer value=reseller>
<input type=hidden name=task value=change_balance>
<div class=control-group>
<div class=control>";
print "
<input type=text size=10 name=value placeholder=\"";
print _("Value");
print "\">";
print "<input type=text size=30 name=description placeholder=\"";
print _("Description");
print "\">";
print " <label class=checkbox>";
print "<input type=checkbox name=notify value=1>";
print _("Notify");
print "</label>
";
print "<input class=btn type=submit value=";
print _("Add");
print ">
</div>
</div>
</form>
";
$transactions = $this->getPaymentIds();
if (count($transactions)) {
$chapter=sprintf(_("Refund Transaction"));
$this->showChapter($chapter);
print "
<form class='form-inline' action=$this->url method=post>
<input type=hidden name=tab value=credit>
<input type=hidden name=issuer value=reseller>
<input type=hidden name=task value=refund>
";
print _("Transaction Id");
print "
<select class=span2 name=transaction> ";
foreach (array_keys($transactions) as $tran) {
$t=array('id' => $tran, 'value' => $transactions[$tran]);
printf ("<option value='%s'>%s",base64_encode(json_encode($t)),$tran);
}
print "
</select>
";
print "
Notify
<input type=checkbox name=notify value=1>
<input class='btn btn-warning' type=submit value=";
print _("Refund");
print ">
</form>
";
}
}
function showChangeBalanceSubscriber () {
$this->showPrepaidVoucherForm();
}
function showPrepaidVoucherForm () {
if ($this->isEmbedded()) return true;
$chapter=sprintf(_("Prepaid Card"));
$this->showChapter($chapter);
print "
<div class='row-fluid'>
<div class='span12'>
";
printf (_("To add Credit to your account using a Prepaid Card enter it below. "));
print "
</div>
</div>
";
print "
<form class=form-inline action=$this->url method=post>
<input type=hidden name=tab value=credit>
<input type=hidden name=issuer value=subscriber>
<input type=hidden name=task value=Add>
<div class=control-group>
<div class=control>
";
print "
<input type=text size=10 name=prepaidId placeholder=\"";
print _("Card Id");
print "\">";
print "<input type=text size=20 name=prepaidCard placeholder=\"";
print _("Card Number");
print "\">";
if ($this->login_type != 'subscriber') {
print " <label class=\"checkbox\">";
print "<input type=checkbox name=notify value=1>";
print _("Notify");
print "</label>";
}
print "
<input class='btn' type=submit value=";
print _("Add");
print "></div></div>
</form>
";
}
function getPrepaidStatus() {
dprint("getPrepaidStatus()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getPrepaidStatus(array($this->sipId));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
unset($this->prepaidAccount);
return false;
} else {
$this->prepaidAccount=$result[0];
return true;
}
}
function addBalanceSubscriber($prepaidCard,$prepaidId) {
dprint("addBalanceSubscriberLocal($prepaidCard,$prepaidId)");
$card = array('id' => intval($prepaidId),
'number' => $prepaidCard
);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->addBalanceFromVoucher($this->sipId,$card);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
return $result;
}
}
function addBalanceReseller($value=0,$description='') {
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->addBalance($this->sipId,floatval($value),$description);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
return $result;
}
}
function getBalanceHistory() {
dprint("getBalanceHistory()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCreditHistory($this->sipId,200);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "2000") {
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
}
}
$this->balance_history=$result->entries;
}
function getPaymentIds() {
$transactions = array();
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCreditHistory($this->sipId,200);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "2000") {
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
}
}
$refunded_transactions=array();
$credit_transactions=array();
foreach ($result->entries as $entry) {
if (preg_match("/^CC transaction (.*)$/",$entry->description,$m)) {
$credit_transactions[$m[1]]=$entry->value;
}
if (preg_match("/^Refund (.*) with (.*)$/",$entry->description,$m)) {
$refunded_transactions[]=$m[1];
}
}
foreach (array_keys($credit_transactions) as $tran) {
if (!in_array($tran, $refunded_transactions)) {
$transactions[$tran] = $credit_transactions[$tran];
}
}
return $transactions;
}
function getTodayBalanceSummary() {
$total_debit = 0;
$total_credit = 0;
foreach ($this->balance_history as $_line) {
$value=$_line->value;
if (substr($_line->date,0,10) != date("Y-m-d")) {
break;
}
if ($value <0) {
$total_debit+=$value;
}
if ($value >0) {
$total_credit+=$value;
}
}
$total = array('debit' => $total_debit,
'credit' => $total_credit
);
return $total;
}
function showBalanceHistory() {
$this->getBalanceHistory();
if (!count($this->balance_history)) {
return;
}
$chapter=sprintf(_("Balance History"));
$this->showChapter($chapter);
print "
<div class=row-fluid>
<div class=span12>
";
$today_summary = $this->getTodayBalanceSummary();
if ($today_summary['credit'] >= $max_credit_per_day) {
print "<p>";
printf (_("Today's transactions: %.2f credit, %.2f debit"), $today_summary['credit'],$today_summary['debit']);
}
print "
<p>
<table class='table table-striped table-condensed'>";
print "<thead>";
print "<tr>";
print "<th class=list_header>";
print "</th>";
print "<th class=list_header>";
print _("Date and Time");
print "</th>";
print "<th class=list_header>";
print _("Action");
print "</th>";
print "<th class=list_header>";
print _("Description");
print "</th>";
print "<th class=list_header align=right>";
print _("Value");
print "</th>";
print "<th class=list_header align=right>";
print _("Balance");
print "</th>";
print "</tr>";
print "</thead>";
foreach ($this->balance_history as $_line) {
if (strstr($_line->description,'Session')) {
if (!$_line->value) continue;
$value=$_line->value;
if ($this->cdrtool_address && !$this->isEmbedded()) {
$description=sprintf("<a href=%s/callsearch.phtml?action=search&call_id=%s target=cdrtool>$_line->description</a>",$this->cdrtool_address,urlencode($_line->session));
} else {
$description=$_line->description;
}
} else {
$description=$_line->description;
$value=$_line->value;
}
if ($value <0) {
$total_debit+=$value;
}
if ($value >0) {
$total_credit+=$value;
}
$found++;
$rr=floor($found/2);
$mod=$found-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "
<tr class=$_class>";
printf ("
<td>%d</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td align=right>%s</td>
<td align=right>%s</td>
</tr>
",$found,
$_line->date,
$_line->action,
$description,
number_format($value,4),
number_format($_line->balance,4)
);
}
print "
</td>
</tr>
";
if (strlen($total_credit)) {
printf ("
<tr>
<td></td>
<td></td>
<td></td>
<td><span class=\"label label-info\">%s</span></td>
<td align=right><b>%s</b></td>
<td align=right></td>
</tr>
",
_("Total Credit"),
number_format($total_credit,4)
);
}
if (strlen($total_debit)) {
printf ("
<tr>
<td></td>
<td></td>
<td></td>
<td><span class=\"label label-important\">%s</span></td>
<td align=right><b>%s</b></td>
<td align=right></td>
</tr>
",
_("Total Debit"),
number_format($total_debit,4)
);
}
print "
</table>
";
if ($found) {
if (!$this->isEmbedded()) {
print "<p class='form-actions'><a class=btn href=$this->url&tab=credit&action=get_balance_history&csv=1 target=_new data-original-title='";
print _("Export");
print "' data-content='";
print _("Export balance history in CSV format");
print "' rel='popover' onclick=\"window.open('$this->url&tab=credit&action=get_balance_history&csv=1]')\">";
print _("Export");
print "</a></p>";
} else {
print "<p class='form-actions'><a rel=popover class=btn href=$this->url&tab=credit&action=get_balance_history&csv=1 data-original-title='";
print _("Export");
print "' data-content='";
print _("Export balance history in CSV format");
print "' onclick=\"location.href='$this->url&tab=credit&action=get_balance_history&csv=1';\">";
print _("Export");
print "</a></p>";
}
}
print "</td></tr>";
}
function exportBalanceHistory() {
Header("Content-type: text/csv");
$h=sprintf("Content-Disposition: inline; filename=%s-prepaid-history.csv",$this->account);
Header($h);
print _("Id");
print ",";
print _("Account");
print ",";
print _("Date");
print ",";
print _("Action");
print ",";
print _("Description");
print ",";
print _("Value");
print ",";
print _("Final Balance");
print ("\n");
foreach ($this->balance_history as $_line) {
if (strstr($_line->description,'Session') && !$_line->value) continue;
$found++;
printf ("%s,%s,%s,%s,%s,%s,%s\n",
$found,
$this->account,
$_line->date,
$_line->action,
$_line->description,
$_line->value,
$_line->balance);
}
}
function showDiversions($conditions=array()) {
// for busy not online or unconditional
foreach (array_keys($this->diversionType) as $condition) {
$_prefName = $condition."_lastOther";
$this->CallPrefLastOther[$condition]= $this->Preferences[$_prefName];
}
if (!count($conditions)) {
$conditions=$this->diversionType;
}
foreach (array_keys($conditions) as $condition) {
$found++;
$rr=floor($found/2);
$mod=$found-$rr*2;
$pref_name = $conditions[$condition];
$pref_value = $this->diversions[$condition];
$select_name=$condition."_select";
$set_uri_java="set_uri_" . $condition;
$update_text_java="update_text_" . $condition;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "
<div class='control-group $_class'>
<label class=control-label>$pref_name</label>
<div class='controls'>
";
$phoneValues = array();
foreach ($this->divertTargets as $phones) {
$phoneValues[] = $phones['value'];
}
$lastOther = $this->CallPrefLastOther[$condition];
$otherIdx = count($this->divertTargets) - 1;
$phoneValues[$otherIdx] = $lastOther;
$targets = sprintf("'%s'", join("', '", $phoneValues));
print "
<SCRIPT>
var ${condition}_other = '$lastOther';
function $set_uri_java(elem) {
var index;
var targets = [$targets];
index = elem.selectedIndex;
if (index == $otherIdx) {
document.sipsettings.$condition.value=${condition}_other;
document.sipsettings.$condition.style.display = 'inline-block';
document.sipsettings.$condition.style.visibility = 'visible';
} else {
document.sipsettings.$condition.style.display = 'none';
document.sipsettings.$condition.value=targets[index];
}
}
function $update_text_java(elem) {
${condition}_other = elem.value;
}
</SCRIPT>
";
print "<select name=$select_name onChange=$set_uri_java(this)>\n";
if ($this->diversions[$condition]) {
$this->CallPrefUriType[$condition]=='Other';
} else {
$this->CallPrefUriType[$condition]=='Disabled';
}
$foundSelected=0;
$nr_targets=count($this->divertTargets);
foreach ($this->divertTargets as $idx => $phone) {
$name = $phone['name'];
if ($this->access_numbers[$condition]) {
if ($phone['description'] == "Mobile") {
$name .= sprintf(' (%s %s0)',_("Dial"),$this->access_numbers[$condition]);
} else if ($phone['description'] == "Voicemail") {
$name .= sprintf(' (%s %s1)',_("Dial"),$this->access_numbers[$condition]);
} else if ($phone['description'] == "Disabled") {
$name .= sprintf(' (%s %s)',_("Dial"),$this->access_numbers[$condition]);
} else if ($phone['description'] == "Other") {
$name .= sprintf(' (%s %s+ %s)',_("Dial"),$this->access_numbers[$condition],_("Number"));
}
}
if ($phone['description'] == 'Other')
$value = $lastOther;
else
$value = $phone['value'];
if (!$foundSelected &&
($this->diversions[$condition]==$phone['value'] || $idx==$nr_targets-1)) {
print "<option value=\"$idx\" selected>$name</option>\n";
$pref_value = $value;
$this->CallPrefUriType[$condition]=$phone['description'];
$foundSelected=1;
} else {
print "<option value=\"$idx\">$name</option>\n";
}
}
print "</select>";
if ($this->CallPrefUriType[$condition]=='Other')
$style = "visible";
else
$style = "hidden";
$pref_value=$this->diversions[$condition];
print "
<span>
<input class='$style' type=text size=40
name=$condition value=\"$pref_value\"
onChange=$update_text_java(this)>
</span>
";
if ($condition=="FUNV" && $this->FUNC_access_number) {
print "<div class=help-block>";
printf (_("Dial %s2*X where X = Number of Minutes, 0 to Reset"), $this->access_numbers['FUNC']);
print "</div>";
}
print "
</div>
</div>
";
}
}
function showHeader() {
/*print "
<table class=settings border=0 width=100%>
<tr>
<td colspan=2 align=right>
";*/
print "
<div class=row-fluid>
<div class='span12'>";
if ($this->logoFile) {
print "<img class='pull-right' src=./$this->logoFile border=0>";
}
print "
</div>
</div>
";
/*
print "
</td>
</tr>
</table>
";
*/
}
function chapterTableStart() {
}
function chapterTableStop() {
}
function getEnumMappings () {
dprint("getEnumMappings()");
$this->enums=array();
$filter=array(
'type' => 'sip',
'mapto' => $this->account,
'owner' => intval($this->owner)
);
// Range
$range=array('start' => 0,
'count' => 10
);
// Order
$orderBy = array('attribute' => 'changeDate',
'direction' => 'ASC'
);
// Compose query
$Query=array('filter' => $filter,
'orderBy' => $orderBy,
'range' => $range
);
// Insert credetials
$this->EnumPort->addHeader($this->SoapAuthEnum);
$result = $this->EnumPort->getNumbers($Query);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (EnumPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
foreach($result->numbers as $_number) {
$enum='+'.$_number->id->number;
$this->voicemailUsernameOptions[]=$enum;
if (!in_array($enum,$this->enums)) $this->enums[]=$enum;
}
}
function enum2tel($enum_text) {
// transform enum style domain name in forward telephone number
$enum_text=trim($enum_text);
if (preg_match("/^\+\d+$/",$enum_text)) {
return $enum_text;
}
$z=0;
$tel_text="";
while ($z < strlen($enum_text)) {
$char = substr($enum_text,$z,1);
if (preg_match("/[a-zA-Z]/",$char)) {
break;
} else if (preg_match("/[0-9]/",$char)) {
$tel_text=$char.$tel_text;
$z++;
} else {
$z++;
}
}
if ($tel_text) {
$tel_text="+".$tel_text;
return ($tel_text);
} else {
return $enum_text;
}
}
function showTimezones($name,$value) {
if (!$fp = fopen("timezones", "r")) {
print _("Failed to open timezone file.");
return false;
}
printf ("<select class=input-medium name=%s>",$name);
print "\n<option>";
while ($buffer = fgets($fp,1024)) {
$buffer=trim($buffer);
if ($value==$buffer) {
$selected="selected";
} else {
$selected="";
}
print "\n<option $selected>";
print "$buffer";
}
fclose($fp);
print "</select>";
}
function showQuickDial() {
if (!preg_match("/^\d+$/",$this->username)) return 1;
print "
<div class='control-group'>
<label class=control-label>";
print _("Quick Dial");
print "
</label>
<div class=controls>
<input class=input-medium type=text size=15 maxsize=64 name=quickdial value=\"$this->quickdial\"><span class=help-inline>";
if ($this->quickdial && preg_match("/^$this->quickdial/",$this->username)) {
$dial_suffix=strlen($this->username) - strlen($this->quickdial);
}
printf (_("Prefix to auto-complete short numbers"),$dial_suffix);
print "</span>
</div>
</div>
";
}
function showMobileNumber() {
if (in_array("free-pstn",$this->groups)) {
print "
<div class='control-group'>
<label for=mobile_number class=control-label>";
print _("Mobile Number");
printf ("
</label>
<div class=controls>
<input class=input-medium type=text size=15 maxsize=64 name=mobile_number value='%s'>
<span class=help-inline>%s</span></div></div>
",$this->Preferences['mobile_number'],_("International format starting with +"));
}
}
function CallLimitChangePolicy() {
if ($this->login_type == 'subscriber' and $this->call_limit_may_by_changed_by == 'reseller') {
return false;
}
if ($this->login_type == 'subscriber' and $this->call_limit_may_by_changed_by == 'customer') {
return false;
}
if ($this->login_type == 'subscriber' and $this->call_limit_may_by_changed_by == 'admin') {
return false;
}
if ($this->login_type == 'customer' and $this->call_limit_may_by_changed_by == 'reseller') {
return false;
}
if ($this->login_type == 'customer' and $this->call_limit_may_by_changed_by == 'admin') {
return false;
}
if ($this->login_type == 'reseller' and $this->call_limit_may_by_changed_by == 'admin') {
return false;
}
return true;
}
function IPAccessListChangePolicy() {
if ($this->login_type == 'subscriber' and $this->ip_access_list_may_by_changed_by == 'reseller') {
return false;
}
if ($this->login_type == 'subscriber' and $this->ip_access_list_may_by_changed_by == 'customer') {
return false;
}
if ($this->login_type == 'subscriber' and $this->ip_access_list_may_by_changed_by == 'admin') {
return false;
}
if ($this->login_type == 'customer' and $this->ip_access_list_may_by_changed_by == 'reseller') {
return false;
}
if ($this->login_type == 'customer' and $this->ip_access_list_may_by_changed_by == 'admin') {
return false;
}
if ($this->login_type == 'reseller' and $this->ip_access_list_may_by_changed_by == 'admin') {
return false;
}
return true;
}
function showIPAccessList() {
if (!$this->soapEngines[$this->sip_engine]['ip_access_list']) {
return;
}
if (!$this->IPAccessListChangePolicy()) {
print "
<div class='control-group even'>
<label class=control-label>";
print _("IP Access List");
printf ("
</label>
<div class=controls style='line-height:23px'>
%s
</div>
</div>
",$this->ip_access_list);
} else {
print "
<div class='control-group odd'>
<label class='control-label'>";
print _("IP Access List");
print "
</label>
<div class=controls>
<textarea class=input-medium rel=popover title data-original-title='Access List Examples' data-trigger='focus' data-toggle=\"popover\" data-content=\"";
print _("You can limit here the IP addresses allowed to use the SIP account as an anti-fraud measure. You may enter a list of network addresses in CIDR format separated by spaces. <p>Examples:<dl><dt>0.0.0.0/0</dt><dd> means any address is allowed</dd><dt>1.2.3.4/32</dt><dd> means only one address 1.2.3.4 is allowed</dd><dt>1.2.3.0/24</dt><dd> means only the 254 IP addresses from the C class 1.2.3.0 are allowed</dd>");
printf ("\" cols=60 rows=1 name=ip_access_list>%s</textarea>
</div>
</div>
",$this->ip_access_list);
}
}
function showCallLimit() {
if (!$this->pstn_access) {
return;
}
if (!in_array("free-pstn",$this->groups)) {
return;
}
if (!$this->soapEngines[$this->sip_engine]['call_limit']) {
return;
}
$limit_text = sprintf(_("Default is %s"), $this->platform_call_limit);
if (strlen($this->callLimit)) {
$limit_text_ro=$this->callLimit;
} else {
$limit_text_ro=$this->platform_call_limit;
}
if (!$this->CallLimitChangePolicy()) {
print "
<div class=control-group>
<label class=control-label>";
print _("PSTN Call Limit");
printf ("
</label>
<div class=controls>
<span style='padding-top:5px; margin-bottom:5px;display:block;'>%s</span>
</div>
</div>
",$limit_text_ro);
} else {
print "
<div class=control-group>
<label class=control-label>";
print _("PSTN Call Limit");
print "
</label>
<div class=controls>
<input class=input-medium rel=popover type=text size=3 name=callLimit title data-original-title='";
print _("PSTN Call limit");
print "' data-trigger='focus' data-toggle=\"popover\" data-content=\"";
print "Used as anti-fraud measure for limiting the maximum number of outgoing concurrent calls to PSTN numbers.";
printf ("\" value='%s'> %s
</div>
</div>
",$this->callLimit, $limit_text);
}
}
function showCallsTab() {
$this->getHistory();
if ($this->calls) {
$chapter=sprintf(_("Call Statistics"));
$this->showChapter($chapter);
$calltime=normalizeTime($this->duration);
print "
<tr>
<td class=cell>";
if ($this->cdrtool_address) {
print "<a href=$this->cdrtool_address target=cdrtool>";
print _("Summary");
print "</a>";
} else {
print _("Usage Data");
}
print "
</td>
<td class=cell>";
printf (_("%s calls / %s / %s / %.2f %s"), $this->calls, $calltime,$this->trafficPrint,$this->price,$this->currency);
print "
</td>
</tr>
";
print "
<tr>
<td>";
print _("First / Last Call");
print "
</td>
<td>
$this->firstCall / $this->lastCall
</td>
</tr>
";
}
if ($this->enable_thor) {
$cdr_source = 'sipthor';
} else {
$cdr_source = 'sip_trace';
}
if (count($this->calls_received)) {
$chapter=sprintf(_("Incoming"));
$this->showChapter($chapter);
$j=0;
print "<table class='table table-striped table-condensed'>";
foreach (array_keys($this->calls_received) as $call) {
$j++;
$uri = $this->calls_received[$call]['remoteParty'];
$media="";
foreach ($this->calls_received[$call]['media'] as $m) {
$media.="$m,";
}
$media=quoted_printable_decode($media);
$media=rtrim($media,",");
$duration = normalizeTime($this->calls_received[$call]['duration']);
$dialURI = $this->PhoneDialURL($uri) ;
$htmlDate = $this->colorizeDate($this->calls_received[$call]['startTime']);
$htmlURI = $this->htmlURI($uri);
$urlURI = urlencode($this->normalizeURI($uri));
$sessionId = urlencode($this->calls_received[$call]['sessionId']);
$fromTag = urlencode($this->calls_received[$call]['fromTag']);
$toTag = urlencode($this->calls_received[$call]['toTag']);
$proxyIP = urlencode($this->calls_received[$call]['proxyIP']);
$trace_link = "<a href=\"javascript:void(null);\" onClick=\"return window.open('sip_trace.phtml?cdr_source=$cdr_source&callid=$sessionId&fromtag=$fromTag&totag=$toTag&proxyIP=$proxyIP', 'siptrace',
'toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=1000,height=600')\">Server Logs</a>";
if (!$this->calls_received[$call]['duration']) {
$htmlURI = "<font color=red>$htmlURI</font>";
}
$rr=floor($j/2);
$mod=$j-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "
<tr class=$_class>
<td width=175>$htmlDate</td>
<td width=12><nobr>$dialURI</nobr></td>
<td style='text-align:right' width=60>$duration</td>
<td><nobr>$htmlURI ($media)</nobr></td>
";
print "<td width=40><nobr>$trace_link</nobr></td>";
print "<td width=19><a href=$this->url&tab=contacts&task=add&uri=$urlURI&search_text=$urlURI>$this->phonebook_img</a></td>";
print "</td>
</tr>
";
}
print "</table>";
}
if (count($this->calls_placed)) {
$chapter=sprintf(_("Outgoing"));
$this->showChapter($chapter);
$j=0;
print "<table class='table table-striped table-condensed'>";
foreach (array_keys($this->calls_placed) as $call) {
$j++;
if ($this->calls_placed[$call]['to'] == "sip:".$this->voicemail['Account'] ) {
continue;
}
$uri = $this->calls_placed[$call]['remoteParty'];
$media = "";
foreach ($this->calls_placed[$call]['media'] as $m) {
$media.="$m,";
}
$media=rtrim($media,",");
$price = $this->calls_placed[$call]['price'];
$status = $this->calls_placed[$call]['status'];
$rateinfo = $this->calls_placed[$call]['rateInfo'];
$duration = normalizeTime($this->calls_placed[$call]['duration']);
$dialURI = $this->PhoneDialURL($uri) ;
$htmlDate = $this->colorizeDate($this->calls_placed[$call]['startTime']);
$stopTime = $this->calls_placed[$call]['stopTime'];
$htmlURI = $this->htmlURI($uri);
$urlURI = urlencode($this->normalizeURI($uri));
$sessionId = urlencode($this->calls_placed[$call]['sessionId']);
$fromTag = urlencode($this->calls_placed[$call]['fromTag']);
$toTag = urlencode($this->calls_placed[$call]['toTag']);
$proxyIP = urlencode($this->calls_placed[$call]['proxyIP']);
$trace_link = "<a href=\"javascript:void(null);\" onClick=\"return window.open('sip_trace.phtml?cdr_source=$cdr_source&callid=$sessionId&fromtag=$fromTag&totag=$toTag&proxyIP=$proxyIP', 'siptrace',
'toolbar=0,status=0,menubar=0,scrollbars=1,resizable=1,width=1000,height=600')\">Server Logs</a>";
if ($price) {
$price_print =sprintf(" (%s %s)",$price,$this->currency);
} else {
$price_print = '';
}
$rr=floor($j/2);
$mod=$j-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
if (!$stopTime) {
$duration = _('In progress');
}
print "
<tr class=$_class>
<td width=175>$htmlDate</td>
<td width=12><nobr>$dialURI<nobr></td>
<td style='text-align:right' width=75>$duration</td>
<td ><nobr>$htmlURI ($media) $price_print</nobr></td>
";
print "<td width=40><nobr>$trace_link</nobr></td>";
print "<td width=19><a href=$this->url&tab=contacts&task=add&uri=$urlURI&search_text=$urlURI>$this->phonebook_img</a></td>";
print "</td>
</tr>
";
}
print "</table>";
}
}
function getHistory($status = 'all')
{
dprint("getHistory()");
$fromDate = time() - 3600 * 24 * 14; // last two weeks
$toDate = time();
$CallQuery = array(
"fromDate" => $fromDate,
"toDate" => $toDate,
"limit" => 50
);
$CallsQuery = array(
"placed" => $CallQuery,
"received" => $CallQuery
);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCalls($this->sipId, $CallsQuery);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
// received calls
foreach ($result->received as $callStructure) {
$media = array();
$apps = explode(",", quoted_printable_decode($callStructure->applicationTypes[0]));
foreach ($apps as $app) {
$media[] = trim($app);
}
if (!$callStructure->stopTime && $status == 'completed') {
continue;
}
$fromHeader = quoted_printable_decode($callStructure->fromHeader);
$this->calls_received[] = array(
"remoteParty" => quoted_printable_decode($callStructure->fromURI),
"displayName" => getDisplayNameFromFromHeader($fromHeader),
"startTime" => getLocalTime($this->timezone, $callStructure->startTime),
"stopTime" => getLocalTime($this->timezone, $callStructure->stopTime),
"timezone" => $this->timezone,
"duration" => $callStructure->duration,
"status" => $callStructure->status,
"sessionId" => quoted_printable_decode($callStructure->sessionId),
"fromTag" => quoted_printable_decode($callStructure->fromTag),
"toTag" => quoted_printable_decode($callStructure->toTag),
"proxyIP" => $callStructure->proxyIP,
"media" => $media
);
}
// placed calls
foreach ($result->placed as $callStructure) {
if ($callStructure->status == 435) continue;
$media = array();
$apps = explode(",", quoted_printable_decode($callStructure->applicationTypes[0]));
foreach ($apps as $app) {
$media[] = trim($app);
}
if (!$callStructure->stopTime && $status == 'completed') {
continue;
}
$fromHeader = quoted_printable_decode($callStructure->fromHeader);
$this->calls_placed[] = array(
"remoteParty" => quoted_printable_decode($callStructure->toURI),
"displayName" => "",
"startTime" => getLocalTime($this->timezone, $callStructure->startTime),
"stopTime" => getLocalTime($this->timezone, $callStructure->stopTime),
"timezone" => $this->timezone,
"duration" => $callStructure->duration,
"status" => $callStructure->status,
"price" => $callStructure->price,
"sessionId" => quoted_printable_decode($callStructure->sessionId),
"fromTag" => quoted_printable_decode($callStructure->fromTag),
"toTag" => quoted_printable_decode($callStructure->toTag),
"proxyIP" => $callStructure->proxyIP,
"media" => $media
);
}
$this->call_history = array(
'placed' => $this->calls_placed,
'received' => $this->calls_received
);
}
function getCallStatistics()
{
dprint("getCallStatistics()");
$fromDate = mktime(0, 0, 0, date("m"), "01", date("Y"));
$toDate = time();
$CallQuery = array(
"fromDate" => $fromDate,
"toDate" => $toDate
);
$CallQuery = array(
"limit" => 1
);
$CallsQuery = array(
"placed" => $CallQuery
);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getCallStatistics($this->sipId, $CallsQuery);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
//dprint_r($result);
$this->thisMonth['calls'] = $result->placed->calls;
$this->thisMonth['price'] = $result->placed->price;
}
function addPhonebookEntry()
{
dprint("addPhonebookEntry()");
$uri = strtolower(trim($_REQUEST['uri']));
$name = trim($_REQUEST['name']);
$group = trim($_REQUEST['group']);
if (!strlen($uri)) return false;
$phonebookEntry = array(
'uri' => $uri,
'name' => $name,
'group' => $group
);
dprint("addPhonebookEntry");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->addPhoneBookEntry($this->sipId, $phonebookEntry);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"
<div class=row-fluid>
<div class=span12>
<span class='alert alert-error'>Error (SipPort): %s (%s): %s</span>
</div>
</div>
",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
return true;
}
function updatePhonebookEntry()
{
dprint("updatePhonebookEntry()");
$uri = strtolower(trim($_REQUEST['uri']));
$group = trim($_REQUEST['group']);
$name = trim($_REQUEST['name']);
$phonebookEntry = array(
'name' => $name,
'uri' => $uri,
'group' => $group
);
//dprint_r($phonebookEntry);
dprint("updatePhonebookEntry");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->updatePhoneBookEntry($this->sipId, $phonebookEntry);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
return true;
}
function deletePhonebookEntry()
{
dprint("deletePhonebookEntry()");
$uri = strtolower($_REQUEST['uri']);
dprint("deletePhonebookEntry");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->deletePhoneBookEntry($this->sipId, $uri);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
return true;
}
function getPhoneBookEntries()
{
dprint("getPhoneBookEntries()");
if ($_REQUEST['task'] == 'search') {
$search_text = trim($_REQUEST['uri']);
}
$group = trim($_REQUEST['group']);
if (!strlen($search_text)) $search_text="%" ;
$match = array(
'uri' => '%'.$search_text.'%',
'name' => '%'.$search_text.'%'
);
if (strlen($group)) {
if ($group == "empty") {
$match['group'] = '';
} else {
$match['group'] = $group;
}
}
$range = array(
'start' => 0,
'count' => 100
);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getPhoneBookEntries($this->sipId, $match, $range);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
$this->PhonebookEntries=$result->entries;
//dprint_r($this->PhonebookEntries);
}
function showContactsTab()
{
dprint("showContactsTab()");
if ($this->show_directory) {
$chapter = sprintf(_("Directory"));
$this->showChapter($chapter);
print "<div class=row-fluid><div class=span12>";
print _("To find other SIP Addresses fill in the First Name or the Last Name and click the Search button. ");
print "</div>";
$this->showSearchDirectory();
print "</div>";
}
if ($this->rows || $_REQUEST['task'] == 'directory') {
// hide local contacts if we found a global contact
return true;
}
$chapter = sprintf(_("Don't Disturb")).' '.sprintf(_("Groups"));
$this->showChapter($chapter);
print "<div class=row-fluid><div class=span12>";
print _("You can organize contacts into groups that can be used to accept incoming calls in Don't Disturb section. ");
print "</div></div>";
$adminonly = $_REQUEST['adminonly'];
$accept = $_REQUEST['accept']; // selected search group;
$task = $_REQUEST['task'];
//if ($task == "search" ){
$search_text = $_REQUEST['uri'];
// }
$confirm = $_REQUEST['confirm'];
$group = $_REQUEST['group'];
$uri = $_REQUEST['uri'];
$name = $_REQUEST['name'];
if ($task == "deleteContact" && $confirm) {
$this->deletePhonebookEntry();
unset($task);
unset($confirm);
} elseif ($task == "update") {
$this->updatePhonebookEntry();
unset($task);
} elseif ($task == "add") {
$this->addPhonebookEntry();
unset($task);
}
$this->getPhoneBookEntries();
$maxrowsperpage = 250;
$url_string = $this->url."&tab=contacts";
printf(
"
<script type=\"text/javascript\">
<!--//
function toggleVisibility(rowid) {
if (document.getElementById) {
row = document.getElementById(rowid);
if (row.style.display == 'block') {
row.style.display = 'none';
} else {
row.style.display = 'block';
}
return false;
} else {
return true;
}
}
function changeAction(url) {
if (url ==='add') {
document.forms.contacts.action='%s&task=add';
} else {
document.forms.contacts.action='%s&task=search';
}
}
//-->
</script>
<form class=form-inline name=contacts action=%s method=post>
<input type=hidden name=tab value=contacts>
<div class='control-group'>
<div class='control'>
<input class=span3 type=text size=20 name=uri placeholder=\"%s\">
<div class=input-append>
",
$this->url,
$this->url,
$this->url,
_("Add sip address or search for contacts")
);
if (count($this->PhonebookEntries) || $task == "search"){
$selected[$group] = "selected";
printf(
"
<select class=span2 name=group>
<option value=\"\">
%s
</option>
",
_('Group')
);
foreach (array_keys($this->PhonebookGroups) as $key) {
printf(
"<option value=\"%s\" %s>%si</option>",
$key,
$selected[$key],
$this->PhonebookGroups[$key]
);
}
printf(
"
<option value=\"\">------</option>
<option value=\"empty\" %s>%s</option>
</select>
<input class='btn btn-primary' type=submit onClick='changeAction(\"search\")' value=%s>
",
$selected['empty'],
_("No group"),
_("Search")
);
}
printf(
"
<input class='btn' type=submit onclick='changeAction(\"add\")' value=%s>
</div>
<span class=help-inline>%s</span>
</div>
</div>
</form>
",
_("Add"),
_("(wildcard %)")
);
if (count($this->PhonebookEntries)){
print "
<p>
<table class='table table-striped table-condensed' width=100% cellpadding=1 cellspacing=1 border=0>
<thead>
<tr>
<th class=list_header align=right></td>
";
print "<th class=list_header>";
print _("SIP Address");
print "</td>";
print "<th class=list_header>";
print "</th>";
print "<th class=list_header>";
print _("Display Name");
print "</th>";
print "<th class=list_header>";
print _("Group");
print "</th>";
print "<th class=list_header>";
print _("Action");
print "</th>";
print "</tr></thead>";
foreach (array_keys($this->PhonebookEntries) as $_entry) {
$found = $i + 1;
$rr = floor($found / 2);
$mod = $found - $rr * 2;
if ($mod == 0) {
$_class = 'odd';
} else {
$_class = 'even';
}
printf(
"
<tr class='%s contacts_table'>
<form name=\"Entry%s\" class=form-inline action=\"%s&tab=%s\">
%s
<input type=hidden name=tab value=\"%s\">
<input type=hidden name=task value=\"update\">
<input type=hidden name=uri value=\"%s\">
<td>%s</td><td>%s</td>
",
$_class,
$found,
$this->url,
$this->tab,
$this->hiddenElements,
$this->tab,
$this->PhonebookEntries[$_entry]->uri,
$found,
$this->PhonebookEntries[$_entry]->uri
);
if (preg_match("/\%/", $this->PhonebookEntries[$_entry]->uri)) {
print "<td></td><td>";
} else {
printf(
"
<td>%s</td>
<td>
",
$this->PhoneDialURL($this->PhonebookEntries[$_entry]->uri)
);
}
printf("<div class='input-append' style='margin-bottom:0px' ><input style='margin-bottom:0' type=text name=name value='%s'>", $this->PhonebookEntries[$_entry]->name);
printf("<a class=btn href=\"javascript: document.Entry$found.submit()\">%s</a></div>", _("Update"));
print "</td><td>";
printf(
"<select style='margin-bottom:0' name=group onChange=\"location.href='%s&task=update&uri=%s&name=%s&group='+this.options[this.selectedIndex].value\">",
$url_string,
urlencode($this->PhonebookEntries[$_entry]->uri),
urlencode($this->PhonebookEntries[$_entry]->name)
);
print "<option value=\"\">";
$selected_grp[$this->PhonebookEntries[$_entry]->group] = "selected";
foreach (array_keys($this->PhonebookGroups) as $_key) {
printf(
"<option value=\"%s\" %s>%s</option>",
$_key,
$selected_grp[$_key],
$this->PhonebookGroups[$_key]
);
}
unset($selected_grp);
print "</select>";
print "</td>";
if ($task == "deleteContact" && $uri == $this->PhonebookEntries[$_entry]->uri) {
print "<td bgcolor=red style='vertical-align: middle'>";
printf(
"<a href=%s&task=deleteContact&uri=%s&confirm=1&search_text=%s>",
$url_string,
urlencode($this->PhonebookEntries[$_entry]->uri),
urlencode($search_text)
);
print _("Confirm");
} else {
print "<td>";
printf(
"<a href=%s&task=deleteContact&uri=%s&search_text=%s>",
$url_string,
urlencode($this->PhonebookEntries[$_entry]->uri),
urlencode($search_text)
);
if ($this->delete_img) {
//print $this->delete_img;
print "<i class=\"icon-remove\"></i>";
} else {
print _("Delete");
}
}
print "</a>";
print "</td></form></tr>";
$i++;
}
print "</table>";
print "</td></tr></table>";
}
}
function exportPhonebook($userAgent)
{
dprint("exportPhonebook()");
$this->getPhonebookEntries();
$this->contentType = "Content-type: text/csv";
if (!is_array($this->PhonebookEntries) || !count($this->PhonebookEntries)) return true;
if (!$userAgent) $userAgent = 'snom';
if ($userAgent == 'snom') {
$this->export_filename = "tbook.csv";
$phonebook .= sprintf("Name,Address,Group\n");
} elseif ($userAgent == 'eyebeam') {
$phonebook .= sprintf("Name,Group Name,SIP URL,Proxy ID\n");
} elseif ($userAgent == 'csco') {
$this->contentType = "Content-type: text/xml";
$this->export_filename = "directory.xml";
$phonebook .= sprintf(
"<CiscoIPPhoneDirectory>\n\t<Title>%s</Title>\n\t<Prompt>Directory</Prompt>\n",
$this->account
);
} elseif ($userAgent == 'unidata') {
$this->export_filename = "phonebook.csv";
$phonebook .= sprintf("Index,Name,,,,\n");
$phonebook .= sprintf("0,Undefined,,,,\n");
$z = 1;
foreach ($this->PhonebookGroups as $_group) {
$this->groupIndex[$_group] = $z;
$phonebook .= sprintf("%s,%s,,,,\n", $z, $_group);
$z++;
}
$phonebook .= sprintf("\nIndex,Name,RdNm,Tel,Group\n");
}
$found = 0;
foreach (array_keys($this->PhonebookEntries) as $_entry) {
$fname = $this->PhonebookEntries[$_entry]->firstName;
$lname = $this->PhonebookEntries[$_entry]->lastName;
$uri = $this->PhonebookEntries[$_entry]->uri;
$group = $this->PhonebookEntries[$_entry]->group;
if (!preg_match("/[_%]/", $uri)) {
$uri = substr($uri, 4);
$els = explode("@", $uri);
if ($els[1] == $this->domain) $uri=$els[0];
if ($userAgent == 'snom') {
$phonebook .= sprintf(
"%s %s,%s,%s\n",
$fname,
$lname,
$uri,
$this->PhonebookGroups[$group]
);
} elseif ($userAgent == 'unidata' && $fname && $lname) {
$phonebook .= sprintf(
"%s,%s,%s %s,%s,%s\n",
$found,
$fname,
$fname,
$lname,
$uri,
$this->PhonebookGroups[$group]
);
} elseif ($userAgent == 'eyebeam') {
$phonebook .= sprintf(
"%s %s,%s,1\n",
$fname,
$lname,
$this->PhonebookEntries[$_entry]->uri,
$this->PhonebookGroups[$group]
);
} elseif ($userAgent == 'csco') {
$phonebook .= sprintf(
"\n\t<DirectoryEntry>\n\t<Name>%s %s</Name>\n\t<Telephone>%s</Telephone>\n\t</DirectoryEntry>\n",
$fname,
$lname,
$uri
);
}
$found++ ;
}
}
if ($userAgent == 'csco') {
$phonebook .= sprintf("\n</CiscoIPPhoneDirectory>\n");
}
Header($this->contentType);
$_header = sprintf("Content-Disposition: inline; filename=%s", $this->export_filename);
Header($_header);
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Pragma: no-cache");
print $phonebook;
}
function getRejectMembers()
{
dprint("getRejectMembers()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getRejectMembers($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
$this->rejectMembers = $result;
//dprint_r($this->rejectMembers);
return true;
}
function setRejectMembers()
{
$members = array();
$rejectMembers = $_REQUEST['rejectMembers'];
foreach ($rejectMembers as $_member) {
if (strlen($_member) && !preg_match("/^sip:/", $_member)) {
$_member = 'sip:'.$_member;
}
if (strlen($_member)) $members[] = $_member;
}
dprint("setRejectMembers");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setRejectMembers($this->sipId, $members);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf(
"<p><font color=red>Error (SipPort): %s (%s): %s</font>",
$error_msg,
$error_fault->detail->exception->errorcode,
$error_fault->detail->exception->errorstring
);
return false;
}
}
function getJournalEntries() {
$this->journalEntries['success'] = false;
$this->journalEntries['error_message'] = NULL;
$this->journalEntries['results'] = array();
$return_summary = $_REQUEST['summary'];
if ($this->chat_replication_backend == 'mysql') {
$this->db = new DB_CDRTool();
$where="";
if ($_REQUEST['except_uuid']) {
$where.= sprintf(" and uuid <> '%s'", addslashes($_REQUEST['except_uuid']));
}
if ($_REQUEST['after_id']) {
$after_id = intval($_REQUEST['after_id']);
} else {
$after_id = 0;
}
$where.= sprintf(" and id > %d", addslashes($after_id));
if ($_REQUEST['after_timestamp']) {
$where.= sprintf(" and timestamp > '%s'", addslashes($_REQUEST['after_timestamp']));
}
if ($_REQUEST['limit'] and intval($_REQUEST['limit']) < 5000) {
$limit = intval($limit);
} else {
$limit = 5000;
}
$query=sprintf("select * from client_journal where account = '%s' %s order by timestamp ASC limit %d", addslashes($this->account), $where, $limit);
if (!$this->db->query($query)) {
$this->journalEntries['error_message'] = 'Database Failure';
$this->journalEntries['rows'] = 0;
return false;
} else {
$this->journalEntries['success'] = true;
$this->journalEntries['rows'] = $this->db->num_rows();
}
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$entry = array(
'id' => $this->db->f('id'),
'source' => 'default',
'timestamp' => $this->db->f('timestamp'),
'account' => $this->db->f('account'),
'uuid' => $this->db->f('uuid'),
'ip_address' => $this->db->f('ip_address'),
'data' => $this->db->f('data')
);
$this->journalEntries['results'][]=$entry;
}
}
- } else {
- if (!$this->getMongoJournalTable()) {
- $result['success'] = false;
- $result['error_message'] = $this->mongo_exception;
- return $result;
- }
-
- $mongo_where=array();
- $mongo_where['account'] = $this->account;
- if ($_REQUEST['except_uuid']) {
- $mongo_where['uuid'] = array('$ne' => $_REQUEST['except_uuid']);
- }
-
- if ($_REQUEST['after_timestamp']) {
- $mongo_where['timestamp'] = array('$gt' => intval($_REQUEST['after_timestamp']));
- }
-
- if ($_REQUEST['limit'] and intval($_REQUEST['limit']) < 5000) {
- $limit = intval($limit);
- } else {
- $limit = 5000;
- }
-
- $cursor = $this->mongo_table_ro->find($mongo_where)->sort(array('timestamp'=>1))->limit($limit)->slaveOkay();
- $this->journalEntries['success'] = true;
- $this->journalEntries['rows'] = $cursor->count();
-
- foreach ($cursor as $result) {
- $entry = array(
- 'id' => strval($result['_id']),
- 'source' => 'default',
- 'timestamp' => $result['timestamp'],
- 'account' => $result['account'],
- 'uuid' => $result['uuid'],
- 'ip_address' => $result['ip_address'],
- 'data' => $result['data']
- );
- $this->journalEntries['results'][]=$entry;
- }
-
- if ($return_summary) {
- $mongo_where=array();
- $mongo_where['account'] = $this->account;
- if ($_REQUEST['except_uuid']) {
- $mongo_where['uuid'] = array('$ne' => $_REQUEST['except_uuid']);
- }
-
- if ($_REQUEST['limit'] and intval($_REQUEST['limit']) < 5000) {
- $limit = intval($limit);
- } else {
- $limit = 5000;
- }
-
- $cursor = $this->mongo_table_ro->find($mongo_where)->sort(array('timestamp'=>1))->limit($limit)->slaveOkay();
- foreach ($cursor as $result) {
- $entry = array(
- 'journal_id' => strval($result['_id']),
- 'timestamp' => $result['timestamp'],
- );
- $this->journalEntries['summary'][]=$entry;
- }
- }
}
return True;
}
function putJournalEntries() {
$result['results'] = array();
if (strlen($_REQUEST['uuid'])) {
$uuid = $_REQUEST['uuid'];
} else {
$result['success'] = false;
$result['error_message'] = 'Missing uuid';
return $result;
}
if (strlen($_REQUEST['data'])) {
$data = $_REQUEST['data'];
} else {
$result['success'] = false;
$result['error_message'] = 'Missing data';
return $result;
}
if ($this->chat_replication_backend == 'mysql') {
$this->db = new DB_CDRTool();
- } else if ($this->chat_replication_backend == 'mongo') {
- if (!$this->getMongoJournalTable()) {
- $result['success'] = false;
- $result['error_message'] = $this->mongo_exception;
- return $result;
- }
}
if ($rows=json_decode($data)) {
foreach ($rows as $row) {
if (!property_exists($row, 'data')) {
continue;
}
$entry = $row->data;
if (property_exists($row, 'action')) {
$action = $row->action;
} else {
$action = 'add';
}
if ($this->chat_replication_backend == 'mysql') {
$query=sprintf("insert into client_journal (timestamp, account, uuid, data, ip_address) values (NOW(),'%s', '%s', '%s', '%s')", addslashes($this->account), addslashes($uuid), addslashes($entry), addslashes($_SERVER['REMOTE_ADDR']));
if (!$this->db->query($query)) {
$result['results'][]=array('id' => $row->id,
'journal_id' => NULL,
'source' => 'default'
);
} else {
$query="select LAST_INSERT_ID() as id";
$this->db->query($query);
$this->db->next_record();
$id = $this->db->f('id');
$result['results'][]=array('id' => $row->id,
'journal_id' => $id,
'source' => 'default'
);
}
- } else if ($this->chat_replication_backend == 'mongo') {
- if ($action == 'add') {
- $timestamp = time();
- $mongo_query=array('timestamp' => $timestamp,
- 'datetime' => Date("Y-m-d H:i:s", $timestamp),
- 'account' => $this->account,
- 'uuid' => $uuid,
- 'data' => $entry,
- 'ip_address' => $_SERVER['REMOTE_ADDR']
- );
-
- $this->mongo_table_rw->insert($mongo_query);
- if ($mongo_query['_id']) {
- $mongo_id = strval($mongo_query['_id']);
- $result['results'][]=array('id' => $row->id,
- 'journal_id' => $mongo_id,
- 'source' => 'default'
- );
- } else {
- $result['results'][]=array('id' => $row->id,
- 'journal_id' => NULL,
- 'source' => 'default'
- );
- }
- } else if ($action == 'remove') {
- if (property_exists($row, 'journal_id')) {
- $mongo_query=array(
- 'account' => $this->account,
- 'journal_id' => $row->journal_id
- );
-
- $this->mongo_table_rw->remove($mongo_query);
- $result['results'][]=array('id' => NULL,
- 'journal_id' => $row->journal_id
- );
- }
- }
}
}
$result['success'] = true;
} else {
$result['success'] = false;
$result['error_message'] = 'Json decode error';
}
return $result;
}
function deleteJournalEntries() {
if (strlen($_REQUEST['data'])) {
$data = $_REQUEST['data'];
$entries = json_decode($data);
} else {
if (strlen($_REQUEST['journal_id'])) {
$entries=array($_REQUEST['journal_id']);
} else {
$result['success'] = false;
$result['error_message'] = 'Missing data';
return $result;
}
}
if ($this->chat_replication_backend == 'mysql') {
$this->db = new DB_CDRTool();
- } else if ($this->chat_replication_backend == 'mongo') {
- if (!$this->getMongoJournalTable()) {
- $result['success'] = false;
- $result['error_message'] = $this->mongo_exception;
- return $result;
- }
}
if ($entries) {
if ($this->chat_replication_backend == 'mysql') {
$journal_id_sql="";
foreach ($entries as $entry) {
$journal_id_sql.=sprintf("'%s',",$entry);
}
$journal_id_sql = rtrim($journal_id_sql,",");
$query=sprintf("delete from client_journal where account in '%s' and journal_id in (%s)", addslashes($this->account), addslashes($journal_id_sql));
if (!$this->db->query($query)) {
$result['error_message'] = 'database error';
} else {
$result['success'] = true;
}
-
- } else if ($this->chat_replication_backend == 'mongo') {
- $id_entries=array();
- foreach ($entries as $entry) {
- $id_entries[] = new MongoId($entry);
- }
- $mongo_query=array('account' => $this->account,
- '_id' => array('$in'=> $id_entries)
- );
-
- $this->mongo_table_rw->remove($mongo_query);
- $result['success'] = true;
}
} else {
$result['success'] = false;
$result['error_message'] = 'No journal entries provided';
}
return $result;
}
function getAcceptRules() {
dprint("getAcceptRules()");
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->getAcceptRules($this->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
foreach(array_keys($result->rules->persistent) as $_rule) {
$_key=$result->rules->persistent[$_rule]->days;
$this->acceptRules['persistent'][$_key]=array('start' =>$result->rules->persistent[$_rule]->start,
'stop' =>$result->rules->persistent[$_rule]->stop,
'groups'=>$result->rules->persistent[$_rule]->groups);
}
$this->acceptRules['temporary']=array('groups' => $result->rules->temporary->groups,
'duration'=> $result->rules->temporary->duration
);
$this->acceptRules['groups'] = $result->nonEmptyGroups;
//dprint_r($this->acceptRules);
return true;
}
function setAcceptRules() {
dprint("setAcceptRules()");
$persistentAcceptArray=array();
$temporaryAcceptArray=array();
foreach (array_keys($this->acceptDailyProfiles) as $profile) {
unset($groups);
$radio_persistentVarName='radio_persistent_'.$profile;
$radio_persistent=$_REQUEST[$radio_persistentVarName];
if ($radio_persistent=="0") {
$groups[]='everybody';
} else if ($radio_persistent=="1") {
$groups[]='nobody';
} else if ($radio_persistent=="2") {
$groupsVarName='groups_'.$profile;
$groups=$_REQUEST[$groupsVarName];
}
$startVarName='start_'.$profile;
$start=$_REQUEST[$startVarName];
$stopVarName='stop_'.$profile;
$stop=$_REQUEST[$stopVarName];
if (!preg_match("/^[0-2][0-9]:[0-5][0-9]$/",$start) ||
!preg_match("/^[0-2][0-9]:[0-5][0-9]$/",$stop) ||
($start=="00:00" && $stop=="00:00") ||
!$start ||
!$stop ||
($radio_persistent=="2" && (!is_array($groups) || !count($groups) )) ) {
continue;
}
$persistentAcceptArray[]=array('start' => $start,
'stop' => $stop,
'groups' => $groups,
'days' => intval($profile)
);
}
// temporary
$radio_temporary=$_REQUEST['radio_temporary'];
unset($groups_temporary);
if ($radio_temporary=="0") {
$groups_temporary[]='everybody';
} else if ($radio_temporary=="1") {
$groups_temporary[]='nobody';
} else if ($radio_temporary=="2") {
$groups_temporary=$_REQUEST['groups_temporary'];
}
if (!is_array($groups_temporary)) $groups_temporary=array();
$duration=$_REQUEST['duration'];
$temporaryAccept=array("groups" => $groups_temporary,
"duration"=> intval($duration)
);
// combine persistent and temporary
$rules=array("persistent" =>$persistentAcceptArray,
"temporary" =>$temporaryAccept);
$this->SipPort->addHeader($this->SoapAuth);
$result = $this->SipPort->setAcceptRules($this->sipId,$rules);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error (SipPort): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
return true;
}
function showAcceptTab() {
if (in_array("trunking",$this->groups)) {
return false;
}
$chapter=sprintf(_("Do Not Disturb"));
$this->showChapter($chapter);
$this->getAcceptRules();
$this->getVoicemail();
$this->getDivertTargets();
$this->getDiversions();
print "
<form method=post class=form-horizontal name=sipsettings onSubmit=\"return checkForm(this)\">
";
print "
<div class=row-fluid>
<div class=span12>
<p>";
print _("You can reject calls depending on the time of day and Caller-ID. ");
print _("You can create custom groups in the Contacts page like Family or Coworkers. ");
print "</p>
<p>";
print _("Rejected calls are diverted based on the Unavailable condition in the Call Forwarding page. ");
print "<p>";
print "<p class=desc>";
printf (_("Your current time is: %s"),$this->timezone);
$timestamp=time();
$LocalTime=getLocalTime($this->timezone,$timestamp);
print " $LocalTime";
print "
</div>
</div>
";
// $chapter=sprintf(_("Rules"));
// $this->showChapter($chapter);
/* print "
<div class=row-fluid>
<div class=span12>";
print _("This will override the permanent rules for the chosen duration. ");
print "
</div>
</div>
";
*/
if ($this->acceptRules['temporary']['duration']) {
$class_e='error';
} else {
$class_e='';
}
// print "<div class='control-group $class_e'>
// <label for=duration class=control-label>";
// print _("Duration");
// print "</label>
//";
// print "<span class=help-inline>";
// print _("minute(s)");
// print "</span>";
//print "</span></div>
//</div>
//";
$chapter=sprintf(_("Rules"));
$this->showChapter($chapter);
print "
<div class=row-fluid>
";
print "<table class='table table-condensed table-striped middle' border=0 width=100%>";
print "<thead><tr>
<tr>
<th colspan=6>
";
print _("Temporary");
print "</th></tr></thead>";
print "<tr><td style='vertical-align: middle'><span>";
print _("Duration");
print "</span></td><td colspan='2' style='vertical-align: middle'>";
if ($this->acceptRules['temporary']['duration']) {
printf ('
<script LANGUAGE="JavaScript">
var minutes = %s;
ID=window.setTimeout("update();", 1000*60);
function update() {
minutes--;
document.sipsettings.minutes.value = minutes;
ID=window.setTimeout("update();",1000*60);
}
</script>
',$this->acceptRules['temporary']['duration']);
print " <input type=text name=minutes size=3 maxsize=3 value=\"";
print $this->acceptRules['temporary']['duration'];
print "\" disabled=true>";
print " <input type=hidden name=accept_temporary_remain value=\"";
print $this->acceptRules['temporary']['duration'];
print "\"> ";
} else {
print "<select id=testselect rel='popover' class=input-medium name=duration data-original-title='";
print _("Temporary Rules");
print "' data-content='";
print _("This will override the permanent rules for the chosen duration.");
print "'> ";
print "<option>";
print "<option value=1 > 1";
print "<option value=5 > 5";
print "<option value=10 > 10";
print "<option value=20 > 20";
print "<option value=30 > 30";
print "<option value=45 > 45";
print "<option value=60 > 60";
print "<option value=90 > 90";
print "<option value=120>120";
print "<option value=150>150";
print "<option value=180>180";
print "<option value=240>240";
print "<option value=480>480";
print "</select><span> ";
print _("Minute(s)");
print "</span>";
}
print "</td>";
$_name="radio_temporary";
$_checked_everybody="";
$_checked_nobody="";
$_checked_groups="";
if (is_array($this->acceptRules['temporary']['groups']) &&in_array("everybody",$this->acceptRules['temporary']['groups'])) {
$_checked_everybody="checked";
} else if (is_array($this->acceptRules['temporary']['groups']) && in_array("nobody",$this->acceptRules['temporary']['groups'])) {
$_checked_nobody="checked";
} else if (!in_array('everybody',$this->acceptRules['temporary']['groups']) &&
!in_array('nobody',$this->acceptRules['temporary']['groups']) &&
count($this->acceptRules['temporary']['groups'])) {
$_checked_groups="checked";
}
if ($_checked_nobody) {
$class_nobody="checked_groups";
} else {
$class_nobody="note";
}
printf ("<td style='vertical-align:middle' class='note'><input type=radio name=%s value=0 %s> %s</td> ",$_name,$_checked_everybody,_("Everybody"));
printf ("<td style='vertical-align:middle' class='$class_nobody'><input type=radio name=%s value=1 %s> %s </td>",$_name,$_checked_nobody,_("Nobody"));
$c=count($this->acceptRules['groups']);
if ($_checked_groups) {
$class_groups="checked_groups";
} else {
$class_groups="note";
}
print "<td style='vertical-align:middle' class='$class_groups'>";
if (count($this->acceptRules['groups'])>2) {
printf ("<input type=radio name=%s value=2 %s class=hidden>",$_name,$_checked_groups);
$i=0;
foreach(array_keys($this->acceptRules['groups']) as $_group) {
$i++;
if (preg_match("/(everybody|nobody)/",$this->acceptRules['groups'][$_group])) continue;
if (in_array($this->acceptRules['groups'][$_group],$this->acceptRules['temporary']['groups'])) {
$_checked="checked";
} else {
$_checked="";
}
$_name="groups_temporary[]";
printf ("<span><input style='vertical-align:top' type=checkbox name=%s value=%s onClick=\"document.sipsettings.radio_temporary[2].checked=true\" %s> %s</span>\n",
$_name,
$this->acceptRules['groups'][$_group],
$_checked,
$this->PhonebookGroups[$this->acceptRules['groups'][$_group]]
);
}
}
print "</td></tr>";
print "<thead>
<th colspan=6>
";
print _("Permanent");
print "</th></tr><tr>
<th>";
print _("Days");
print "</th>
<th colspan=2>";
print _("Time Interval");
print "</th>
<th colspan=3>";
print _("Groups");
print "</th>
</tr></thead>
";
foreach (array_keys($this->acceptDailyProfiles) as $profile) {
if ($this->acceptRules['persistent'][$profile]['start'] || $this->acceptRules['persistent'][$profile]['stop']) {
$class="checked_groups";
$class2="label label-info";
} else {
$class="mhj";
$class2='';
}
if ($profile==1) {
print "<tr><td colspan=6 style='height:3px; padding:0px' bgcolor=lightgrey></td></tr>";
}
print "
<tr>
<td style='vertical-align: middle;'><span class='$class2'>";
printf ("%s",$this->acceptDailyProfiles[$profile]);
print "</span></td>";
unset($selected_StartTime);
$selected_StartTime[$this->acceptRules['persistent'][$profile]['start']]="selected";
printf ("<td><select class=span10 name=start_%s>",$profile);
$t=0;
$j=0;
print "<option>";
while ($t<24) {
if (!$j) {
if (strlen($t)==1) {
$t1="0".$t.":00";
} else {
$t1=$t.":00";
}
$j++;
} else {
if (strlen($t)==1) {
$t1="0".$t.":30";
} else {
$t1=$t.":30";
}
$j=0;
$t++;
}
print "<option $selected_StartTime[$t1]>$t1";
}
printf ("<option %s>23:59",$selected_StartTime['23:59']);
print "</select>";
unset($selected_StopTime);
$selected_StopTime[$this->acceptRules['persistent'][$profile]['stop']]="selected";
printf ("<td><select class=span10 name=stop_%s>",$profile);
$t=0;
$j=0;
print "<option>";
while ($t<24) {
if (!$j) {
if (strlen($t)==1) {
$t1="0".$t.":00";
} else {
$t1=$t.":00";
}
$j++;
} else {
if (strlen($t)==1) {
$t1="0".$t.":30";
} else {
$t1=$t.":30";
}
$j=0;
$t++;
}
print "<option $selected_StopTime[$t1]> $t1";
}
printf ("<option %s>23:59",$selected_StopTime['23:59']);
print "</select>";
$_name="radio_persistent_".$profile;
$_checked_everybody="";
$_checked_nobody="";
$_checked_groups="";
if (is_array($this->acceptRules['persistent'][$profile]['groups']) && in_array("everybody",$this->acceptRules['persistent'][$profile]['groups'])) {
$_checked_everybody="checked";
} else if (is_array($this->acceptRules['persistent'][$profile]['groups']) && in_array("nobody",$this->acceptRules['persistent'][$profile]['groups'])) {
$_checked_nobody="checked";
} else if (!in_array('everybody',$this->acceptRules['persistent'][$profile]['groups']) &&
!in_array('nobody',$this->acceptRules['persistent'][$profile]['groups']) &&
count($this->acceptRules['persistent'][$profile]['groups'])) {
$_checked_groups="checked";
} else {
$_checked_everybody="checked";
}
if ($_checked_nobody) {
$class_nobody="checked_groups";
} else {
$class_nobody="note";
}
printf ("<td style='vertical-align: middle;' class='note'><input style='vertical-align: top;' type=radio name=%s value=0 %s> %s</td>",$_name,$_checked_everybody,_("Everybody"));
printf ("<td style='vertical-align: middle;' class='$class_nobody'><input style='vertical-align: top;' type=radio name=%s value=1 %s> %s</td>",$_name,$_checked_nobody,_("Nobody"));
$c=count($this->acceptRules['groups']);
if ($_checked_groups) {
$class_groups="checked_groups";
} else {
$class_groups="note";
}
print "<td style='vertical-align: middle' class='controls $class_groups'>";
if (count($this->acceptRules['groups'])>2) {
printf ("<input style='vertical-align: top;' type=radio name=%s value=2 %s class=hidden>",$_name,$_checked_groups);
$i=0;
foreach(array_keys($this->acceptRules['groups']) as $_group) {
$i++;
if (preg_match("/(everybody|nobody)/",$this->acceptRules['groups'][$_group])) continue;
if (in_array($this->acceptRules['groups'][$_group],$this->acceptRules['persistent'][$profile]['groups'])) {
$_checked="checked";
} else {
$_checked="";
}
$_name="groups_".$profile."[]";
printf ("<input style='vertical-align: top;' type=checkbox name=%s value=%s onClick=\"document.sipsettings.radio_persistent_%s[2].checked=true\" %s> %s ",
$_name,
$this->acceptRules['groups'][$_group],
$profile,
$_checked,
$this->PhonebookGroups[$this->acceptRules['groups'][$_group]]
);
}
}
print "</td>
</tr>
";
}
print "</table></div>";
print "
<div class='form-actions'>
<input type=hidden name=action value=\"set accept rules\">
";
print "
<input class='btn' type=submit value=\"";
print _("Save");
print "\"
onClick=saveHandler(this)>
";
print "
</div>
";
print $this->hiddenElements;
print "
</form>
";
$chapter=sprintf(_("Rejected Callers"));
$this->showChapter($chapter);
print "
<form class=form-horizontal method=post name=reject_form onSubmit=\"return checkForm(this)\">
";
print "
<div class=row-fluid>
<div class=span12>";
print _("Use %Number@% to match PSTN numbers and user@domain to match SIP Addresses");
print "
</div>
</div>
";
if ($this->getRejectMembers()) {
foreach ($this->rejectMembers as $_member) {
$j++;
$rr=floor($j/2);
$mod=$j-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
print "
<div class='control-group $_class'>";
print "<label class=control-label>";
print _("SIP Address");
print "</label>";
print "<div class=controls>
<input type=text size=35 name=rejectMembers[] value=\"$_member\">
</div>";
print "</div>";
}
}
print "<div class=control-group>";
print "<label class=control-label>";
print _("SIP Address");
print "</label>";
print "<div class=controls>
<input type=text size=35 name=rejectMembers[]>";
print "</div></div>";
print "<div class='form-actions'>";
print "<input class=btn type=submit value=\"";
print _("Save");
print "\"
onClick=saveHandler(this)>
";
print "</div></div>";
print "
<input type=hidden name=action value=\"set reject\">
";
print $this->hiddenElements;
print "
</form>
";
}
function deleteAccount($skip_html=False) {
dprint ("SipSettings->deleteAccount($this->account, $this->email)");
$this->getBalanceHistory();
if (count($this->balance_history) != "0" && $this->login_type == 'subscriber') {
return false;
}
if (!$this->email && !$skip_html) {
print "<p><font color=blue>";
print _("Please fill in the e-mail address. ");
print "</font>";
return false;
}
$subject = sprintf("Removal of SIP account %s",$this->account);
//$this->expire_date = new DateTime('now');
$this->expire_date = date("Y-m-d H:i:s",strtotime("+2 days"));
$this->ip = $_SERVER['REMOTE_ADDR'];
$tpl_html = $this->getEmailDeleteTemplateHTML($this->reseller, $this->Preferences['language']);
//dprint("$tpl_html");
if (!$tpl_html && !$skip_html) {
print "<p><font color=red>";
print _("Error: no HTML email template found");
print "</font>";
return false;
}
//print "$tpl_html";
define("SMARTY_DIR", "/usr/share/php/smarty/libs/");
include_once(SMARTY_DIR . 'Smarty.class.php');
$smarty = new Smarty;
$smarty->template_dir = '.';
//$smarty->use_sub_dirs = true;
//$smarty->cache_dir = 'templates_c';
$smarty->assign('client', $this);
//print"$this->sip_settings_page";
if ($tpl_html) {
$bodyhtml = $smarty->fetch($tpl_html);
}
include_once 'Mail.php';
include_once 'Mail/mime.php' ;
$hdrs = array(
'From' => $this->support_email,
'Subject' => $subject,
// 'Cc' => $this->support_email
);
//dprint("1");
$crlf = "\n";
$mime = new Mail_mime($crlf);
if ($tpl_html) {
$mime->setHTMLBody($bodyhtml);
}
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
if ($mail->send($this->email, $hdrs, $body)) {
if (!$skip_html) {
$this->Preferences['account_delete_request']=1;
$this->saveSettings();
$this->getAccount($this->account);
print "<p>";
printf (_("Removal email has been sent to %s"), $this->email);
}
return 1;
}
}
function sendEmail($skip_html=False) {
dprint ("SipSettings->sendEmail($this->email)");
$this->getVoicemail();
$this->getEnumMappings();
$this->getAliases();
$this->countAliases=count($this->aliases);
if (!$this->email && !$skip_html) {
print "<p><font color=blue>";
print _("Please fill in the e-mail address. ");
print "</font>";
return false;
}
$subject = sprintf("SIP Account settings %s",$this->account);
//if ($_REQUEST['sip_filter'] == '1') {
// $identifier = $this->RandomIdentifier();
//}
$tpl = $this->getEmailTemplate($this->reseller, $this->Preferences['language']);
if (!$tpl && !$skip_html) {
print "<p><font color=red>";
print _("Error: no email template found");
print "</font>";
return false;
}
$tpl_html = $this->getEmailTemplateHTML($this->reseller, $this->Preferences['language']);
//if (!$tpl_html && !$skip_html) {
// print "<p><font color=red>";
// print _("Error: no HTML email template found");
// print "</font>";
//}
if (!$this->store_clear_text_password) {
$web_password = '';
}
if (in_array("free-pstn",$this->groups)) $this->allowPSTN=1; // used by smarty
define("SMARTY_DIR", "/usr/share/php/smarty/libs/");
include_once(SMARTY_DIR . 'Smarty.class.php');
$smarty = new Smarty;
$smarty->template_dir = '.';
//$smarty->use_sub_dirs = true;
//$smarty->cache_dir = 'templates_c';
$smarty->assign('client', $this);
$bodyt = $smarty->fetch($tpl);
if ($tpl_html) {
$bodyhtml = $smarty->fetch($tpl_html);
}
include_once 'Mail.php';
include_once 'Mail/mime.php' ;
$hdrs = array(
'From' => $this->support_email,
'Subject' => $subject
);
$crlf = "\n";
$mime = new Mail_mime($crlf);
$mime->setTXTBody($bodyt);
if ($tpl_html) {
$mime->setHTMLBody($bodyhtml);
}
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
//dprint_r($_REQUEST);
if ($mail->send($this->email, $hdrs, $body)) {
if (!$skip_html) {
print "<p>";
printf (_("SIP settings have been sent to %s"), $this->email);
}
if ($_REQUEST['password_reset'] == 'on') {
$this->sendPasswordReset($skip_html);
}
return 1;
}
}
function sendChangedEmail($skip_html=False, $fields=array()) {
dprint ("SipSettings->sendChangedEmail($this->email)");
//dprint_r($fields);
$this->ip = $_SERVER['REMOTE_ADDR'];
if (!$this->email && !$skip_html) {
print "<p><font color=blue>";
print _("Please fill in the e-mail address. ");
print "</font>";
return false;
}
//$this->location = "Unknown";
$_loc=geoip_record_by_name($_SERVER['REMOTE_ADDR']);
if ($_loc['country_name']) {
$this->location = $_loc['country_name'];
}
$subject = sprintf("SIP Account %s changed",$this->account);
$tpl = $this->getChangedEmailTemplate($this->reseller, $this->Preferences['language']);
if (!$tpl && !$skip_html) {
print "<p><font color=red>";
print _("Error: no email template found");
print "</font>";
return false;
}
$tpl_html = $this->getChangedEmailTemplateHTML($this->reseller, $this->Preferences['language']);
define("SMARTY_DIR", "/usr/share/php/smarty/libs/");
include_once(SMARTY_DIR . 'Smarty.class.php');
$smarty = new Smarty;
$smarty->template_dir = '.';
//$smarty->use_sub_dirs = true;
//$smarty->cache_dir = 'templates_c';
$this->fields = $fields;
$smarty->assign('client', $this);
$bodyt = $smarty->fetch($tpl);
if ($tpl_html) {
$bodyhtml = $smarty->fetch($tpl_html);
}
include_once 'Mail.php';
include_once 'Mail/mime.php' ;
$hdrs = array(
'From' => $this->support_email,
'Subject' => $subject
);
$crlf = "\n";
$mime = new Mail_mime($crlf);
$mime->setTXTBody($bodyt);
if ($tpl_html) {
$mime->setHTMLBody($bodyhtml);
}
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
//dprint_r($_REQUEST);
if ($mail->send($this->email, $hdrs, $body)) {
return 1;
}
}
function sendRemoveAccount() {
$this->ip = $_SERVER['REMOTE_ADDR'];
$subject=sprintf ("The account %s was removed from IP Address: %s",$this->account, $this->ip);
syslog(LOG_NOTICE, $subject);
}
function sendPasswordReset($skip_html=False) {
dprint ("SipSettings->sendPasswordEmail($this->email)");
$identifier = RandomIdentifier();
$this->db = new DB_CDRTool();
$this->ip = $_SERVER['REMOTE_ADDR'];
$insert_data = array (
'sip_account' => $this->account,
'email' => $this->email,
'ip' => $this->ip
);
$this->expire=date("Y-m-d H:i:s",strtotime("+30 minutes"));
$query=sprintf("insert into memcache set `key`='email_%s', `value`='%s', `expire`='%s'",
$identifier,
json_encode($insert_data),
$this->expire );
$this->db->query($query);
$this->identifier = $identifier;
dprint("$query <br> Identifier: $identifier");
if (!$this->email && !$skip_html) {
print "<p><font color=blue>";
print _("Please fill in the e-mail address. ");
print "</font>";
return false;
}
$subject = sprintf("Password reset for %s",$this->account);
$tpl_html = $this->getEmailPasswordTemplateHTML($this->reseller, $this->Preferences['language']);
define("SMARTY_DIR", "/usr/share/php/smarty/libs/");
include_once(SMARTY_DIR . 'Smarty.class.php');
$smarty = new Smarty;
$smarty->template_dir = '.';
//$smarty->use_sub_dirs = true;
//$smarty->cache_dir = 'templates_c';
$smarty->assign('client', $this);
$bodyhtml = $smarty->fetch($tpl_html);
include_once 'Mail.php';
include_once 'Mail/mime.php' ;
$hdrs = array(
'From' => $this->support_email,
'Subject' => $subject
);
$crlf = "\n";
$mime = new Mail_mime($crlf);
$mime->setHTMLBody($bodyhtml);
$body = $mime->get();
$hdrs = $mime->headers($hdrs);
$mail =& Mail::factory('mail');
//dprint_r($_REQUEST);
if ($mail->send($this->email, $hdrs, $body) && !$skip_html) {
print "<li>";
printf (_("Password reset has been sent to %s"), $this->email);
print "</li>";
}
return 1;
}
function checkSettings() {
dprint ("checkSettings()");
foreach ($this->form_elements as $el) {
${$el}=trim($_REQUEST[$el]);
}
if ($accept_temporary_remain && !is_numeric($accept_temporary_remain)) {
$this->error=_("Invalid Expiration Period");
return false;
}
if ($quota && !is_numeric($quota) && !is_float($quota)) {
$this->error=_("Invalid Quota");
return false;
}
if (!$timezone && !$this->timezone) {
$this->error=_("Missing Timezone");
return false;
}
if (!$this->checkEmail($mailto)) {
$this->error=_("Invalid E-mail Address");
return false;
}
$rpid=preg_replace("/[^0-9\x]/","",$rpid);
if (preg_match("/^0+([1-9]\d*)$/",$rpid,$m)) $rpid=$m[1];
$quickdial=preg_replace("/[^0-9]/","",$quickdial);
if (!strlen($accept_temporary_group)) $accept_temporary_remain=0;
if (!$accept_temporary_remain) $accept_temporary_group="";
if (!$anonymous) $anonymous="0";
return true;
}
function RandomPassword($len=6) {
$alf=array("1","2","3","4","5","6","7","8","9");
$i=0;
while($i < $len) {
srand((double)microtime(true)*1000000);
$randval = rand(0,8);
$string="$string"."$alf[$randval]";
$i++;
}
return $string;
}
function cleanURI($uri) {
$uri=preg_replace("/.*sips?:([^;><=]+).*/", "\$1", $uri);
return urlencode($uri);
}
function showUpgradeTab () {
}
function PhoneDialURL($uri) {
$uri=$this->normalizeURI($uri);
if (!preg_match("/^sip:/",$uri)) {
$uri="sip:".$uri;
}
$uri_print="<a href=$uri>$this->call_img</a>";
return $uri_print;
}
function showChapter($chapter) {
print "
<div class=row-fluid><div class=span12><h4>";
print $chapter;
print "
</h4></div></div>
";
}
function normalizeURI($uri) {
$uri=quoted_printable_decode($uri);
$uri=preg_replace("/.*(sips?:[^;><=]+).*/", "\$1", $uri);
if (preg_match("/^(sips?:.*):/", $uri, $m)) $uri=$m[1];
if (preg_match("/^(.*sips?:0\d+)@(.*)(>?)$/",$uri,$m)) {
$uri=$m[1]."@".$this->domain.$m[3];
}
return $uri;
}
function htmlURI($uri) {
if (preg_match("/^sips?:00(\d+)@/",$uri,$m)) {
$uri="+".$m[1];
}
return htmlentities($uri);
}
function colorizeDate($call_date) {
list($date,$time)=explode(" ",$call_date);
if ($date== Date("Y-m-d",time())) {
$datePrint="<span class=\"label label-success\">".sprintf(_("Today"))."</span> ".$time;
} else if ($date== Date("Y-m-d",time()-3600*24)) {
$datePrint="<span class=\"label label-info\">".sprintf(_("Yesterday"))."</span> ".$time;
} else {
$datePrint=$call_date;
}
return $datePrint;
}
function checkEmail($email) {
dprint ("checkEmail($email)");
$regexp = "/^([a-z0-9][a-z0-9_.-]*)@([a-z0-9][a-z0-9-]*\.)+([a-z]{2,})$/i";
if (stristr($email,"-.") ||
!preg_match($regexp, $email)) {
return false;
}
return true;
}
function getFileTemplate($name, $type="file") {
dprint("getFileTemplate(name=$name, type=$type, path=$this->templates_path)");
if ($type=='logo') {
$extensions=array('png','gif','jpg');
foreach ($extensions as $_ext) {
$file=$this->templates_path.'/'.$this->reseller.'/'.$name.'.'.$_ext;
if (file_exists($file)) {
return $file;
}
}
foreach ($extensions as $_ext) {
if (file_exists("$this->templates_path/default/$name.$_ext")) {
return "$this->templates_path/default/$name.$_ext";
}
}
return false;
} else {
if (file_exists("$this->templates_path/$this->reseller/$name")) {
return "$this->templates_path/$this->reseller/$name";
} elseif (file_exists("$this->templates_path/default/$name")) {
return "$this->templates_path/default/$name";
} else {
return false;
}
}
}
function getEmailTemplate($reseller, $language='en') {
$file = "sip_settings_email_$language.tpl";
$file2 = "sip_settings_email.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getEmailTemplateHTML($reseller, $language='en') {
$file = "sip_settings_email_$language.html.tpl";
$file2 = "sip_settings_email.html.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getChangedEmailTemplate($reseller, $language='en') {
$file = "sip_settings_changed_$language.tpl";
$file2 = "sip_settings_changed.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getChangedEmailTemplateHTML($reseller, $language='en') {
$file = "sip_settings_changed_$language.html.tpl";
$file2 = "sip_settings_changed.html.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getEmailPasswordTemplateHTML($reseller, $language='en') {
$file = "password_reminder_$language.html.tpl";
$file2 = "password_reminder.html.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getEmailDeleteTemplateHTML($reseller, $language='en') {
$file = "delete_$language.html.tpl";
$file2 = "delete.html.tpl";
//print("templates_path = $this->templates_path");
if (file_exists("$this->templates_path/$this->reseller/$file")) {
return "$this->templates_path/$this->reseller/$file";
} elseif (file_exists("$this->templates_path/$this->reseller/$file2")) {
return "$this->templates_path/$this->reseller/$file2";
} elseif (file_exists("$this->templates_path/default/$file")) {
return "$this->templates_path/default/$file";
} elseif (file_exists("$this->templates_path/default/$file2")) {
return "$this->templates_path/default/$file2";
} else {
return false;
}
}
function getBillingProfiles() {
dprint("getBillingProfiles()");
// Get getBillingProfiles
$this->RatingPort->addHeader($this->SoapAuthRating);
$result = $this->RatingPort->getEntityProfiles("subscriber://".$this->account);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "4001") {
printf ("<p><font color=red>Error (Rating): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
$this->billingProfiles=$result;
}
function showBillingProfiles() {
if ($this->login_type != 'reseller' && $this->login_type != 'admin') {
return false;
}
if (!$this->pstn_changes_allowed) {
return false;
}
$this->getBillingProfiles();
$chapter=sprintf(_("Billing Profiles"));
$this->showChapter($chapter);
print "
<div class='control-group even'>
<label for=profileWeekday class=control-label>";
print _("Weekdays");
printf ("
</label>
<div class=controls>
<div class=input-append>
<input class=input-medium type=text size=10 maxsize=64 name=profileWeekday value='%s'><span class=add-on>/</span><input class=input-medium type=text size=10 maxsize=64 name=profileWeekdayAlt value='%s'>
",
$this->billingProfiles->profileWeekday,
$this->billingProfiles->profileWeekdayAlt
);
print "
</div>
</div>
</div>
";
print "
<div class='control-group odd'>
<label for=profileWeekend class=control-label>";
print _("Weekends");
printf ("
</label>
<div class=controls>
<div class=input-append>
<input class=input-medium type=text size=10 maxsize=64 name=profileWeekend value='%s'><span class=add-on>/</span><input class=input-medium type=text size=10 maxsize=64 name=profileWeekendAlt value='%s'>
",
$this->billingProfiles->profileWeekend,
$this->billingProfiles->profileWeekendAlt
);
print "
</div>
</div>
</div>
";
print "
<div class='control-group even'>
<label for=profileTimezone class=control-label>";
print _("Timezone");
print ("
</label>
<div class=controls>
");
if ($this->billingProfiles->timezone) {
$_timezone=$this->billingProfiles->timezone;
} else {
$_timezone=$this->resellerProperties['timezone'];
}
$this->showTimezones('profileTimezone',$_timezone);
print "
</div>
</div>
";
}
function updateBillingProfiles() {
if ($this->login_type != 'reseller' && $this->login_type != 'admin') {
return false;
}
if (!$this->pstn_changes_allowed) {
return true;
}
$this->RatingPort->addHeader($this->SoapAuthRating);
$result = $this->RatingPort->getEntityProfiles("subscriber://".$this->account);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "4001") {
printf ("<p><font color=red>Error (Rating): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
$this->billingProfiles=$result;
$profiles=array("entity" =>'subscriber://'.$this->account ,
"profileWeekday" => trim($_REQUEST['profileWeekday']),
"profileWeekdayAlt" => trim($_REQUEST['profileWeekdayAlt']),
"profileWeekend" => trim($_REQUEST['profileWeekend']),
"profileWeekendAlt" => trim($_REQUEST['profileWeekendAlt']),
"timezone" => trim($_REQUEST['profileTimezone'])
);
//print_r($profiles);
$this->RatingPort->addHeader($this->SoapAuthRating);
if ($this->billingProfiles->profileWeekday && !$profiles['profileWeekday']) {
// delete profile
$result = $this->RatingPort->deleteEntityProfiles('subscriber://'.$this->account);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "4001") {
printf ("<p><font color=red>Error (Rating): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
} else if ($profiles['profileWeekday']) {
// update profile
$result = $this->RatingPort->setEntityProfiles($profiles);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode != "4001") {
printf ("<p><font color=red>Error (Rating): %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
}
}
}
function getImageForUserAgent($agent) {
// array with mappings between User Agents and images
foreach ($this->userAgentImages as $agentRegexp => $image) {
if (preg_match("/$agentRegexp/i", $agent)) {
return $image;
}
}
return "unknown.png";
}
function showExtraGroups () {
if ($this->disable_extra_groups) return true;
$foundGroupInAvailableGroups=array();
foreach ($this->groups as $_grp) {
foreach (array_keys($this->availableGroups) as $a_grp) {
if ($_grp == $a_grp) $foundGroupInAvailableGroups[]=$_grp;
continue;
}
}
$extraGroups = array_unique(array_diff($this->groups,$foundGroupInAvailableGroups));
foreach ($extraGroups as $_eg) {
$extraGroups_text.=$_eg.' ';
}
if ($this->login_type == 'subscriber') {
printf ("<input type=hidden name=extra_groups value='%s'>",trim($extraGroups_text));
} else {
print "
<div class=control-group>
<label for=extra_groups class=control-label>";
print _("Extra Groups");
print "
</label>
<div class=controls>";
printf ("<input class=input-medium type=text size=30 name=extra_groups value='%s'>",trim($extraGroups_text));
print "
</div>
</div>
";
}
}
function generateCertificate() {
global $enrollment;
include("/etc/cdrtool/enrollment/config.ini");
if (!is_array($enrollment)) {
print _("Error: missing enrollment settings");
return false;
}
if (!$enrollment['ca_conf']) {
//print _("Error: missing enrollment ca_conf settings");
return false;
}
if (!$this->owner) {
return false;
}
if (!$enrollment['ca_crt']) {
//print _("Error: missing enrollment ca_crt settings");
return false;
}
if (!$enrollment['ca_key']) {
//print _("Error: missing enrollment ca_key settings");
return false;
}
$config = array(
'config' => $enrollment['ca_conf'],
'digest_alg' => 'md5',
'private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'encrypt_key' => false,
);
$dn = array(
"countryName" => "NL",
"stateOrProvinceName" => "Noord Holland",
"localityName" => "Haarlem",
"organizationName" => "AG Projects",
"organizationalUnitName" => "Blink",
"commonName" => $this->owner,
"emailAddress" => $this->email
);
$this->key = openssl_pkey_new($config);
if ($this->key==FALSE) {
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
print "<br><br>";
}
return false;
}
$this->csr = openssl_csr_new($dn, $this->key);
if (!$this->csr) {
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
print "<br><br>";
}
return false;
}
$ca="file://".$enrollment['ca_crt'];
$this->crt = openssl_csr_sign($this->csr, $ca, $enrollment['ca_key'], 3650, $config);
if ($this->crt==FALSE) {
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
print "<br><br>";
}
return false;
}
openssl_csr_export ($this->csr, $this->csr_out);
openssl_pkey_export ($this->key, $this->key_out, $this->password, $config);
openssl_x509_export ($this->crt, $this->crt_out);
openssl_pkcs12_export ($this->crt, $this->p12_out, $this->key, $this->password);
$ret=array( 'csr' => $this->csr_out,
'crt' => $this->crt_out,
'key' => $this->key_out,
'pkey'=> $public_key,
'p12' => $this->p12_out,
'ca' => file_get_contents($enrollment['ca_crt'])
);
return $ret;
}
function exportCertificateX509() {
if (!$this->owner) return;
Header("Content-type: application/x-crt");
$header=sprintf("Content-Disposition: inline; filename=sipthor-owner-certificate-%s.crt",$this->owner);
Header($header);
$cert=$this->generateCertificate();
$crt=$cert['crt'].$cert['key'];
print $crt;
}
function exportCertificateP12() {
if (!$this->owner) return;
$cert=$this->generateCertificate();
Header("Content-type: application/x-p12");
$header=sprintf("Content-Disposition: inline; filename=sipthor-owner-certificate-%s.p12",$this->owner);
Header($header);
print $cert['p12'];
}
function isEmbedded() {
// return true if page was loaded from non-session based web session
if ($_SERVER['SSL_CLIENT_CERT'] || $_SERVER['PHP_AUTH_DIGEST']) {
return true;
}
return false;
}
function changeLanguage($lang='en',$domain='cdrtool') {
// run dpkg-reconfigure locales and select support languages .utf8
$lang = $this->languageCodeFor(isset($lang) ? $lang : 'en');
$lang.='.utf8';
setlocale(LC_ALL, $lang);
bindtextdomain($domain, '/var/www/CDRTool/po/locale');
bind_textdomain_codeset($domain,'UTF-8');
textdomain($domain);
}
// return full language code for given 2 letter language code
function languageCodeFor($lang='en') {
$lang = isset($lang) ? strtolower($lang) : 'en';
switch ($lang) {
case 'en': return 'en_US'; // this can be C or en_US
case 'ja': return 'ja_JP';
default : return ($lang . '_' . strtoupper($lang));
}
return 'C'; // this will never be reached
}
function showDirectorySearchForm () {
if (in_array("trunking",$this->groups)) {
return false;
}
print "
<form class='form-inline' action=$this->url method=post>
<input type=hidden name=tab value='contacts'>
";
print $this->hiddenElements;
print "<div class=control-group>";
print "<input type=text size=20 name='firstname' placeholder='";
print _("First Name");
printf ("' value='%s'> ",$_REQUEST['firstname']);
print "<div class=input-append>";
print "<input type=text size=20 name='lastname' placeholder='";
print _("Last Name");
printf ("' value='%s'>",$_REQUEST['lastname']);
print "<button class=btn type=submit>";
print _("Search");
print "</button>";
print "</div></div>
</form>
";
}
function showSearchDirectory() {
if (!$this->show_directory) {
return false;
}
$this->maxrowsperpage=20;
$this->showDirectorySearchForm();
if ($_REQUEST['firstname'] || $_REQUEST['lastname']) {
if ($_REQUEST['firstname'] && strlen($_REQUEST['firstname']) < 3) {
return false;
}
if ($_REQUEST['lastname'] && strlen($_REQUEST['lastname']) < 3) {
return false;
}
} else {
return false;
}
$this->next = $_REQUEST['next'];
// Filter
$filter=array('firstName'=> trim($_REQUEST['firstname']),
'lastName' => trim($_REQUEST['lastname'])
);
// Range
$range=array('start' => intval($this->next),
'count' => intval($this->maxrowsperpage)
);
// Order
if (!$this->sorting['sortBy']) $this->sorting['sortBy'] = 'changeDate';
if (!$this->sorting['sortOrder']) $this->sorting['sortOrder'] = 'DESC';
$orderBy = array('attribute' => $this->sorting['sortBy'],
'direction' => $this->sorting['sortOrder']
);
// Compose query
$Query=array('filter' => $filter,
'orderBy' => $orderBy,
'range' => $range
);
// Insert credetials
$this->SipPort->addHeader($this->SoapAuthAdmin);
// Call function
$result = $this->SipPort->getAccounts($Query);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error from %s: %s (%s): %s</font>",$this->SoapEngine->SOAPurl,$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
$this->rows = $result->total;
if (!$this->next) $this->next=0;
if ($this->rows > $this->maxrowsperpage) {
$maxrows = $this->maxrowsperpage + $this->next;
if ($maxrows > $this->rows) $maxrows = $this->maxrowsperpage;
} else {
$maxrows=$this->rows;
}
if ($this->rows) {
print "
<div class=row-fluid>
<div class=span12 style='text-align:center'>";
printf(_("%s contacts found. "),$this->rows);
if ($this->isEmbedded()) {
//printf (_("Click on %s to add a Contact to Blink. "),$this->plus_sign_img);
}
print "</div>
</div>
<table class='table table-condensed table-striped' border=0 cellpadding=2 width=100%>
<thead>
<tr>
<td bgcolor=white></td>";
print "<th><b>";
print _('Display Name');
print "</b></th>";
print "<th><b>";
print _('SIP Address');
print "</b></th>";
print "<th><b>";
print _('Timezone');
print "</b></th>";
print "<th><b>";
print _('Action');
print "</b></th>";
print "
</tr></thead>
";
$i=0;
while ($i < $maxrows) {
if (!$result->accounts[$i]) break;
$account = $result->accounts[$i];
$index=$this->next+$i+1;
$rr=floor($index/2);
$mod=$index-$rr*2;
if ($mod ==0) {
$_class='odd';
} else {
$_class='even';
}
$i++;
$name=$account->firstName.' '.$account->lastName;
$sip_account=sprintf("%s@%s",$account->id->username,$account->id->domain);
$contacts_url=sprintf("<a href=%s&tab=contacts&task=add&uri=%s&name=%s&search_text=%s>%s</a>",$this->url,$sip_account,urlencode($name),$sip_account,$this->phonebook_img);
if ($this->isEmbedded()) {
//$add_contact_url=sprintf("<a href=\"javascript:blink.addContact_withDisplayName_('%s', '%s');\">%s</a>",$sip_account,$name,$this->plus_sign_img);
printf ("<tr class=%s><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s %s</td>",
$_class,
$index,
$name,
$sip_account,
$account->timezone,
$this->PhoneDialURL($sip_account),
$add_contact_url
);
} else {
printf ("<tr class=%s><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s %s</td>",
$_class,
$index,
$name,
$sip_account,
$account->timezone,
$this->PhoneDialURL($sip_account),
$contacts_url
);
}
}
print "</table>";
$this->showPagination($maxrows);
return true;
}
}
function showPagination($maxrows) {
$url = sprintf("%s&tab=%s&firstname=%s&lastname%s",
$this->url,
$this->tab,
urlencode($_REQUEST['firstname']),
urlencode($_REQUEST['lastname'])
);
print "
<p>
<table border=0 align=center>
<tr>
<td>
";
if ($this->next != 0 ) {
$show_next=$this->maxrowsperpage-$this->next;
if ($show_next < 0) {
$mod_show_next = $show_next-2*$show_next;
}
if (!$mod_show_next) $mod_show_next=0;
if ($mod_show_next/$this->maxrowsperpage >= 1) {
printf ("<a href='%s&next=0'>Begin</a> ",$url);
}
printf ("<a href='%s&next=%s'>Previous</a> ",$url,$mod_show_next);
}
print "
</td>
<td>
";
if ($this->next + $this->maxrowsperpage < $this->rows) {
$show_next = $this->maxrowsperpage + $this->next;
printf ("<a href='%s&next=%s'>Next</a> ",$url,$show_next);
}
print "
</td>
</tr>
</table>
";
}
}
function lookupGeoLocation($ip) {
if ($_loc=geoip_record_by_name($ip)) {
$_loc['timezone'] = get_time_zone($_loc['country_code'], $_loc['region']);
$_loc['region'] = get_region($_loc['country_code'], $_loc['region']);
$country_transition = array(
"A1" => "N/A",
"A2" => "N/A",
"O1" => "N/A",
"AP" => "N/A",
"GB" => "UK");
if (array_key_exists($_loc['country_code'],$country_transition)) {
$_loc['country_code'] = $country_transition[$_loc['country_code']];
}
return $_loc;
} else {
return array();
}
}
function get_region($country, $region) {
if ($country == "US" || $country =="CA" ) {
$full_region = $region;
// If region can't be found make it a default region to prevent NGNpro error
if ($full_region == '' && $country == "US") {
$full_region = "NY";
} else if ($full_region == '' && $country == "CA") {
$full_region = "QC";
}
} else {
$full_region='';
}
return $full_region;
}
function get_time_zone($country, $region) {
switch ($country) {
case "US":
switch ($region) {
case "AL":
$timezone = "America/Chicago";
break;
case "AK":
$timezone = "America/Anchorage";
break;
case "AZ":
$timezone = "America/Phoenix";
break;
case "AR":
$timezone = "America/Chicago";
break;
case "CA":
$timezone = "America/Los_Angeles";
break;
case "CO":
$timezone = "America/Denver";
break;
case "CT":
$timezone = "America/New_York";
break;
case "DE":
$timezone = "America/New_York";
break;
case "DC":
$timezone = "America/New_York";
break;
case "FL":
$timezone = "America/New_York";
break;
case "GA":
$timezone = "America/New_York";
break;
case "HI":
$timezone = "Pacific/Honolulu";
break;
case "ID":
$timezone = "America/Denver";
break;
case "IL":
$timezone = "America/Chicago";
break;
case "IN":
$timezone = "America/Indianapolis";
break;
case "IA":
$timezone = "America/Chicago";
break;
case "KS":
$timezone = "America/Chicago";
break;
case "KY":
$timezone = "America/New_York";
break;
case "LA":
$timezone = "America/Chicago";
break;
case "ME":
$timezone = "America/New_York";
break;
case "MD":
$timezone = "America/New_York";
break;
case "MA":
$timezone = "America/New_York";
break;
case "MI":
$timezone = "America/New_York";
break;
case "MN":
$timezone = "America/Chicago";
break;
case "MS":
$timezone = "America/Chicago";
break;
case "MO":
$timezone = "America/Chicago";
break;
case "MT":
$timezone = "America/Denver";
break;
case "NE":
$timezone = "America/Chicago";
break;
case "NV":
$timezone = "America/Los_Angeles";
break;
case "NH":
$timezone = "America/New_York";
break;
case "NJ":
$timezone = "America/New_York";
break;
case "NM":
$timezone = "America/Denver";
break;
case "NY":
$timezone = "America/New_York";
break;
case "NC":
$timezone = "America/New_York";
break;
case "ND":
$timezone = "America/Chicago";
break;
case "OH":
$timezone = "America/New_York";
break;
case "OK":
$timezone = "America/Chicago";
break;
case "OR":
$timezone = "America/Los_Angeles";
break;
case "PA":
$timezone = "America/New_York";
break;
case "RI":
$timezone = "America/New_York";
break;
case "SC":
$timezone = "America/New_York";
break;
case "SD":
$timezone = "America/Chicago";
break;
case "TN":
$timezone = "America/Chicago";
break;
case "TX":
$timezone = "America/Chicago";
break;
case "UT":
$timezone = "America/Denver";
break;
case "VT":
$timezone = "America/New_York";
break;
case "VA":
$timezone = "America/New_York";
break;
case "WA":
$timezone = "America/Los_Angeles";
break;
case "WV":
$timezone = "America/New_York";
break;
case "WI":
$timezone = "America/Chicago";
break;
case "WY":
$timezone = "America/Denver";
break;
}
break;
case "CA":
switch ($region) {
case "AB":
$timezone = "America/Edmonton";
break;
case "BC":
$timezone = "America/Vancouver";
break;
case "MB":
$timezone = "America/Winnipeg";
break;
case "NB":
$timezone = "America/Halifax";
break;
case "NL":
$timezone = "America/St_Johns";
break;
case "NT":
$timezone = "America/Yellowknife";
break;
case "NS":
$timezone = "America/Halifax";
break;
case "NU":
$timezone = "America/Rankin_Inlet";
break;
case "ON":
$timezone = "America/Rainy_River";
break;
case "PE":
$timezone = "America/Halifax";
break;
case "QC":
$timezone = "America/Montreal";
break;
case "SK":
$timezone = "America/Regina";
break;
case "YT":
$timezone = "America/Whitehorse";
break;
}
break;
case "AU":
switch ($region) {
case "01":
$timezone = "Australia/Canberra";
break;
case "02":
$timezone = "Australia/NSW";
break;
case "03":
$timezone = "Australia/North";
break;
case "04":
$timezone = "Australia/Queensland";
break;
case "05":
$timezone = "Australia/South";
break;
case "06":
$timezone = "Australia/Tasmania";
break;
case "07":
$timezone = "Australia/Victoria";
break;
case "08":
$timezone = "Australia/West";
break;
}
break;
case "AS":
$timezone = "US/Samoa";
break;
case "CI":
$timezone = "Africa/Abidjan";
break;
case "GH":
$timezone = "Africa/Accra";
break;
case "DZ":
$timezone = "Africa/Algiers";
break;
case "ER":
$timezone = "Africa/Asmera";
break;
case "ML":
$timezone = "Africa/Bamako";
break;
case "CF":
$timezone = "Africa/Bangui";
break;
case "GM":
$timezone = "Africa/Banjul";
break;
case "GW":
$timezone = "Africa/Bissau";
break;
case "CG":
$timezone = "Africa/Brazzaville";
break;
case "BI":
$timezone = "Africa/Bujumbura";
break;
case "EG":
$timezone = "Africa/Cairo";
break;
case "MA":
$timezone = "Africa/Casablanca";
break;
case "GN":
$timezone = "Africa/Conakry";
break;
case "SN":
$timezone = "Africa/Dakar";
break;
case "DJ":
$timezone = "Africa/Djibouti";
break;
case "SL":
$timezone = "Africa/Freetown";
break;
case "BW":
$timezone = "Africa/Gaborone";
break;
case "ZW":
$timezone = "Africa/Harare";
break;
case "ZA":
$timezone = "Africa/Johannesburg";
break;
case "UG":
$timezone = "Africa/Kampala";
break;
case "SD":
$timezone = "Africa/Khartoum";
break;
case "RW":
$timezone = "Africa/Kigali";
break;
case "NG":
$timezone = "Africa/Lagos";
break;
case "GA":
$timezone = "Africa/Libreville";
break;
case "TG":
$timezone = "Africa/Lome";
break;
case "AO":
$timezone = "Africa/Luanda";
break;
case "ZM":
$timezone = "Africa/Lusaka";
break;
case "GQ":
$timezone = "Africa/Malabo";
break;
case "MZ":
$timezone = "Africa/Maputo";
break;
case "LS":
$timezone = "Africa/Maseru";
break;
case "SZ":
$timezone = "Africa/Mbabane";
break;
case "SO":
$timezone = "Africa/Mogadishu";
break;
case "LR":
$timezone = "Africa/Monrovia";
break;
case "KE":
$timezone = "Africa/Nairobi";
break;
case "TD":
$timezone = "Africa/Ndjamena";
break;
case "NE":
$timezone = "Africa/Niamey";
break;
case "MR":
$timezone = "Africa/Nouakchott";
break;
case "BF":
$timezone = "Africa/Ouagadougou";
break;
case "ST":
$timezone = "Africa/Sao_Tome";
break;
case "LY":
$timezone = "Africa/Tripoli";
break;
case "TN":
$timezone = "Africa/Tunis";
break;
case "AI":
$timezone = "America/Anguilla";
break;
case "AG":
$timezone = "America/Antigua";
break;
case "AW":
$timezone = "America/Aruba";
break;
case "BB":
$timezone = "America/Barbados";
break;
case "BZ":
$timezone = "America/Belize";
break;
case "CO":
$timezone = "America/Bogota";
break;
case "VE":
$timezone = "America/Caracas";
break;
case "KY":
$timezone = "America/Cayman";
break;
case "CR":
$timezone = "America/Costa_Rica";
break;
case "DM":
$timezone = "America/Dominica";
break;
case "SV":
$timezone = "America/El_Salvador";
break;
case "GD":
$timezone = "America/Grenada";
break;
case "FR":
$timezone = "Europe/Paris";
break;
case "GP":
$timezone = "America/Guadeloupe";
break;
case "GT":
$timezone = "America/Guatemala";
break;
case "GY":
$timezone = "America/Guyana";
break;
case "CU":
$timezone = "America/Havana";
break;
case "JM":
$timezone = "America/Jamaica";
break;
case "BO":
$timezone = "America/La_Paz";
break;
case "PE":
$timezone = "America/Lima";
break;
case "NI":
$timezone = "America/Managua";
break;
case "MQ":
$timezone = "America/Martinique";
break;
case "UY":
$timezone = "America/Montevideo";
break;
case "MS":
$timezone = "America/Montserrat";
break;
case "BS":
$timezone = "America/Nassau";
break;
case "PA":
$timezone = "America/Panama";
break;
case "SR":
$timezone = "America/Paramaribo";
break;
case "PR":
$timezone = "America/Puerto_Rico";
break;
case "KN":
$timezone = "America/St_Kitts";
break;
case "LC":
$timezone = "America/St_Lucia";
break;
case "VC":
$timezone = "America/St_Vincent";
break;
case "HN":
$timezone = "America/Tegucigalpa";
break;
case "YE":
$timezone = "Asia/Aden";
break;
case "JO":
$timezone = "Asia/Amman";
break;
case "TM":
$timezone = "Asia/Ashgabat";
break;
case "IQ":
$timezone = "Asia/Baghdad";
break;
case "BH":
$timezone = "Asia/Bahrain";
break;
case "AZ":
$timezone = "Asia/Baku";
break;
case "TH":
$timezone = "Asia/Bangkok";
break;
case "LB":
$timezone = "Asia/Beirut";
break;
case "KG":
$timezone = "Asia/Bishkek";
break;
case "BN":
$timezone = "Asia/Brunei";
break;
case "IN":
$timezone = "Asia/Calcutta";
break;
case "MN":
$timezone = "Asia/Choibalsan";
break;
case "LK":
$timezone = "Asia/Colombo";
break;
case "BD":
$timezone = "Asia/Dhaka";
break;
case "AE":
$timezone = "Asia/Dubai";
break;
case "TJ":
$timezone = "Asia/Dushanbe";
break;
case "HK":
$timezone = "Asia/Hong_Kong";
break;
case "TR":
$timezone = "Asia/Istanbul";
break;
case "IL":
$timezone = "Asia/Jerusalem";
break;
case "AF":
$timezone = "Asia/Kabul";
break;
case "PK":
$timezone = "Asia/Karachi";
break;
case "NP":
$timezone = "Asia/Katmandu";
break;
case "KW":
$timezone = "Asia/Kuwait";
break;
case "MO":
$timezone = "Asia/Macao";
break;
case "PH":
$timezone = "Asia/Manila";
break;
case "OM":
$timezone = "Asia/Muscat";
break;
case "CY":
$timezone = "Asia/Nicosia";
break;
case "KP":
$timezone = "Asia/Pyongyang";
break;
case "QA":
$timezone = "Asia/Qatar";
break;
case "MM":
$timezone = "Asia/Rangoon";
break;
case "SA":
$timezone = "Asia/Riyadh";
break;
case "KR":
$timezone = "Asia/Seoul";
break;
case "SG":
$timezone = "Asia/Singapore";
break;
case "TW":
$timezone = "Asia/Taipei";
break;
case "GE":
$timezone = "Asia/Tbilisi";
break;
case "BT":
$timezone = "Asia/Thimphu";
break;
case "JP":
$timezone = "Asia/Tokyo";
break;
case "LA":
$timezone = "Asia/Vientiane";
break;
case "AM":
$timezone = "Asia/Yerevan";
break;
case "BM":
$timezone = "Atlantic/Bermuda";
break;
case "CV":
$timezone = "Atlantic/Cape_Verde";
break;
case "FO":
$timezone = "Atlantic/Faeroe";
break;
case "IS":
$timezone = "Atlantic/Reykjavik";
break;
case "GS":
$timezone = "Atlantic/South_Georgia";
break;
case "SH":
$timezone = "Atlantic/St_Helena";
break;
case "CL":
$timezone = "Chile/Continental";
break;
case "NL":
$timezone = "Europe/Amsterdam";
break;
case "AD":
$timezone = "Europe/Andorra";
break;
case "GR":
$timezone = "Europe/Athens";
break;
case "YU":
$timezone = "Europe/Belgrade";
break;
case "DE":
$timezone = "Europe/Berlin";
break;
case "SK":
$timezone = "Europe/Bratislava";
break;
case "BE":
$timezone = "Europe/Brussels";
break;
case "RO":
$timezone = "Europe/Bucharest";
break;
case "HU":
$timezone = "Europe/Budapest";
break;
case "DK":
$timezone = "Europe/Copenhagen";
break;
case "IE":
$timezone = "Europe/Dublin";
break;
case "GI":
$timezone = "Europe/Gibraltar";
break;
case "FI":
$timezone = "Europe/Helsinki";
break;
case "SI":
$timezone = "Europe/Ljubljana";
break;
case "GB":
$timezone = "Europe/London";
break;
case "LU":
$timezone = "Europe/Luxembourg";
break;
case "MT":
$timezone = "Europe/Malta";
break;
case "BY":
$timezone = "Europe/Minsk";
break;
case "MC":
$timezone = "Europe/Monaco";
break;
case "NO":
$timezone = "Europe/Oslo";
break;
case "CZ":
$timezone = "Europe/Prague";
break;
case "LV":
$timezone = "Europe/Riga";
break;
case "IT":
$timezone = "Europe/Rome";
break;
case "SM":
$timezone = "Europe/San_Marino";
break;
case "BA":
$timezone = "Europe/Sarajevo";
break;
case "MK":
$timezone = "Europe/Skopje";
break;
case "BG":
$timezone = "Europe/Sofia";
break;
case "SE":
$timezone = "Europe/Stockholm";
break;
case "EE":
$timezone = "Europe/Tallinn";
break;
case "AL":
$timezone = "Europe/Tirane";
break;
case "LI":
$timezone = "Europe/Vaduz";
break;
case "VA":
$timezone = "Europe/Vatican";
break;
case "AT":
$timezone = "Europe/Vienna";
break;
case "LT":
$timezone = "Europe/Vilnius";
break;
case "PL":
$timezone = "Europe/Warsaw";
break;
case "HR":
$timezone = "Europe/Zagreb";
break;
case "IR":
$timezone = "Asia/Tehran";
break;
case "MG":
$timezone = "Indian/Antananarivo";
break;
case "CX":
$timezone = "Indian/Christmas";
break;
case "CC":
$timezone = "Indian/Cocos";
break;
case "KM":
$timezone = "Indian/Comoro";
break;
case "MV":
$timezone = "Indian/Maldives";
break;
case "MU":
$timezone = "Indian/Mauritius";
break;
case "YT":
$timezone = "Indian/Mayotte";
break;
case "RE":
$timezone = "Indian/Reunion";
break;
case "FJ":
$timezone = "Pacific/Fiji";
break;
case "TV":
$timezone = "Pacific/Funafuti";
break;
case "GU":
$timezone = "Pacific/Guam";
break;
case "NR":
$timezone = "Pacific/Nauru";
break;
case "NU":
$timezone = "Pacific/Niue";
break;
case "NF":
$timezone = "Pacific/Norfolk";
break;
case "PW":
$timezone = "Pacific/Palau";
break;
case "PN":
$timezone = "Pacific/Pitcairn";
break;
case "CK":
$timezone = "Pacific/Rarotonga";
break;
case "WS":
$timezone = "Pacific/Samoa";
break;
case "KI":
$timezone = "Pacific/Tarawa";
break;
case "TO":
$timezone = "Pacific/Tongatapu";
break;
case "WF":
$timezone = "Pacific/Wallis";
break;
case "TZ":
$timezone = "Africa/Dar_es_Salaam";
break;
case "VN":
$timezone = "Asia/Phnom_Penh";
break;
case "KH":
$timezone = "Asia/Phnom_Penh";
break;
case "CM":
$timezone = "Africa/Lagos";
break;
case "DO":
$timezone = "America/Santo_Domingo";
break;
case "ET":
$timezone = "Africa/Addis_Ababa";
break;
case "FX":
$timezone = "Europe/Paris";
break;
case "HT":
$timezone = "America/Port-au-Prince";
break;
case "CH":
$timezone = "Europe/Zurich";
break;
case "AN":
$timezone = "America/Curacao";
break;
case "BJ":
$timezone = "Africa/Porto-Novo";
break;
case "EH":
$timezone = "Africa/El_Aaiun";
break;
case "FK":
$timezone = "Atlantic/Stanley";
break;
case "GF":
$timezone = "America/Cayenne";
break;
case "IO":
$timezone = "Indian/Chagos";
break;
case "MD":
$timezone = "Europe/Chisinau";
break;
case "MP":
$timezone = "Pacific/Saipan";
break;
case "MW":
$timezone = "Africa/Blantyre";
break;
case "NA":
$timezone = "Africa/Windhoek";
break;
case "NC":
$timezone = "Pacific/Noumea";
break;
case "PG":
$timezone = "Pacific/Port_Moresby";
break;
case "PM":
$timezone = "America/Miquelon";
break;
case "PS":
$timezone = "Asia/Gaza";
break;
case "PY":
$timezone = "America/Asuncion";
break;
case "SB":
$timezone = "Pacific/Guadalcanal";
break;
case "SC":
$timezone = "Indian/Mahe";
break;
case "SJ":
$timezone = "Arctic/Longyearbyen";
break;
case "SY":
$timezone = "Asia/Damascus";
break;
case "TC":
$timezone = "America/Grand_Turk";
break;
case "TF":
$timezone = "Indian/Kerguelen";
break;
case "TK":
$timezone = "Pacific/Fakaofo";
break;
case "TT":
$timezone = "America/Port_of_Spain";
break;
case "VG":
$timezone = "America/Tortola";
break;
case "VI":
$timezone = "America/St_Thomas";
break;
case "VU":
$timezone = "Pacific/Efate";
break;
case "RS":
$timezone = "Europe/Belgrade";
break;
case "ME":
$timezone = "Europe/Podgorica";
break;
case "AX":
$timezone = "Europe/Mariehamn";
break;
case "GG":
$timezone = "Europe/Guernsey";
break;
case "IM":
$timezone = "Europe/Isle_of_Man";
break;
case "JE":
$timezone = "Europe/Jersey";
break;
case "BL":
$timezone = "America/St_Barthelemy";
break;
case "MF":
$timezone = "America/Marigot";
break;
case "AR":
switch ($region) {
case "01":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "02":
$timezone = "America/Argentina/Catamarca";
break;
case "03":
$timezone = "America/Argentina/Tucuman";
break;
case "04":
$timezone = "America/Argentina/Rio_Gallegos";
break;
case "05":
$timezone = "America/Argentina/Cordoba";
break;
case "06":
$timezone = "America/Argentina/Tucuman";
break;
case "07":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "08":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "09":
$timezone = "America/Argentina/Tucuman";
break;
case "10":
$timezone = "America/Argentina/Jujuy";
break;
case "11":
$timezone = "America/Argentina/San_Luis";
break;
case "12":
$timezone = "America/Argentina/La_Rioja";
break;
case "13":
$timezone = "America/Argentina/Mendoza";
break;
case "14":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "15":
$timezone = "America/Argentina/San_Luis";
break;
case "16":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "17":
$timezone = "America/Argentina/Salta";
break;
case "18":
$timezone = "America/Argentina/San_Juan";
break;
case "19":
$timezone = "America/Argentina/San_Luis";
break;
case "20":
$timezone = "America/Argentina/Rio_Gallegos";
break;
case "21":
$timezone = "America/Argentina/Buenos_Aires";
break;
case "22":
$timezone = "America/Argentina/Catamarca";
break;
case "23":
$timezone = "America/Argentina/Ushuaia";
break;
case "24":
$timezone = "America/Argentina/Tucuman";
break;
}
break;
case "BR":
switch ($region) {
case "01":
$timezone = "America/Rio_Branco";
break;
case "02":
$timezone = "America/Maceio";
break;
case "03":
$timezone = "America/Sao_Paulo";
break;
case "04":
$timezone = "America/Manaus";
break;
case "05":
$timezone = "America/Bahia";
break;
case "06":
$timezone = "America/Fortaleza";
break;
case "07":
$timezone = "America/Sao_Paulo";
break;
case "08":
$timezone = "America/Sao_Paulo";
break;
case "11":
$timezone = "America/Campo_Grande";
break;
case "13":
$timezone = "America/Belem";
break;
case "14":
$timezone = "America/Cuiaba";
break;
case "15":
$timezone = "America/Sao_Paulo";
break;
case "16":
$timezone = "America/Belem";
break;
case "17":
$timezone = "America/Recife";
break;
case "18":
$timezone = "America/Sao_Paulo";
break;
case "20":
$timezone = "America/Fortaleza";
break;
case "21":
$timezone = "America/Sao_Paulo";
break;
case "22":
$timezone = "America/Recife";
break;
case "23":
$timezone = "America/Sao_Paulo";
break;
case "24":
$timezone = "America/Porto_Velho";
break;
case "25":
$timezone = "America/Boa_Vista";
break;
case "26":
$timezone = "America/Sao_Paulo";
break;
case "27":
$timezone = "America/Sao_Paulo";
break;
case "28":
$timezone = "America/Maceio";
break;
case "29":
$timezone = "America/Sao_Paulo";
break;
case "30":
$timezone = "America/Recife";
break;
case "31":
$timezone = "America/Araguaina";
break;
}
break;
case "CD":
switch ($region) {
case "02":
$timezone = "Africa/Kinshasa";
break;
case "05":
$timezone = "Africa/Lubumbashi";
break;
case "06":
$timezone = "Africa/Kinshasa";
break;
case "08":
$timezone = "Africa/Kinshasa";
break;
case "10":
$timezone = "Africa/Lubumbashi";
break;
case "11":
$timezone = "Africa/Lubumbashi";
break;
case "12":
$timezone = "Africa/Lubumbashi";
break;
}
break;
case "CN":
switch ($region) {
case "01":
$timezone = "Asia/Shanghai";
break;
case "02":
$timezone = "Asia/Shanghai";
break;
case "03":
$timezone = "Asia/Shanghai";
break;
case "04":
$timezone = "Asia/Shanghai";
break;
case "05":
$timezone = "Asia/Harbin";
break;
case "06":
$timezone = "Asia/Chongqing";
break;
case "07":
$timezone = "Asia/Shanghai";
break;
case "08":
$timezone = "Asia/Harbin";
break;
case "09":
$timezone = "Asia/Shanghai";
break;
case "10":
$timezone = "Asia/Shanghai";
break;
case "11":
$timezone = "Asia/Chongqing";
break;
case "12":
$timezone = "Asia/Shanghai";
break;
case "13":
$timezone = "Asia/Urumqi";
break;
case "14":
$timezone = "Asia/Chongqing";
break;
case "15":
$timezone = "Asia/Chongqing";
break;
case "16":
$timezone = "Asia/Chongqing";
break;
case "18":
$timezone = "Asia/Chongqing";
break;
case "19":
$timezone = "Asia/Harbin";
break;
case "20":
$timezone = "Asia/Harbin";
break;
case "21":
$timezone = "Asia/Chongqing";
break;
case "22":
$timezone = "Asia/Harbin";
break;
case "23":
$timezone = "Asia/Shanghai";
break;
case "24":
$timezone = "Asia/Chongqing";
break;
case "25":
$timezone = "Asia/Shanghai";
break;
case "26":
$timezone = "Asia/Chongqing";
break;
case "28":
$timezone = "Asia/Shanghai";
break;
case "29":
$timezone = "Asia/Chongqing";
break;
case "30":
$timezone = "Asia/Chongqing";
break;
case "31":
$timezone = "Asia/Chongqing";
break;
case "32":
$timezone = "Asia/Chongqing";
break;
case "33":
$timezone = "Asia/Chongqing";
break;
}
break;
case "EC":
switch ($region) {
case "01":
$timezone = "Pacific/Galapagos";
break;
case "02":
$timezone = "America/Guayaquil";
break;
case "03":
$timezone = "America/Guayaquil";
break;
case "04":
$timezone = "America/Guayaquil";
break;
case "05":
$timezone = "America/Guayaquil";
break;
case "06":
$timezone = "America/Guayaquil";
break;
case "07":
$timezone = "America/Guayaquil";
break;
case "08":
$timezone = "America/Guayaquil";
break;
case "09":
$timezone = "America/Guayaquil";
break;
case "10":
$timezone = "America/Guayaquil";
break;
case "11":
$timezone = "America/Guayaquil";
break;
case "12":
$timezone = "America/Guayaquil";
break;
case "13":
$timezone = "America/Guayaquil";
break;
case "14":
$timezone = "America/Guayaquil";
break;
case "15":
$timezone = "America/Guayaquil";
break;
case "17":
$timezone = "America/Guayaquil";
break;
case "18":
$timezone = "America/Guayaquil";
break;
case "19":
$timezone = "America/Guayaquil";
break;
case "20":
$timezone = "America/Guayaquil";
break;
case "22":
$timezone = "America/Guayaquil";
break;
}
break;
case "ES":
switch ($region) {
case "07":
$timezone = "Europe/Madrid";
break;
case "27":
$timezone = "Europe/Madrid";
break;
case "29":
$timezone = "Europe/Madrid";
break;
case "31":
$timezone = "Europe/Madrid";
break;
case "32":
$timezone = "Europe/Madrid";
break;
case "34":
$timezone = "Europe/Madrid";
break;
case "39":
$timezone = "Europe/Madrid";
break;
case "51":
$timezone = "Africa/Ceuta";
break;
case "52":
$timezone = "Europe/Madrid";
break;
case "53":
$timezone = "Atlantic/Canary";
break;
case "54":
$timezone = "Europe/Madrid";
break;
case "55":
$timezone = "Europe/Madrid";
break;
case "56":
$timezone = "Europe/Madrid";
break;
case "57":
$timezone = "Europe/Madrid";
break;
case "58":
$timezone = "Europe/Madrid";
break;
case "59":
$timezone = "Europe/Madrid";
break;
case "60":
$timezone = "Europe/Madrid";
break;
}
break;
case "GL":
switch ($region) {
case "01":
$timezone = "America/Thule";
break;
case "02":
$timezone = "America/Godthab";
break;
case "03":
$timezone = "America/Godthab";
break;
}
break;
case "ID":
switch ($region) {
case "01":
$timezone = "Asia/Pontianak";
break;
case "02":
$timezone = "Asia/Makassar";
break;
case "03":
$timezone = "Asia/Jakarta";
break;
case "04":
$timezone = "Asia/Jakarta";
break;
case "05":
$timezone = "Asia/Jakarta";
break;
case "06":
$timezone = "Asia/Jakarta";
break;
case "07":
$timezone = "Asia/Jakarta";
break;
case "08":
$timezone = "Asia/Jakarta";
break;
case "09":
$timezone = "Asia/Jayapura";
break;
case "10":
$timezone = "Asia/Jakarta";
break;
case "11":
$timezone = "Asia/Pontianak";
break;
case "12":
$timezone = "Asia/Makassar";
break;
case "13":
$timezone = "Asia/Makassar";
break;
case "14":
$timezone = "Asia/Makassar";
break;
case "15":
$timezone = "Asia/Jakarta";
break;
case "16":
$timezone = "Asia/Makassar";
break;
case "17":
$timezone = "Asia/Makassar";
break;
case "18":
$timezone = "Asia/Makassar";
break;
case "19":
$timezone = "Asia/Pontianak";
break;
case "20":
$timezone = "Asia/Makassar";
break;
case "21":
$timezone = "Asia/Makassar";
break;
case "22":
$timezone = "Asia/Makassar";
break;
case "23":
$timezone = "Asia/Makassar";
break;
case "24":
$timezone = "Asia/Jakarta";
break;
case "25":
$timezone = "Asia/Pontianak";
break;
case "26":
$timezone = "Asia/Pontianak";
break;
case "30":
$timezone = "Asia/Jakarta";
break;
case "31":
$timezone = "Asia/Makassar";
break;
case "33":
$timezone = "Asia/Jakarta";
break;
}
break;
case "KZ":
switch ($region) {
case "01":
$timezone = "Asia/Almaty";
break;
case "02":
$timezone = "Asia/Almaty";
break;
case "03":
$timezone = "Asia/Qyzylorda";
break;
case "04":
$timezone = "Asia/Aqtobe";
break;
case "05":
$timezone = "Asia/Qyzylorda";
break;
case "06":
$timezone = "Asia/Aqtau";
break;
case "07":
$timezone = "Asia/Oral";
break;
case "08":
$timezone = "Asia/Qyzylorda";
break;
case "09":
$timezone = "Asia/Aqtau";
break;
case "10":
$timezone = "Asia/Qyzylorda";
break;
case "11":
$timezone = "Asia/Almaty";
break;
case "12":
$timezone = "Asia/Qyzylorda";
break;
case "13":
$timezone = "Asia/Aqtobe";
break;
case "14":
$timezone = "Asia/Qyzylorda";
break;
case "15":
$timezone = "Asia/Almaty";
break;
case "16":
$timezone = "Asia/Aqtobe";
break;
case "17":
$timezone = "Asia/Almaty";
break;
}
break;
case "MX":
switch ($region) {
case "01":
$timezone = "America/Mexico_City";
break;
case "02":
$timezone = "America/Tijuana";
break;
case "03":
$timezone = "America/Hermosillo";
break;
case "04":
$timezone = "America/Merida";
break;
case "05":
$timezone = "America/Mexico_City";
break;
case "06":
$timezone = "America/Chihuahua";
break;
case "07":
$timezone = "America/Monterrey";
break;
case "08":
$timezone = "America/Mexico_City";
break;
case "09":
$timezone = "America/Mexico_City";
break;
case "10":
$timezone = "America/Mazatlan";
break;
case "11":
$timezone = "America/Mexico_City";
break;
case "12":
$timezone = "America/Mexico_City";
break;
case "13":
$timezone = "America/Mexico_City";
break;
case "14":
$timezone = "America/Mazatlan";
break;
case "15":
$timezone = "America/Chihuahua";
break;
case "16":
$timezone = "America/Mexico_City";
break;
case "17":
$timezone = "America/Mexico_City";
break;
case "18":
$timezone = "America/Mazatlan";
break;
case "19":
$timezone = "America/Monterrey";
break;
case "20":
$timezone = "America/Mexico_City";
break;
case "21":
$timezone = "America/Mexico_City";
break;
case "22":
$timezone = "America/Mexico_City";
break;
case "23":
$timezone = "America/Cancun";
break;
case "24":
$timezone = "America/Mexico_City";
break;
case "25":
$timezone = "America/Mazatlan";
break;
case "26":
$timezone = "America/Hermosillo";
break;
case "27":
$timezone = "America/Merida";
break;
case "28":
$timezone = "America/Monterrey";
break;
case "29":
$timezone = "America/Mexico_City";
break;
case "30":
$timezone = "America/Mexico_City";
break;
case "31":
$timezone = "America/Merida";
break;
case "32":
$timezone = "America/Monterrey";
break;
}
break;
case "MY":
switch ($region) {
case "01":
$timezone = "Asia/Kuala_Lumpur";
break;
case "02":
$timezone = "Asia/Kuala_Lumpur";
break;
case "03":
$timezone = "Asia/Kuala_Lumpur";
break;
case "04":
$timezone = "Asia/Kuala_Lumpur";
break;
case "05":
$timezone = "Asia/Kuala_Lumpur";
break;
case "06":
$timezone = "Asia/Kuala_Lumpur";
break;
case "07":
$timezone = "Asia/Kuala_Lumpur";
break;
case "08":
$timezone = "Asia/Kuala_Lumpur";
break;
case "09":
$timezone = "Asia/Kuala_Lumpur";
break;
case "11":
$timezone = "Asia/Kuching";
break;
case "12":
$timezone = "Asia/Kuala_Lumpur";
break;
case "13":
$timezone = "Asia/Kuala_Lumpur";
break;
case "14":
$timezone = "Asia/Kuala_Lumpur";
break;
case "15":
$timezone = "Asia/Kuching";
break;
case "16":
$timezone = "Asia/Kuching";
break;
}
break;
case "NZ":
switch ($region) {
case "85":
$timezone = "Pacific/Auckland";
break;
case "E7":
$timezone = "Pacific/Auckland";
break;
case "E8":
$timezone = "Pacific/Auckland";
break;
case "E9":
$timezone = "Pacific/Auckland";
break;
case "F1":
$timezone = "Pacific/Auckland";
break;
case "F2":
$timezone = "Pacific/Auckland";
break;
case "F3":
$timezone = "Pacific/Auckland";
break;
case "F4":
$timezone = "Pacific/Auckland";
break;
case "F5":
$timezone = "Pacific/Auckland";
break;
case "F7":
$timezone = "Pacific/Chatham";
break;
case "F8":
$timezone = "Pacific/Auckland";
break;
case "F9":
$timezone = "Pacific/Auckland";
break;
case "G1":
$timezone = "Pacific/Auckland";
break;
case "G2":
$timezone = "Pacific/Auckland";
break;
case "G3":
$timezone = "Pacific/Auckland";
break;
}
break;
case "PT":
switch ($region) {
case "02":
$timezone = "Europe/Lisbon";
break;
case "03":
$timezone = "Europe/Lisbon";
break;
case "04":
$timezone = "Europe/Lisbon";
break;
case "05":
$timezone = "Europe/Lisbon";
break;
case "06":
$timezone = "Europe/Lisbon";
break;
case "07":
$timezone = "Europe/Lisbon";
break;
case "08":
$timezone = "Europe/Lisbon";
break;
case "09":
$timezone = "Europe/Lisbon";
break;
case "10":
$timezone = "Atlantic/Madeira";
break;
case "11":
$timezone = "Europe/Lisbon";
break;
case "13":
$timezone = "Europe/Lisbon";
break;
case "14":
$timezone = "Europe/Lisbon";
break;
case "16":
$timezone = "Europe/Lisbon";
break;
case "17":
$timezone = "Europe/Lisbon";
break;
case "18":
$timezone = "Europe/Lisbon";
break;
case "19":
$timezone = "Europe/Lisbon";
break;
case "20":
$timezone = "Europe/Lisbon";
break;
case "21":
$timezone = "Europe/Lisbon";
break;
case "22":
$timezone = "Europe/Lisbon";
break;
}
break;
case "RU":
switch ($region) {
case "01":
$timezone = "Europe/Volgograd";
break;
case "02":
$timezone = "Asia/Irkutsk";
break;
case "03":
$timezone = "Asia/Novokuznetsk";
break;
case "04":
$timezone = "Asia/Novosibirsk";
break;
case "05":
$timezone = "Asia/Vladivostok";
break;
case "06":
$timezone = "Europe/Moscow";
break;
case "07":
$timezone = "Europe/Volgograd";
break;
case "08":
$timezone = "Europe/Samara";
break;
case "09":
$timezone = "Europe/Moscow";
break;
case "10":
$timezone = "Europe/Moscow";
break;
case "11":
$timezone = "Asia/Irkutsk";
break;
case "13":
$timezone = "Asia/Yekaterinburg";
break;
case "14":
$timezone = "Asia/Irkutsk";
break;
case "15":
$timezone = "Asia/Anadyr";
break;
case "16":
$timezone = "Europe/Samara";
break;
case "17":
$timezone = "Europe/Volgograd";
break;
case "18":
$timezone = "Asia/Krasnoyarsk";
break;
case "20":
$timezone = "Asia/Irkutsk";
break;
case "21":
$timezone = "Europe/Moscow";
break;
case "22":
$timezone = "Europe/Volgograd";
break;
case "23":
$timezone = "Europe/Kaliningrad";
break;
case "24":
$timezone = "Europe/Volgograd";
break;
case "25":
$timezone = "Europe/Moscow";
break;
case "26":
$timezone = "Asia/Kamchatka";
break;
case "27":
$timezone = "Europe/Volgograd";
break;
case "28":
$timezone = "Europe/Moscow";
break;
case "29":
$timezone = "Asia/Novokuznetsk";
break;
case "30":
$timezone = "Asia/Vladivostok";
break;
case "31":
$timezone = "Asia/Krasnoyarsk";
break;
case "32":
$timezone = "Asia/Omsk";
break;
case "33":
$timezone = "Asia/Yekaterinburg";
break;
case "34":
$timezone = "Asia/Yekaterinburg";
break;
case "35":
$timezone = "Asia/Yekaterinburg";
break;
case "36":
$timezone = "Asia/Anadyr";
break;
case "37":
$timezone = "Europe/Moscow";
break;
case "38":
$timezone = "Europe/Volgograd";
break;
case "39":
$timezone = "Asia/Krasnoyarsk";
break;
case "40":
$timezone = "Asia/Yekaterinburg";
break;
case "41":
$timezone = "Europe/Moscow";
break;
case "42":
$timezone = "Europe/Moscow";
break;
case "43":
$timezone = "Europe/Moscow";
break;
case "44":
$timezone = "Asia/Magadan";
break;
case "45":
$timezone = "Europe/Samara";
break;
case "46":
$timezone = "Europe/Samara";
break;
case "47":
$timezone = "Europe/Moscow";
break;
case "48":
$timezone = "Europe/Moscow";
break;
case "49":
$timezone = "Europe/Moscow";
break;
case "50":
$timezone = "Asia/Yekaterinburg";
break;
case "51":
$timezone = "Europe/Moscow";
break;
case "52":
$timezone = "Europe/Moscow";
break;
case "53":
$timezone = "Asia/Novosibirsk";
break;
case "54":
$timezone = "Asia/Omsk";
break;
case "55":
$timezone = "Europe/Samara";
break;
case "56":
$timezone = "Europe/Moscow";
break;
case "57":
$timezone = "Europe/Samara";
break;
case "58":
$timezone = "Asia/Yekaterinburg";
break;
case "59":
$timezone = "Asia/Vladivostok";
break;
case "60":
$timezone = "Europe/Kaliningrad";
break;
case "61":
$timezone = "Europe/Volgograd";
break;
case "62":
$timezone = "Europe/Moscow";
break;
case "63":
$timezone = "Asia/Yakutsk";
break;
case "64":
$timezone = "Asia/Sakhalin";
break;
case "65":
$timezone = "Europe/Samara";
break;
case "66":
$timezone = "Europe/Moscow";
break;
case "67":
$timezone = "Europe/Samara";
break;
case "68":
$timezone = "Europe/Volgograd";
break;
case "69":
$timezone = "Europe/Moscow";
break;
case "70":
$timezone = "Europe/Volgograd";
break;
case "71":
$timezone = "Asia/Yekaterinburg";
break;
case "72":
$timezone = "Europe/Moscow";
break;
case "73":
$timezone = "Europe/Samara";
break;
case "74":
$timezone = "Asia/Krasnoyarsk";
break;
case "75":
$timezone = "Asia/Novosibirsk";
break;
case "76":
$timezone = "Europe/Moscow";
break;
case "77":
$timezone = "Europe/Moscow";
break;
case "78":
$timezone = "Asia/Yekaterinburg";
break;
case "79":
$timezone = "Asia/Irkutsk";
break;
case "80":
$timezone = "Asia/Yekaterinburg";
break;
case "81":
$timezone = "Europe/Samara";
break;
case "82":
$timezone = "Asia/Irkutsk";
break;
case "83":
$timezone = "Europe/Moscow";
break;
case "84":
$timezone = "Europe/Volgograd";
break;
case "85":
$timezone = "Europe/Moscow";
break;
case "86":
$timezone = "Europe/Moscow";
break;
case "87":
$timezone = "Asia/Novosibirsk";
break;
case "88":
$timezone = "Europe/Moscow";
break;
case "89":
$timezone = "Asia/Vladivostok";
break;
}
break;
case "UA":
switch ($region) {
case "01":
$timezone = "Europe/Kiev";
break;
case "02":
$timezone = "Europe/Kiev";
break;
case "03":
$timezone = "Europe/Uzhgorod";
break;
case "04":
$timezone = "Europe/Zaporozhye";
break;
case "05":
$timezone = "Europe/Zaporozhye";
break;
case "06":
$timezone = "Europe/Uzhgorod";
break;
case "07":
$timezone = "Europe/Zaporozhye";
break;
case "08":
$timezone = "Europe/Simferopol";
break;
case "09":
$timezone = "Europe/Kiev";
break;
case "10":
$timezone = "Europe/Zaporozhye";
break;
case "11":
$timezone = "Europe/Simferopol";
break;
case "13":
$timezone = "Europe/Kiev";
break;
case "14":
$timezone = "Europe/Zaporozhye";
break;
case "15":
$timezone = "Europe/Uzhgorod";
break;
case "16":
$timezone = "Europe/Zaporozhye";
break;
case "17":
$timezone = "Europe/Simferopol";
break;
case "18":
$timezone = "Europe/Zaporozhye";
break;
case "19":
$timezone = "Europe/Kiev";
break;
case "20":
$timezone = "Europe/Simferopol";
break;
case "21":
$timezone = "Europe/Kiev";
break;
case "22":
$timezone = "Europe/Uzhgorod";
break;
case "23":
$timezone = "Europe/Kiev";
break;
case "24":
$timezone = "Europe/Uzhgorod";
break;
case "25":
$timezone = "Europe/Uzhgorod";
break;
case "26":
$timezone = "Europe/Zaporozhye";
break;
case "27":
$timezone = "Europe/Kiev";
break;
}
break;
case "UZ":
switch ($region) {
case "01":
$timezone = "Asia/Tashkent";
break;
case "02":
$timezone = "Asia/Samarkand";
break;
case "03":
$timezone = "Asia/Tashkent";
break;
case "06":
$timezone = "Asia/Tashkent";
break;
case "07":
$timezone = "Asia/Samarkand";
break;
case "08":
$timezone = "Asia/Samarkand";
break;
case "09":
$timezone = "Asia/Samarkand";
break;
case "10":
$timezone = "Asia/Samarkand";
break;
case "12":
$timezone = "Asia/Samarkand";
break;
case "13":
$timezone = "Asia/Tashkent";
break;
case "14":
$timezone = "Asia/Tashkent";
break;
}
break;
case "TL":
$timezone = "Asia/Dili";
break;
case "PF":
$timezone = "Pacific/Marquesas";
break;
}
return $timezone;
}
function normalizeURI($uri) {
$uri=quoted_printable_decode($uri);
if (preg_match("/^(.*<sips?:.*)@(.*>)/",$uri,$m)) {
if (preg_match("/^(.*):/U",$m[2],$p)){
$uri=$m[1]."@".$p[1].">";
} else {
$uri=$m[1]."@".$m[2];
}
} else if (preg_match("/^(sips?:.*)[=:;]/U",$uri,$p)) {
$uri=$p[1];
}
return $uri;
}
function normalizeTime($period) {
$sec=$period%60;
$min=floor($period/60);
$h=floor($min/60);
if (!$period) return ;
if ($h>0) {
$min=$min-60*$h;
}
if ($h >= 1) {
return sprintf('%dh%02d\'%02d"', $h, $min, $sec);
} else {
return sprintf('%d\'%02d"', $min, $sec);
}
}
function checkURI($uri) {
//dprint ("<b>checkURI($uri) </b>");
if ($uri == "<voice-mailbox>") return true;
if (preg_match("/^(sip:|sips:)(.*)$/",$uri,$m)) $uri=$m[2];
$regexp = "/^(\+?[a-z0-9*][a-z0-9_.*-]*)@([a-z0-9][a-z0-9-]*\.)+(([a-z]{2,})|(\d+))$/i";
if (stristr($uri,"-.") ||
!preg_match($regexp, $uri)) {
print "Invalid URI \"$uri\". ";
return false;
}
return true;
}
function checkPhonebookURI($uri) {
$regexp = "/^sip:([a-z0-9%_.-]*)@([a-z0-9%.-]*)$/i";
if (stristr($contact,"-.") || !preg_match($regexp, $uri)) {
print "Invalid URI \"$uri\". ";
return false;
}
return true;
}
function getLocalTime($timezone, $timestamp) {
$tz = getenv('TZ');
putenv("TZ=$timezone");
if (!$timestamp) {
return;
}
$LocalTime = date("Y-m-d H:i:s", $timestamp);
putenv("TZ=$tz");
return $LocalTime;
}
function getSipThorHomeNode ($account,$sip_proxy) {
if (!$account || !$sip_proxy) return false;
$socket = fsockopen($sip_proxy, 9500, $errno, $errstr, 1);
if (!$socket) {
return false;
}
$request=sprintf("lookup sip_proxy for %s",$account);
if (fputs($socket,"$request\r\n") !== false) {
$ret = fgets($socket,4096);
}
fclose($socket);
return $ret;
}
function getSipAccountFromX509Certificate($account='') {
if (!$account) {
print _('Error, please specify an account');
return false;
}
list($username, $domain) = explode("@",$account);
if (!$username || !$domain) {
print _("Invalid account provided");
return false;
}
if (!$_SERVER[SSL_CLIENT_CERT]) {
print _("Error: No X.509 client certificate provided\n");
return false;
}
if (!$cert=openssl_x509_parse($_SERVER[SSL_CLIENT_CERT])) {
print _("Error: Failed to parse X.509 client certificate\n");
return false;
}
require("/etc/cdrtool/ngnpro_engines.inc");
global $domainFilters, $resellerFilters, $soapEngines;
if ($domainFilters[$domain]['sip_engine']) {
$credentials['engine'] = $domainFilters[$domain]['sip_engine'];
$credentials['customer'] = $domainFilters[$domain]['customer'];
$credentials['reseller'] = $domainFilters[$domain]['reseller'];
} else if ($domainFilters['default']['sip_engine']) {
$credentials['engine']=$domainFilters['default']['sip_engine'];
} else {
print "Error: no domainFilter available in ngnpro_engines.inc";
return false;
}
$SOAPlogin=array(
"username" => $soapEngines[$credentials['engine']]['username'],
"password" => $soapEngines[$credentials['engine']]['password'],
"admin" => true
);
$SoapAuth = array('auth', $SOAPlogin , 'urn:AGProjects:NGNPro', 0, '');
$SipPort = new WebService_NGNPro_SipPort($soapEngines[$credentials['engine']]['url']);
$SipPort->_options['timeout'] = 5;
$SipPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$SipPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
$SipPort->addHeader($SoapAuth);
// Filter
$filter=array('username' => $username,
'domain' => $domain,
'owner' => intval($cert['subject']['CN'])
);
// Range
$range=array('start' => 0,
'count' => 10
);
$orderBy = array('attribute' => 'changeDate',
'direction' => 'DESC'
);
// Compose query
$Query=array('filter' => $filter,
'orderBy' => $orderBy,
'range' => $range
);
// Call function
$result = $SipPort->getAccounts($Query);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error from %s (SipPort): %s (%s): %s</font>",$soapEngines[$credentials['engine']]['url'],$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
}
if ($result->total != 1) {
return false;
}
$credentials['account'] = $account;
$credentials['customer'] = $result->customer;
$credentials['reseller'] = $result->reseller;
return $credentials;
}
function getSipAccountFromHTTPDigest () {
require("/etc/cdrtool/enrollment/config.ini");
if (!is_array($enrollment) || !strlen($enrollment['nonce_key'])) {
$log= 'Error: Missing nonce in enrollment settings';
syslog(LOG_NOTICE, $log);
die($log);
return false;
}
if ($_REQUEST['realm']) {
// required by Blink cocoa
$realm=$_REQUEST['realm'];
$a=explode("@",$realm);
if (count($a) == 2) {
$realm = $a[1];
}
} else {
$realm = 'SIP_settings';
}
// security implemented based on
// http://static.springsource.org/spring-security/site/docs/2.0.x/reference/digest.html
$_id = microtime(true)+ 300; // expires 5 minutes in the future
$_key = $enrollment['nonce_key'];
$nonce = base64_encode($_id.":".md5($_id.":".$_key));
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$nonce.'",opaque="'.md5($realm).'"');
//syslog(LOG_NOTICE, sprintf ("SIP settings page: sent auth request for realm %s to %s", $realm, $_SERVER['REMOTE_ADDR']));
die();
}
// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($data['username'])) {
$log=sprintf("SIP settings page: Invalid credentials from %s", $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die($log);
}
// generate the valid response
$username = $data['username'];
if (strstr($username, '@')) {
$a = explode("@",$username);
$username = $a[0];
$domain = $a[1];
} else {
$domain = $realm;
}
require("/etc/cdrtool/ngnpro_engines.inc");
global $domainFilters, $resellerFilters, $soapEngines ;
$credentials['account'] = sprintf("%s@%s",$username, $domain);
if ($domainFilters[$domain]['sip_engine']) {
$credentials['engine'] = $domainFilters[$domain]['sip_engine'];
$credentials['customer'] = $domainFilters[$domain]['customer'];
$credentials['reseller'] = $domainFilters[$domain]['reseller'];
} else if ($domainFilters['default']['sip_engine']) {
$credentials['engine']=$domainFilters['default']['sip_engine'];
} else {
$log=sprintf("SIP settings page error: no domainFilter available in ngnpro_engines.inc from %s", $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die();
}
$SOAPlogin=array(
"username" => $soapEngines[$credentials['engine']]['username'],
"password" => $soapEngines[$credentials['engine']]['password'],
"admin" => true
);
$SoapAuth = array('auth', $SOAPlogin , 'urn:AGProjects:NGNPro', 0, '');
$SipPort = new WebService_NGNPro_SipPort($soapEngines[$credentials['engine']]['url']);
$SipPort->_options['timeout'] = 5;
$SipPort->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0);
$SipPort->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0);
$SipPort->addHeader($SoapAuth);
$result = $SipPort->getAccount(array("username" =>$username,"domain" =>$domain));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$nonce.'",opaque="'.md5($realm).'"');
$log=sprintf("SIP settings page error: non-existent username %s from %s", $credentials['account'], $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die();
}
$web_password='';
foreach ($result->properties as $_property) {
if ($_property->name == 'web_password') {
//$web_password = explode(":", $_property->value, -1);
$split=explode(":",$_property->value);
$web_password=$split['0'];
break;
}
}
if (!empty($web_password)) {
//$A1 = md5($data['username'] . ':' . $realm . ':' . $data['password']);
$A1 = $web_password;
$login_type_log = 'web password';
//$log=sprintf("TEST %s %s %s %s", $data['username'], $realm, $web_password , $data['nonce']);
//syslog(LOG_NOTICE, $log);
// } else if (strstr($data['username'], '@')) {
// $A1 = md5($data['username'] . ':' . $realm . ':' . $result->password);
// $login_type_log = 'cleartext legacy password';
} else if ($result->ha1) {
$login_type_log = sprintf('encrypted password');
$A1 = $result->ha1;
} else {
$A1 = md5($data['username'] . ':' . $realm . ':' . $result->password);
$login_type_log = 'cleartext password';
}
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response ) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$nonce.'",opaque="'.md5($realm).'"');
$log=sprintf("SIP settings page error: wrong credentials using %s for %s from %s", $login_type_log, $credentials['account'], $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die();
}
// check nonce
$client_nonce_els=explode(":",base64_decode($data['nonce']));
if (md5($client_nonce_els[0].":".$_key) != $client_nonce_els[1]) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$nonce.'",opaque="'.md5($realm).'"');
$log=sprintf("SIP settings page error: wrong nonce for %s from %s", $credentials['account'], $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die();
}
if (microtime(true) > $client_nonce_els[0]) {
// nonce is stale
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$nonce.'",stale=true,opaque="'.md5($realm).'"');
$log=sprintf("SIP settings page error: nonce has expired for %s from %s", $username, $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
die();
}
$log=sprintf("SIP settings page: %s logged in using %s from %s", $credentials['account'], $login_type_log, $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
$credentials['customer'] = $result->customer;
$credentials['reseller'] = $result->reseller;
return $credentials;
}
function http_digest_parse($txt) {
// function to parse the http auth header
// protect against missing data
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
function renderUI($SipSettings_class,$account,$login_credentials,$soapEngines) {
// Generic code for all sip settings pages
$SipSettings = new $SipSettings_class($account,$login_credentials,$soapEngines);
if ($_REQUEST['action']) {
$log_action=$_REQUEST['action'];
} else {
$log_action='load main page';
}
$log=sprintf("SIP settings page: %s for %s from %s", $log_action, $account, $_SERVER['REMOTE_ADDR']);
syslog(LOG_NOTICE, $log);
if (!strstr($_REQUEST['action'],'get_') &&
!strstr($_REQUEST['action'],'set_') &&
!strstr($_REQUEST['action'],'put_') &&
!strstr($_REQUEST['action'],'delete_') &&
!strstr($_REQUEST['action'],'export_') &&
!strstr($_REQUEST['action'],'add_')) {
$title = "$account";
if (array_key_exists($SipSettings->tab, $SipSettings->tabs)) {
$title = $SipSettings->tabs[$SipSettings->tab]. " - ". $title;
}
$header = $SipSettings->headerFile;
$css = $SipSettings->cssFile;
$auto_refesh_tab=$SipSettings->auto_refesh_tab;
$absolute_url= $SipSettings->absolute_url;
include($header);
dprint("Header file $header included, refresh=$auto_refesh_tab");
include($css);
dprint("CSS file $css included");
}
if ($_REQUEST['action']=="save settings") {
if ($SipSettings->checkSettings()) {
$SipSettings->saveSettings();
unset($SipSettings);
$SipSettings = new $SipSettings_class($account,$login_credentials,$soapEngines);
} else {
print "<font color=red>";
printf (_("Error: %s"),$SipSettings->error);
print "</font>";
}
} else if ($_REQUEST['action']=="set diversions") {
$SipSettings->setDiversions();
unset($SipSettings);
$SipSettings = new $SipSettings_class($account,$login_credentials,$soapEngines);
} else if ($_REQUEST['action']=="set barring") {
$SipSettings->setBarringPrefixes();
} else if ($_REQUEST['action']=="set reject") {
$SipSettings->setRejectMembers();
} else if ($_REQUEST['action']=="set accept rules") {
$SipSettings->setAcceptRules();
} else if ($_REQUEST['action']=="set aliases") {
$SipSettings->setAliases();
} else if ($_REQUEST['action']=="send email") {
$SipSettings->sendEmail();
} else if ($_REQUEST['action']=="delete account") {
$SipSettings->deleteAccount();
} else if ($_REQUEST['action']=="delete_account") {
// print "<pre>";
// print_r($SipSettings->Preferences);
$date1= new datetime($SipSettings->Preferences['account_delete_request']);
$today= new datetime('now');
if ($date1->diff($today)->d <= '2' && $SipSettings->Preferences['account_delete_request'] ) {
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->deleteAccount($SipSettings->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$return=array('success' => false,
'error_message' => $_msg
);
return false;
} else {
printf("<p>The account %s has been removed</p>",$SipSettings->account);
$SipSettings->sendRemoveAccount();
//print "<script>var t1=setTimeout(window.location.href = 'sip_logout.phtml',5000);</script>"
print "<a href=sip_logout.phtml>";
print _("Click here to Logout");
print "</a>";
//$auth->logout();
//$sess->delete();
return true;
}
} else {
printf("The delete request for account %s has expired or is not valid",$SipSettings->account);
return false;
}
return true ;
//$SipSettings->deleteAccount();
} else if ($_REQUEST['action']=="get_crt") {
$SipSettings->exportCertificateX509();
return true;
} else if ($_REQUEST['action']=="get_p12") {
$SipSettings->exportCertificateP12();
return true;
} else if ($_REQUEST['action'] == 'get_balance_history') {
$SipSettings->getBalanceHistory();
if ($_REQUEST['csv']) {
$SipSettings->exportBalanceHistory();
} else {
print json_encode($SipSettings->balance_history);
}
return true;
} else if ($_REQUEST['action'] == 'get_call_forwarding') {
$SipSettings->getDiversions();
print json_encode($SipSettings->diversions);
return true;
} else if ($_REQUEST['action'] == 'get_prepaid') {
$SipSettings->getPrepaidStatus();
print json_encode($SipSettings->prepaidAccount);
return true;
} else if ($_REQUEST['action'] == 'get_monthly_usage') {
$SipSettings->getCallStatistics();
print json_encode($SipSettings->thisMonth);
return true;
} else if ($_REQUEST['action'] == 'get_accept_rules'){
$SipSettings->getAcceptRules();
print json_encode($SipSettings->acceptRules);
return true;
} else if ($_REQUEST['action'] == 'get_journal_entries'){
$SipSettings->getJournalEntries();
print json_encode($SipSettings->journalEntries);
return true;
} else if ($_REQUEST['action'] == 'put_journal_entries'){
print json_encode($SipSettings->putJournalEntries());
return true;
} else if ($_REQUEST['action'] == 'delete_journal_entries'){
print json_encode($SipSettings->deleteJournalEntries());
return true;
} else if ($_REQUEST['action'] == 'get_reject_rules'){
$SipSettings->getRejectMembers();
print json_encode($SipSettings->rejectMembers);
return true;
} else if ($_REQUEST['action'] == 'get_history'){
$SipSettings->getHistory('completed');
print json_encode($SipSettings->call_history);
return true;
} else if ($_REQUEST['action'] == 'get_voicemail'){
$SipSettings->getVoicemail();
print json_encode($SipSettings->voicemail);
return true;
} else if ($_REQUEST['action'] == 'get_aliases'){
$SipSettings->getAliases();
print json_encode($SipSettings->aliases);
return true;
} else if ($_REQUEST['action'] == 'get_enum'){
$SipSettings->getEnumMappings();
print json_encode($SipSettings->enums);
return true;
} else if ($_REQUEST['action'] == 'export_identity_proof'){
$SipSettings->exportIdentityProof();
return true;
} else if ($_REQUEST['action'] == 'add_balance'){
if (!$_REQUEST['id'] || !$_REQUEST['number']) {
$return=array('success' => false,
'error_message' => 'Missing id or number'
);
print (json_encode($return));
return false;
}
$card = array('id' => intval($_REQUEST['id']),
'number' => $_REQUEST['number']
);
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->addBalanceFromVoucher($SipSettings->sipId,$card);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$return=array('success' => false,
'error_message' => $_msg
);
print (json_encode($return));
return false;
} else {
$return=array('success' => true,
'error_message' => 'Added balance succeeded'
);
print (json_encode($return));
return true;
}
} else if ($_REQUEST['action'] == 'get_identity'){
$account=array('sip_address' => $SipSettings->account,
'email' => $SipSettings->email,
'first' => $SipSettings->firstName,
'lastname' => $SipSettings->lastName,
'pstn_caller_id' => $SipSettings->rpid,
'mobile_number' => $SipSettings->mobile_number,
'timezone' => $SipSettings->timezone,
'no_answer_timeout' => $SipSettings->timeout,
'quick_dial' => $SipSettings->quickdial
);
print json_encode($account);
return true;
} else if ($_REQUEST['action'] == 'get_devices'){
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->getSipDeviceLocations(array($SipSettings->sipId));
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return false;
} else {
foreach ($result[0]->locations as $locationStructure) {
$contact=$locationStructure->address.":".$locationStructure->port;
if ($locationStructure->publicAddress) {
$publicContact=$locationStructure->publicAddress.":".$locationStructure->publicPort;
} else {
$publicContact=$contact;
}
$devices[]=array("contact" => $contact,
"publicContact" => $publicContact,
"expires" => $locationStructure->expires,
"user_agent" => $locationStructure->userAgent,
"transport" => $locationStructure->transport
);
}
}
print (json_encode($devices));
return true;
} else if ($_REQUEST['action'] == 'set_dnd_on'){
$SipSettings->getAcceptRules();
$SipSettings->acceptRules['temporary']=array('groups' =>array('nobody'),
'duration' =>intval($_REQUEST['duration'])
);
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->setAcceptRules($SipSettings->sipId,$SipSettings->acceptRules);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
} else {
$_ret=true;
if (intval($_REQUEST['duration'] > 0)) {
$_msg=sprintf(_('Do not disturb has been enabled for %d minutes'),intval($_REQUEST['duration']));
} else {
$_msg=sprintf(_('Do not disturb has been enabled'));
}
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else if ($_REQUEST['action'] == 'set_dnd_off'){
$SipSettings->getAcceptRules();
$SipSettings->acceptRules['temporary']=array('groups' =>array('everybody'),
'duration' =>0
);
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->setAcceptRules($SipSettings->sipId,$SipSettings->acceptRules);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
} else {
$_ret=true;
$_msg=sprintf(_('Do not disturb has been disabled'));
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else if ($_REQUEST['action'] == 'set_privacy_on'){
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->addToGroup(array("username" => $SipSettings->username,"domain"=> $SipSettings->domain),"anonymous");
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
} else {
$_ret=true;
$_msg=sprintf(_('Caller-ID is now hidden for outgoing calls'));
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else if ($_REQUEST['action'] == 'set_privacy_off'){
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->removeFromGroup(array("username" => $SipSettings->username,"domain"=> $SipSettings->domain),"anonymous");
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
if ($error_fault->detail->exception->errorcode == 1031) {
$_ret=true;
$_msg=sprintf(_('Caller-ID is now visible for outgoing calls'));
} else {
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
}
} else {
$_ret=true;
$_msg=sprintf(_('Caller-ID is now visible for outgoing calls'));
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else if ($_REQUEST['action'] == 'add_alias'){
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$username=trim($_REQUEST['username']);
if (!strlen($username)) {
$return=array('success' => false,
'error_message' => 'Error: missing username'
);
print (json_encode($return));
return false;
}
$_aliasObject=array("id"=>array("username"=>strtolower($username),
"domain"=>$SipSettings->domain
),
"owner" => intval($SipSettings->owner),
"target"=> array("username" => $SipSettings->username,"domain"=> $SipSettings->domain)
)
;
$result = $SipSettings->SipPort->addAlias($_aliasObject);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
} else {
$_ret=true;
$_msg=sprintf(_('Added alias %s'),strtolower($username));
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else if ($_REQUEST['action'] == 'set_call_forwarding') {
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->getCallDiversions($SipSettings->sipId);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
}
$SipSettings->getVoicemail();
foreach(array_keys($SipSettings->diversionType) as $condition) {
$old_diversions[$condition]=$result->$condition;
}
$_log='';
foreach(array_keys($old_diversions) as $key) {
if (isset($_REQUEST[$key])) {
printf ("Key $key changed %s",$_REQUEST[$key]);
$textboxURI=$_REQUEST[$key];
if ($textboxURI == "<mobile-number>" && strlen($SipSettings->mobile_number)) {
$textboxURI = $SipSettings->mobile_number;
}
if ($textboxURI && $textboxURI != "<voice-mailbox>" && !preg_match("/@/",$textboxURI)) {
$textboxURI=$textboxURI."@".$SipSettings->domain;
}
if (preg_match("/^([\+|0].*)@/",$textboxURI,$m)) {
$textboxURI=$m[1]."@".$SipSettings->domain;
}
if (strlen($textboxURI) && $textboxURI != "<voice-mailbox>" && !preg_match("/^sip:/",$textboxURI)) {
$textboxURI='sip:'.$textboxURI;
}
if ($textboxURI) {
$new_diversions[$key]=$textboxURI;
}
$_log.=sprintf("%s=%s ",$key,$textboxURI);
$divert_changed=true;
} else {
if ($old_diversions[$key]) {
$new_diversions[$key]=$old_diversions[$key];
}
}
}
if ($divert_changed) {
$SipSettings->SipPort->addHeader($SipSettings->SoapAuth);
$result = $SipSettings->SipPort->setCallDiversions($SipSettings->sipId,$new_diversions);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
$_msg=sprintf ("Error (SipPort): %s (%s): %s",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
$_ret=false;
} else {
$_ret=true;
$_msg=sprintf(_('Changed diversions %s'),$_log);
}
$return=array('success' => $_ret,
'error_message' => $_msg
);
print (json_encode($return));
return true;
} else {
$return=array('success' => true,
'error_message' => 'Diversions remained the same'
);
print (json_encode($return));
return true;
}
} else if ($_REQUEST['action']) {
$return=array('success' => false,
'error_message' => "Error: invalid action"
);
print (json_encode($return));
return false;
}
if (!$_REQUEST['export']) {
$SipSettings->showAccount();
print "
</body>
</html>
";
}
}
class Enrollment {
var $init = false;
var $create_voicemail = false;
var $send_email_notification = true;
var $create_email_alias = false;
var $create_customer = true;
var $timezones = array();
var $default_timezone = 'Europe/Amsterdam';
var $configuration_file = '/etc/cdrtool/enrollment/config.ini';
var $allow_pstn = 1;
var $quota = 50;
var $prepaid = 1;
var $create_certificate = 0;
var $customer_belongs_to_reseller = false;
function log_action($action){
global $auth;
$location = "Unknown";
$_loc=geoip_record_by_name($_SERVER['REMOTE_ADDR']);
if ($_loc['country_name']) {
$location = $_loc['country_name'];
}
$log = sprintf("CDRTool login username=%s, IP=%s, location=%s, action=%s, script=%s",
$auth->auth["uname"],
$_SERVER['REMOTE_ADDR'],
$location,
$action,
$_SERVER['PHP_SELF']
);
syslog(LOG_NOTICE, $log);
}
function Enrollment()
{
require($this->configuration_file);
require("/etc/cdrtool/ngnpro_engines.inc");
$this->soapEngines = $soapEngines;
$this->enrollment = $enrollment;
$this->loadTimezones();
if (!is_array($this->soapEngines)) {
$return=array('success' => false,
'error_message' => 'Error: Missing soap engines configuration'
);
print (json_encode($return));
return false;
}
if (!is_array($this->enrollment)) {
$return=array('success' => false,
'error_message' => 'Error: Missing enrollment configuration'
);
print (json_encode($return));
return false;
}
$this->sipDomain = $this->enrollment['sip_domain'];
$this->sipEngine = $this->enrollment['sip_engine'];
if ($this->enrollment['timezone']) {
$this->default_timezone = $this->enrollment['timezone'];
}
if ($this->enrollment['customer_engine']) {
$this->customerEngine = $this->enrollment['customer_engine'];
} else {
$this->customerEngine = $this->enrollment['sip_engine'];
}
if ($this->enrollment['email_engine']) {
$this->emailEngine = $this->enrollment['email_engine'];
} else {
$this->emailEngine = $this->enrollment['sip_engine'];
}
if (is_array($this->enrollment['groups'])) {
$this->groups = $this->enrollment['groups'];
} else {
$this->groups = array();
}
$this->reseller = $this->enrollment['reseller'];
$this->outbound_proxy = $this->enrollment['outbound_proxy'];
$this->xcap_root = $this->enrollment['xcap_root'];
$this->msrp_relay = $this->enrollment['msrp_relay'];
$this->settings_url = $this->enrollment['settings_url'];
$this->ldap_hostname = $this->enrollment['ldap_hostname'];
$this->ldap_dn = $this->enrollment['ldap_dn'];
$this->conference_server = $this->enrollment['conference_server'];
if ($this->enrollment['sip_class']) {
$this->sipClass = $this->enrollment['sip_class'];
} else {
$this->sipClass = 'SipSettings';
}
if (!$this->sipEngine) {
$return=array('success' => false,
'error_message' => 'Missing sip engine'
);
print (json_encode($return));
return false;
}
if (!$this->sipDomain) {
$return=array('success' => false,
'error_message' => 'Missing sip domain'
);
print (json_encode($return));
return false;
}
$this->sipLoginCredentials = array(
'reseller' => intval($this->reseller),
'sip_engine' => $this->sipEngine,
'login_type' => 'admin'
);
$this->init=true;
}
function createAccount() {
if (!$this->init) return false;
if (!$_REQUEST['email']) {
$return=array('success' => false,
'error' => 'value_error',
'error_message' => 'Missing email address'
);
print (json_encode($return));
return false;
}
if (!$this->checkEmail($_REQUEST['email'])) {
$return=array('success' => false,
'error' => 'value_error',
'error_message' => 'Invalid email address'
);
print (json_encode($return));
return false;
}
if (!$_REQUEST['password']) {
$return=array('success' => false,
'error' => 'value_error',
'error_message' => 'Missing password'
);
print (json_encode($return));
return false;
}
if (!$_REQUEST['display_name']) {
$return=array('success' => false,
'error' => 'value_error',
'error_message' => 'Missing display name'
);
print (json_encode($return));
return false;
}
$username=strtolower(trim($_REQUEST['username']));
if (!preg_match("/^[1-9a-z][0-9a-z_.-]{2,64}[0-9a-z]$/",$username)) {
$return=array('success' => false,
'error' => 'value_error',
'error_message' => 'The username must contain at least 4 lowercase alpha-numeric . _ or - characters and must start and end with a positive digit or letter'
);
print (json_encode($return));
return false;
}
$sip_address=$username.'@'.$this->sipDomain;
if ($this->create_customer && !$_REQUEST['owner']) {
// create owner id
$customerEngine = 'customers@'.$this->customerEngine;
$this->CustomerSoapEngine = new SoapEngine($customerEngine,$this->soapEngines,$this->customerLoginCredentials);
$_customer_class = $this->CustomerSoapEngine->records_class;
$this->customerRecords = new $_customer_class($this->CustomerSoapEngine);
$this->customerRecords->html=false;
$properties=$this->customerRecords->setInitialCredits(array('sip_credit' => 1,
'sip_alias_credit' => 1,
'email_credit' => 1
)
);
if (preg_match("/^(\w+)\s+(\w+)$/",$_REQUEST['display_name'],$m)) {
$firstName = $m[1];
$lastName = $m[2];
} else {
$firstName = $_REQUEST['display_name'];
$lastName = 'Blink';
}
$this->log_action("Create owner account ($firstname $lastname) ");
$timezone=$_REQUEST['tzinfo'];
if (!in_array($timezone, $this->timezones)) {
$timezone=$this->default_timezone;
}
$location = lookupGeoLocation($_SERVER['REMOTE_ADDR']);
$customer=array(
'firstName' => $firstName,
'lastName' => $lastName,
'timezone' => $timezone,
'password' => trim($_REQUEST['password']),
'email' => trim($_REQUEST['email']),
'country' => $location['country_code'],
'state' => utf8_encode($location['region']),
'city' => utf8_encode($location['city']),
'properties' => $properties
);
if ($this->customer_belongs_to_reseller) {
$customer['reseller'] =intval($this->reseller);
}
if ($location['country_code'] == 'NL') {
$customer['tel'] = '+31999999999';
} else if ($location['country_code'] == 'US') {
$customer['tel'] = sprintf ("+1%s9999999",$location['area_code']);
} else {
$customer['tel'] = '+19999999999';
}
$_customer_created=false;
$j=0;
while ($j < 3) {
$username.=RandomString(4);
$customer['username']=$username;
if (!$result = $this->customerRecords->addRecord($customer)) {
if ($this->customerRecords->SoapEngine->exception->errorcode != "5001") {
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => 'failed to create non-duplicate customer entry'
);
print (json_encode($return));
return false;
}
} else {
$_customer_created=true;
break;
}
$j++;
}
if (!$_customer_created) {
if ($this->sipRecords->soap_error_description) {
$_msg=$this->sipRecords->soap_error_description;
} else {
$_msg='failed to create customer account';
}
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => $_msg
);
print (json_encode($return));
return false;
} else {
$this->log_action("Owner account created (". $customer['username'].")");
}
$owner=$result->id;
if (!$owner) {
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => 'failed to obtain a new owner id'
);
print (json_encode($return));
return false;
} else {
$this->log_action("Owner id is $owner (". $customer['username'].")");
}
} else if (is_numeric($_REQUEST['owner']) && $_REQUEST['owner'] != 0 ) {
$owner=intval($_REQUEST['owner']);
} else {
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => 'no owner information provided'
);
print (json_encode($return));
return false;
}
// create SIP Account
$sipEngine = 'sip_accounts@'.$this->sipEngine;
$this->SipSoapEngine = new SoapEngine($sipEngine,$this->soapEngines,$this->sipLoginCredentials);
$_sip_class = $this->SipSoapEngine->records_class;
$this->sipRecords = new $_sip_class($this->SipSoapEngine);
$this->sipRecords->html=false;
$sip_properties[]=array('name'=> 'ip', 'value' => $_SERVER['REMOTE_ADDR']);
$sip_properties[]=array('name'=> 'registration_email', 'value' => $_REQUEST['email']);
$languages=array("en","ro","nl","es","de");
if (isset($_REQUEST['lang'])){
if (in_array($_REQUEST['lang'],$languages)) {
$sip_properties[]=array('name'=> 'language', 'value' => $_REQUEST['lang']);
}
}
if (strlen($timezone)) {
$sip_properties[]=array('name'=> 'timezone', 'value' => $timezone);
}
if (strlen($user_agent)) {
$sip_properties[]=array('name'=> 'user_agent', 'value' => trim(urldecode($user_agent)));
}
$sipAccount = array('account' => $sip_address,
'fullname' => $_REQUEST['display_name'],
'email' => $_REQUEST['email'],
'password' => $_REQUEST['password'],
'timezone' => $timezone,
'prepaid' => $this->prepaid,
'pstn' => $this->allow_pstn,
'quota' => $this->quota,
'owner' => intval($owner),
'groups' => $this->groups,
'properties'=> $sip_properties
);
$this->log_action("Create SIP account ($sip_addres)");
if (!$result = $this->sipRecords->addRecord($sipAccount)) {
if ($this->sipRecords->SoapEngine->exception->errorstring) {
if ($this->sipRecords->SoapEngine->exception->errorcode == 1011) {
$return=array('success' => false,
'error' => 'user_exists',
'error_message' => $this->sipRecords->SoapEngine->exception->errorstring
);
} else {
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => $this->sipRecords->SoapEngine->exception->errorstring
);
}
} else {
$_msg='failed to create sip account';
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => $_msg
);
}
print (json_encode($return));
$_dictionary=array('customer'=>intval($owner),
'error' => 'internal_error',
'confirm' => true
);
$this->customerRecords->deleteRecord($_dictionary);
return false;
} else {
$sip_address=$result->id->username.'@'.$result->id->domain;
$this->log_action("SIP account created ($sip_address)");
if ($this->create_certificate) {
if (!$passport = $this->generateCertificate($sip_address,$_REQUEST['email'],$_REQUEST['password'])) {
$return=array('success' => false,
'error' => 'internal_error',
'error_message' => 'failed to generate certificate'
);
print (json_encode($return));
return false;
}
}
// Generic code for all sip settings pages
if ($this->create_voicemail || $this->send_email_notification) {
if ($SipSettings = new $this->sipClass($sip_address,$this->sipLoginCredentials,$this->soapEngines)) {
if ($this->create_voicemail) {
// Add voicemail account
$this->log_action("Add voicemail account ($sip_address)");
$SipSettings->addVoicemail();
$SipSettings->setVoicemailDiversions();
}
if ($this->send_email_notification) {
// Sent account settings by email
$SipSettings->sendEmail('hideHtml');
}
}
}
if ($this->create_email_alias) {
$this->log_action("Add email alias ($sip_address)");
$emailEngine = 'email_aliases@'.$this->emailEngine;
$this->EmailSoapEngine = new SoapEngine($emailEngine,$this->soapEngines,$this->sipLoginCredentials);
$_email_class = $this->EmailSoapEngine->records_class;
$this->emailRecords = new $_email_class($this->EmailSoapEngine);
$this->emailRecords->html=false;
$emailAlias = array('name' => strtolower($sip_address),
'type' => 'MBOXFW',
'owner' => intval($owner),
'value' => $_REQUEST['email']
);
$this->emailRecords->addRecord($emailAlias);
}
$return=array('success' => true,
'sip_address' => $sip_address,
'email' => $result->email,
'settings_url' => $this->settings_url,
'outbound_proxy' => $this->outbound_proxy
);
if ($this->create_certificate) {
$return['passport'] = $passport;
}
if ($this->ldap_hostname) {
$return['ldap_hostname'] = $this->ldap_hostname;
}
if ($this->ldap_dn) {
$return['ldap_dn'] = $this->ldap_dn;
}
if ($this->msrp_relay) {
$return['msrp_relay'] = $this->msrp_relay;
}
if ($this->xcap_root) {
$return['xcap_root'] = $this->xcap_root;
}
if ($this->conference_server) {
$return['conference_server'] = $this->conference_server;
}
print (json_encode($return));
return true;
}
}
function generateCertificate($sip_address,$email,$password) {
if (!$this->init) return false;
if (!is_array($this->enrollment)) {
print _("Error: missing enrollment settings");
return false;
}
if (!$this->enrollment['ca_conf']) {
//print _("Error: missing enrollment ca_conf settings");
return false;
}
if (!$this->enrollment['ca_crt']) {
//print _("Error: missing enrollment ca_crt settings");
return false;
}
if (!$this->enrollment['ca_key']) {
//print _("Error: missing enrollment ca_key settings");
return false;
}
$config = array(
'config' => $this->enrollment['ca_conf'],
'digest_alg' => 'md5',
'private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'encrypt_key' => false,
);
$dn = array(
"countryName" => $this->enrollment['countryName'],
"stateOrProvinceName" => $this->enrollment['stateOrProvinceName'],
"localityName" => $this->enrollment['localityName'],
"organizationName" => $this->enrollment['organizationName'],
"organizationalUnitName" => $this->enrollment['organizationalUnitName'],
"commonName" => $sip_address,
"emailAddress" => $email
);
$this->key = openssl_pkey_new($config);
$this->csr = openssl_csr_new($dn, $this->key);
openssl_csr_export($this->csr, $this->csr_out);
openssl_pkey_export($this->key, $this->key_out, $password, $config);
$ca="file://".$this->enrollment['ca_crt'];
$this->crt = openssl_csr_sign($this->csr, $ca, $this->enrollment['ca_key'], 3650, $config);
if ($this->crt==FALSE) {
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
print "<br><br>";
}
return false;
}
openssl_x509_export ($this->crt, $this->crt_out);
openssl_pkcs12_export ($this->crt, $this->pk12_out, $this->key, $password);
return array(
'crt' => $this->crt_out,
'key' => $this->key_out,
'pk12' => $this->pk12_out,
'ca' => file_get_contents($this->enrollment['ca_crt'])
);
}
function checkEmail($email) {
dprint ("checkEmail($email)");
$regexp = "/^([a-z0-9][a-z0-9_.-]*)@([a-z0-9][a-z0-9-]*\.)+([a-z]{2,})$/i";
if (stristr($email,"-.") ||
!preg_match($regexp, $email)) {
return false;
}
return true;
}
function loadTimezones () {
if (!$fp = fopen("timezones", "r")) {
syslog(LOG_NOTICE, 'Error: Failed to open timezones file');
return false;
}
while ($buffer = fgets($fp,1024)) {
$this->timezones[]=trim($buffer);
}
fclose($fp);
}
}
class PaypalProcessor {
var $deny_countries = array();
var $allow_countries = array();
var $deny_ips = array();
var $make_credit_checks = true;
var $transaction_results = array('success' => false);
var $vat = 0;
function PaypalProcessor($account) {
require('cc_processor.php');
$this->CardProcessor = new CreditCardProcessor();
$this->account = &$account;
}
function refundTransaction($transaction_id) {
}
function doDirectPayment($basket) {
if (!is_object($this->account)) {
print "
<tr>
<td colspan=3>
";
print 'Invalid account data';
print "
</td>
</tr>
";
return false;
}
if (!is_array($basket)) {
print "
<tr>
<td colspan=3>
";
print 'Invalid basket data';
print "
</td>
</tr>
";
return false;
}
if (is_array($this->test_credit_cards) && in_array($_POST['creditCardNumber'], $this->test_credit_cards)) {
$this->CardProcessor->environment='sandbox';
}
$this->CardProcessor->chapter_class = 'chapter';
$this->CardProcessor->odd_row_class = 'oddc';
$this->CardProcessor->even_row_class = 'evenc';
$this->CardProcessor->note = $this->account->account;
$this->CardProcessor->account = $this->account->account;
$this->CardProcessor->vat = $this->vat;
// set hidden elements we need to preserve in the shopping cart application
$this->CardProcessor->hidden_elements = $this->account->hiddenElements;
// load shopping items
$this->CardProcessor->cart_items=$basket;
// load user information from owner information if available otherwise from sip account settings
if ($this->account->owner_information['firstName']) {
$this->CardProcessor->user_account['FirstName']=$this->account->owner_information['firstName'];
} else {
$this->CardProcessor->user_account['FirstName']=$this->account->firstName;
}
if ($this->account->owner_information['lastName']) {
$this->CardProcessor->user_account['LastName']=$this->account->owner_information['lastName'];
} else {
$this->CardProcessor->user_account['LastName']=$this->account->lastName;
}
if ($this->account->owner_information['email']) {
$this->CardProcessor->user_account['Email']=$this->account->owner_information['email'];
} else {
$this->CardProcessor->user_account['Email']=$this->account->email;
}
if ($this->account->owner_information['address'] && $this->account->owner_information['address']!= 'Unknown') {
$this->CardProcessor->user_account['Address1']=$this->account->owner_information['address'];
} else {
$this->CardProcessor->user_account['Address1']='';
}
if ($this->account->owner_information['city'] && $this->account->owner_information['city']!= 'Unknown') {
$this->CardProcessor->user_account['City']=$this->account->owner_information['city'];
} else {
$this->CardProcessor->user_account['City']='';
}
if ($this->account->owner_information['country'] && $this->account->owner_information['country']!= 'Unknown') {
$this->CardProcessor->user_account['Country']=$this->account->owner_information['country'];
} else {
$this->CardProcessor->user_account['Country']='';
}
if ($this->account->owner_information['state'] && $this->account->owner_information['state']!= 'Unknown') {
$this->CardProcessor->user_account['State']=$this->account->owner_information['state'];
} else {
$this->CardProcessor->user_account['State']='';
}
if ($this->account->owner_information['postcode'] && $this->account->owner_information['postcode']!= 'Unknown') {
$this->CardProcessor->user_account['PostCode']=$this->account->owner_information['postcode'];
} else {
$this->CardProcessor->user_account['PostCode']='';
}
if ($_REQUEST['purchase'] == '1' ) {
$chapter=sprintf(_("Transaction Results"));
$this->account->showChapter($chapter);
print "
<tr>
<td colspan=3>
";
// ensure that submit requests are coming only from the current page
if ($_SERVER['HTTP_REFERER'] == $this->CardProcessor->getPageURL()) {
// check submitted values
$errors = $this->CardProcessor->checkForm($_POST);
if (count($errors) > 0){
print $this->CardProcessor->displayFormErrors($errors);
foreach (array_keys($errors) as $key) {
$log_text.=sprintf("%s:%s ",$errors[$key]['field'],$errors[$key]['desc']);
}
$log=sprintf("CC transaction for %s failed with error: %s",$this->account->account,$log_text);
syslog(LOG_NOTICE, $log);
return false;
}
// process the payment
$b=time();
$pay_process_results = $this->CardProcessor->processPayment($_POST);
if(count($pay_process_results['error']) > 0){
// there was a problem with payment
// show error and stop
if ($pay_process_results['error']['field'] == 'reload') {
print $pay_process_results['error']['desc'];
} else {
print $this->CardProcessor->displayProcessErrors($pay_process_results['error']);
}
$e=time();
$d=$e-$b;
$log=sprintf("CC transaction for %s failed with error: %s (%s) after %d seconds",
$this->account->account,
$pay_process_results['error']['short_message'],
$pay_process_results['error']['error_code'],
$d
);
syslog(LOG_NOTICE, $log);
return false;
} else {
$e=time();
$d=$e-$b;
$log=sprintf("CC transaction %s for %s completed succesfully in %d seconds",
$pay_process_results['success']['desc']->TransactionID,
$this->account->account,
$d
);
syslog(LOG_NOTICE, $log);
print "<p>";
print _("Transaction completed sucessfully. ");
/*
if ($this->CardProcessor->environment!='sandbox' && $this->account->first_transaction) {
print "<p>";
print _("This is your first payment. ");
print "<p>";
print _("Please allow the time to check the validity of your transaction before activating your Credit. ");
print "<p>";
print _("You can speed up the validation process by sending a copy of an utility bill (electriciy, gas or TV) that displays your address. ");
print "<p>";
printf (_("For questions related to your payments or to request a refund please email to <i>%s</i> and mention your transaction id <b>%s</b>. "),
$this->account->billing_email,
$pay_process_results['success']['desc']->TransactionID
);
$this->make_credit_checks=true;
} else {
print "<p>";
print _("You may check your new balance in the Credit tab. ");
}
*/
}
if ($this->account->Preferences['ip'] && $_loc=geoip_record_by_name($this->account->Preferences['ip'])) {
$enrollment_location=$_loc['country_name'].'/'.$_loc['city'];
} else if ($this->account->Preferences['ip'] && $_loc=geoip_country_name_by_name($this->account->Preferences['ip'])) {
$enrollment_location=$_loc;
} else {
$enrollment_location='Unknown';
}
if ($_loc=geoip_record_by_name($_SERVER['REMOTE_ADDR'])) {
$transaction_location=$_loc['country_name'].'/'.$_loc['city'];
} else if ($_loc=geoip_country_name_by_name($_SERVER['REMOTE_ADDR'])) {
$transaction_location=$_loc;
} else {
$transaction_location='Unknown';
}
if ($this->account->Preferences['timezone']) {
$timezone=$this->account->Preferences['timezone'];
} else {
$timezone='Unknown';
}
$extra_information=array(
'Account Page' => $this->account->admin_url_absolute,
'Account First Name' => $this->account->firstName,
'Account Last Name ' => $this->account->lastName,
'Account Timezone' => $this->account->timezone,
'Enrollment IP' => $this->account->Preferences['ip'],
'Enrollment Location' => $enrollment_location,
'Enrollment Email' => $this->account->Preferences['registration_email'],
'Enrollment Timezone' => $timezone,
'Transaction Location' => $transaction_location
);
$result = $this->account->addInvoice($this->CardProcessor);
if ($result) {
$extra_information['Invoice Page']=sprintf("https://admin.ag-projects.com/admin/invoice.phtml?iId=%d&adminonly=1",$result['invoice']);
}
if ($this->CardProcessor->saveOrder($_POST,$pay_process_results,$extra_information)) {
$this->transaction_results=array('success' => true,
'id' => $this->CardProcessor->transaction_data['TRANSACTION_ID']
);
return true;
} else {
$log=sprintf("Error: SIP Account %s - CC transaction %s failed to save order",$this->account->account, $this->CardProcessor->transaction_data['TRANSACTION_ID']);
syslog(LOG_NOTICE, $log);
return false;
}
} else {
print _("Invalid CC Request");
return false;
}
print "
</td>
</tr>
";
} else {
print "
<tr>
<td colspan=3>
";
// print the submit form
$arr_form_page_objects = $this->CardProcessor->showSubmitForm();
print $arr_form_page_objects['page_body_content'];
print "
</td>
</tr>
";
}
}
function fraudDetected() {
if (count($this->deny_ips)) {
foreach ($this->deny_ips as $_ip) {
if ($this->account->Preferences['ip'] && preg_match("/^$_ip/",$this->account->Preferences['ip'])) {
$this->fraud_reason=$this->account->Preferences['ip'].' is Blocked';
return true;
}
if (preg_match("/^$_ip/",$_SERVER['REMOTE_ADDR'])) {
$this->fraud_reason=$_SERVER['REMOTE_ADDR'].' is a Blocked';
return true;
}
}
}
if (count($this->deny_countries)) {
if ($_loc=geoip_record_by_name($this->account->Preferences['ip'])) {
if (in_array($_loc['country_name'],$this->deny_countries)) {
$this->fraud_reason=$_loc['country_name'].' is Blocked';
return true;
}
}
}
if (count($this->allow_countries)) {
if ($_loc=geoip_record_by_name($this->account->Preferences['ip'])) {
if (!in_array($_loc['country_name'],$this->allow_countries)) {
$this->fraud_reason=$_loc['country_name'].' is Not Allowed';
return true;
}
}
}
if (count($this->deny_email_domains)) {
if (count($this->accept_email_addresses)) {
if (in_array($this->account->email,$this->accept_email_addresses)) return false;
}
list($user,$domain)= explode("@",$this->account->email);
foreach ($this->deny_email_domains as $deny_domain) {
if ($domain == $deny_domain) {
$this->fraud_reason=sprintf ('Domain %s is Not Allowed',$domain);
return true;
}
}
}
return false;
}
}
class DIDProcessor {
function DIDProcessor() {
/*
http://www.didww.com/support/
API help page: http://open.didww.com
*/
$this->db = new DB_CDRTool();
require('didww_soap_library.php');
include("/etc/cdrtool/enrollment/config.ini");
if (!$enrollment['did_username'] || !$enrollment['did_key']) {
print '<p>Error: Missing DID engine credentials';
return false;
}
if ($enrollment['did_environment'] == 'production') {
$this->did_engine = new WebService_DID_World_Wide__DID_World_Wide_Port();
$this->auth_string = sha1($enrollment['did_username'].$enrollment['did_key']);
$this->environment='production';
} else {
print "<h2>Testing DID environment</h2>";
flush();
$this->did_engine = new WebService_DID_World_Wide__DID_World_Wide_Port_Testing();
$this->auth_string = sha1($enrollment['did_username'].$enrollment['did_key'].'sandbox');
$this->environment='testing';
}
$this->did_engine->_options['timeout'] = 30;
}
function getPrefixesFromRemote () {
if (!$this->auth_string) return false;
$result = $this->did_engine->didww_getdidwwregions($this->auth_string,$country);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error: %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
foreach ($result as $_country) {
foreach ($_country->cities as $_city) {
$prefix = $_country->country_prefix.$_city->city_prefix;
if (!$_city->isavailable) continue;
$prefixes[$prefix]=array('country_prefix' => trim($_country->country_prefix),
'country_name' => trim($_country->country_name),
'country_iso' => trim($_country->country_iso),
'city_name' => trim($_city->city_name),
'city_prefix' => trim($_city->city_prefix),
'setup' => $_city->setup,
'monthly' => $_city->monthly
);
}
}
}
return $prefixes;
}
function getPrefixes () {
$query=sprintf("select * from ddi_cache where environment = '%s' and DATE_ADD(date, INTERVAL +1 day) > NOW()",addslashes($this->environment));
if (!$this->db->query($query)) return false;
if ($this->db->num_rows()) {
$this->db->next_record();
$prefixes = json_decode($this->db->f('cache'),true);
if (!is_array($prefixes)) {
$prefixes = $this->cachePrefixes();
}
} else {
$prefixes=$this->cachePrefixes();
}
return $prefixes;
}
function cachePrefixes() {
if ($prefixes = $this->getPrefixesFromRemote()) {
$query=sprintf("delete from ddi_cache where environment = '%s'",addslashes($this->environment));
$this->db->query($query);
$query=sprintf("insert into ddi_cache (cache,date,environment) values ('%s', NOW(),'%s')",addslashes(json_encode($prefixes)),addslashes($this->environment));
$this->db->query($query);
return $prefixes;
} else {
return false;
}
}
function getResellerInfo() {
if (!$this->auth_string) return false;
$result = $this->did_engine->didww_getdidwwapidetails($this->auth_string);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error: %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
print "<pre>";
print_r($result);
print "</pre>";
}
}
function createOrder($data) {
if (!$this->auth_string) return false;
print "<pre>";
print_r($data);
print "</pre>";
$result = $this->did_engine->didww_ordercreate($this->auth_string,
$data['customer_id'],
$data['country_iso'],
$data['city_prefix'],
$data['period'],
$data['map_data'],
$data['prepaid_funds'],
$data['uniq_hash']
);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error: %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
$query=sprintf ("insert into ddi_numbers (
`customer_id`,
`country_name`,
`city_name`,
`did_number`,
`did_status`,
`did_timeleft`,
`did_expire_date_gmt`,
`order_id`,
`order_status`,
`sip_address`,
`did_setup`,
`did_monthly`,
`did_period`,
`prepaid_balance`,
`environment`
)
values
(
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s',
'%s'
)
",
addslashes($data['customer_id']),
addslashes($result->country_name),
addslashes($result->city_name),
addslashes($result->did_number),
addslashes($result->did_status),
addslashes($result->did_timeleft),
addslashes($result->did_expire_date_gmt),
addslashes($result->order_id),
addslashes($result->order_status),
addslashes($data['map_data']['map_detail']),
addslashes($result->did_setup),
addslashes($result->did_monthly),
addslashes($result->did_period),
addslashes($result->prepaid_balance),
addslashes($this->environment)
);
if (!$this->db->query($query)) {
$log=sprintf ("Database error for DID createOrder: %s (%s)",$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
}
}
}
function renewOrder($data) {
if (!$this->auth_string) return false;
print "<pre>";
print_r($data);
print "</pre>";
$result = $this->did_engine->didww_orderautorenew($this->auth_string,
$data['customer_id'],
$data['number'],
$data['period'],
$data['uniq_hash']
);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error: %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
$query=sprintf ("update ddi_numbers set did_timeleft = '%s' and did_expire_date_gmt = '%s' where did_number = '%s'
",
addslashes($result->did_timeleft),
addslashes($result->did_expire_date_gmt),
addslashes($result->did_number)
);
if (!$this->db->query($query)) {
$log=sprintf ("Database error for DID renewOrder: %s (%s)",$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
}
print $query;
}
}
function cancelOrder($data) {
if (!$this->auth_string) return false;
print "<pre>";
print_r($data);
print "</pre>";
$result = $this->did_engine->didww_ordercancel($this->auth_string,
$data['customer_id'],
$data['number']
);
if ((new PEAR)->isError($result)) {
$error_msg = $result->getMessage();
$error_fault= $result->getFault();
$error_code = $result->getCode();
printf ("<p><font color=red>Error: %s (%s): %s</font>",$error_msg, $error_fault->detail->exception->errorcode,$error_fault->detail->exception->errorstring);
return false;
} else {
$query=sprintf ("delete from ddi_numbers where did_number = '%s'",addslashes($result->did_number));
if (!$this->db->query($query)) {
$log=sprintf ("Database error for DID cancelOrder: %s (%s)",$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
}
print $query;
}
}
function getOrders($sip_address) {
$orders=array();
$query=sprintf ("select * from ddi_numbers where sip_address = '%s' and environment = '%s'",addslashes($sip_address),addslashes($this->environment));
if (!$this->db->query($query)) {
$log=sprintf ("Database error for DID createOrder: %s (%s)",$this->db->Error,$this->db->Errno);
print $log;
syslog(LOG_NOTICE, $log);
} else {
while ($this->db->next_record()) {
$orders[$this->db->f('did_number')]=array('country_name' => $this->db->f('country_name'),
'city_name' => $this->db->f('city_name'),
'did_status' => $this->db->f('did_status'),
'did_timeleft' => $this->db->f('did_timeleft'),
'did_expire_date_gmt' => $this->db->f('did_expire_date_gmt'),
'order_id' => $this->db->f('order_id'),
'order_status' => $this->db->f('order_status'),
'sip_address' => $this->db->f('sip_address'),
'did_setup' => $this->db->f('did_setup'),
'did_monthly' => $this->db->f('did_monthly')
);
}
}
return $orders;
}
}
function RandomIdentifier($length = 30)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
function getDisplayNameFromFromHeader($header)
{
// match all words and whitespace, will be terminated by '<'
$name = preg_match("/([\w\s]+).*<.*/", $header, $matches);
if (isset($matches[1])) {
return trim($matches[1]);
} else {
return "";
}
}
if (file_exists("/etc/cdrtool/local/sip_settings.php")) {
require_once '/etc/cdrtool/local/sip_settings.php';
}
?>

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 4:50 AM (1 d, 3 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
6a/36/df7e9ad9eca77cc50900f5bee702
Default Alt Text
(1 MB)

Event Timeline