* - If your dialplan is finite (completely fixed length (depends on your country dialplan) dialplan, then dial templates are not required) -->
* - As far as i know FreePBX does also attempt to build a finite dialplan -->
* - Having to maintain both an asterisk dialplan and these skinny dial templates is annoying -->
* + Dial Templates + Configuration
* + Dial Templates in Global Configuration ( Enabled / Disabled ; default template )
* ? Dial Templates - Howto IT Include in XML.Config ???????
* + Dial Templates - SIP Device
* - Dial Templates in device Configuration ( Enabled / inheret / Disabled ; template )
* - WiFi Config (Bulk Deployment Utility for Cisco 7921, 7925, 7926)?????
* + Change internal use Field to _Field (new feature in chan_sccp (added for Sccp_manager))
* + Delete phone XML
* + Change Installer ?? (test )
* + Installer Realtime config update
* + Installer Adaptive DB reconfig.
* + Add system info page
* + Change Cisco Language data
* + Make DB Acces from separate class
* + Make System Acces from separate class
* + Make Var elements from separate class
* + To make creating XML files in a separate class
* + Add Switch to select XML schema (display)
* + SRST Config
* + secondary_dialtone_digits = "" line config
* + secondary_dialtone_tone = 0x22 line config
* - deviceSecurityMode http://usecallmanager.nz//itl-file-tlv.html
* - transportLayerProtocol http://usecallmanager.nz//itl-file-tlv.html
* - Check Time zone ....
* - Failover config
* + Auto Addons!
* + DND Mode
* - support kv-store ?????
* + Shared Line
* - bug Soft key set (empty keysets )
* - bug Fix ...(K no w bug? no fix)
* - restore default Value on page
* - restore default Value on sccp.class
* - 'Device SEP ID.[XXXXXXXXXXXX]=MAC'
* + ATA's start with ATAXXXXXXXXXXXX.
* + Create ATADefault.cnf.xml
* - Create Second line Use MAC AABBCCDDEEFF rotation MAC BBCCDDEEFF01 (ATA 187 )
* + Add SEP, ATA, VG prefix.
* + Add Cisco SIP device Tftp config.
* - VG248 ports start with VGXXXXXXXXXXXX0.
* * I think this file should be split in 3 parts (as in Model-View-Controller(MVC))
* * XML/Database Parts -> Model directory
* * Processing parts -> Controller directory
* * Ajax Handler Parts -> Controller directory
* * Result parts -> View directory
* + Support TFTP rewrite :
* + dir "settings"
* + dir "templates"
* + dir "firmware"
* + dir "locales"
* + Add error information on the server information page (critical display error - the system can not work correctly)
* - Add Warning Information on Server Info Page
* - ADD Reload Line
* - Add Call Map (show Current call Information)
* ---TODO ---
*
* 0
* 0
*
*/
namespace FreePBX\modules;
class Sccp_manager extends \FreePBX_Helpers implements \BMO {
/* Field Values for type seq */
private $pagedata = null;
private $sccp_driver_ver = '11.4'; // Ver fore SCCP.CLASS.PHP
public $sccp_manager_ver = '14.1.0.0';
public $sccp_branch = 'm'; // Ver fore SCCP.CLASS.PHP
private $installedLangs = array();
private $hint_context = array('default' => '@ext-local'); /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Get it from Config !!!
private $val_null = 'NONE'; /// REPLACE to null Field
public $sccp_model_list = array();
private $cnf_wr = null;
public $sccppath = array();
public $sccpvalues = array();
public $sccp_conf_init = array();
public $xml_data;
public $class_error; //error construct
public $info_warning;
public $sccpHelpInfo = array();
// Move all non sccp_manager specific functions to traits
use \FreePBX\modules\Sccp_Manager\sccpManTraits\helperFunctions;
use \FreePBX\modules\Sccp_Manager\sccpManTraits\ajaxHelper; // TODO should migrate this to child class
use \FreePBX\modules\Sccp_Manager\sccpManTraits\bmoFunctions;
public function __construct($freepbx = null) {
if ($freepbx == null) {
throw new Exception("Not given a FreePBX Object");
}
$this->class_error = array();
$this->FreePBX = $freepbx;
$this->db = $freepbx->Database;
$this->cnf_wr = \FreePBX::WriteConfig();
$this->cnf_read = \FreePBX::LoadConfig();
$driverNamespace = "\\FreePBX\\Modules\\Sccp_manager";
if (class_exists($driverNamespace, false)) {
foreach (glob(__DIR__ . "/sccpManClasses/*.class.php") as $driver) {
if (preg_match("/\/([a-z1-9]*)\.class\.php$/i", $driver, $matches)) {
$name = $matches[1];
$class = $driverNamespace . "\\" . $name;
if (!class_exists($class, false)) {
include($driver);
}
if (class_exists($class, false)) {
$this->$name = new $class($this);
} else {
throw new \Exception("Invalid Class inside in the include folder" . print_r($freepbx));
}
}
}
} else {
return;
}
$this->sccpvalues = $this->dbinterface->get_db_SccpSetting(); //Initialise core settings
$this->initializeSccpPath(); //Set required Paths
$this->updateTimeZone(); // Get timezone from FreePBX
$this->findInstLangs();
$this->saveSccpSettings();
}
/*
* Generate Input elements in Html Code from sccpgeneral.xml
*/
public function showGroup($group_name, $show_Header, $form_prefix = 'sccp', $form_values = array()) {
// load xml data - moved from Construct to simplify Construct.
// TODO: This is static data so only load first time. Left as is for dbug.
$xml_vars = __DIR__ . '/conf/sccpgeneral.xml.v433';
$this->xml_data = simplexml_load_file($xml_vars);
// load metainfo from chan-sccp - help information if not in xml. Only load first time as static data.
if (empty($this->sccpHelpInfo)) {
$sysConfiguration = $this->aminterface->getSCCPConfigMetaData('general');
foreach ($sysConfiguration['Options'] as $key => $valueArray) {
foreach ($valueArray['Description'] as $descKey => $descValue) {
$this->sccpHelpInfo[$valueArray['Name']] .= $descValue . '
';
}
}
unset($sysConfiguration);
}
if ((array) $this->xml_data) {
foreach ($this->xml_data->xpath('//page_group[@name="' . $group_name . '"]') as $item) {
$htmlret = load_view(__DIR__ . '/views/formShowSysDefs.php', array(
'itm' => $item,
'h_show' => $show_Header,
'form_prefix' => $form_prefix,
'fvalues' => $form_values,
'installedLangs' => $this->installedLangs,
'chanSccpHelp' => $this->sccpHelpInfo,
'sccp_defaults' => $this->sccpvalues
)
);
}
} else {
$htmlret = load_view(__DIR__ . '/views/formShowError.php');
}
return $htmlret;
}
/*
* Load config vars from base array
*/
public function updateTimeZone() {
// Get latest FreePBX time $timeZoneOffsetList
$freepbxTZ = \date_default_timezone_get();
$this->sccpvalues['ntp_timezone'] = array('keyword' => 'ntp_timezone', 'seq'=>95, 'type' => 2, 'data' => $freepbxTZ);
$TZdata = $this->extconfigs->getExtConfig('sccp_timezone', $freepbxTZ);
if (!empty($TZdata)) {
$value = $TZdata['offset']/60; // TODO: Is this correct (storing in hours not minutes)
$this->sccpvalues['tzoffset'] = array('keyword' => 'tzoffset', 'seq'=>98, 'type' => 2, 'data' => $value);
}
}
/*
* Show form information - General
*/
public function settingsShowPage() {
$this->checkTftpMapping();
$request = $_REQUEST;
$action = !empty($request['action']) ? $request['action'] : '';
$this->pagedata = array(
"general" => array(
"name" => _("Site Default Settings"),
"page" => 'views/server.setting.php'
),
"sccpdevice" => array(
"name" => _("SCCP Device"),
"page" => 'views/server.device.php'
),
"sccpurl" => array(
"name" => _("SCCP Device URL"),
"page" => 'views/server.url.php'
),
"sccpntp" => array(
"name" => _("SCCP Time"),
"page" => 'views/server.datetime.php'
),
"sccpcodec" => array(
"name" => _("SCCP Codec"),
"page" => 'views/server.codec.php'
),
"sccpadv" => array(
"name" => _("Advanced SCCP Settings"),
"page" => 'views/server.advanced.php'
),
"sccpinfo" => array(
"name" => _("SCCP info"),
"page" => 'views/server.info.php'
)
);
// If view is set to simple, remove the ntp, codec and advanced tabs
if (isset($this->sccpvalues['displayconfig']['data']) && ($this->sccpvalues['displayconfig']['data'] == 'sccpsimple')) {
unset($this->pagedata['sccpntp'], $this->pagedata['sccpcodec'], $this->pagedata['sccpadv'] );
}
$this->processPageData();
return $this->pagedata;
}
public function infoServerShowPage() {
$request = $_REQUEST;
$action = !empty($request['action']) ? $request['action'] : '';
$this->pagedata = array(
"general" => array(
"name" => _("General SCCP Settings"),
"page" => 'views/server.info.php'
),
);
$this->processPageData();
return $this->pagedata;
}
public function advServerShowPage() {
$request = $_REQUEST;
$action = !empty($request['action']) ? $request['action'] : '';
$inputform = !empty($request['tech_hardware']) ? $request['tech_hardware'] : '';
switch ($inputform) {
case 'dialplan':
$this->pagedata = array(
"general" => array(
"name" => _("SCCP Dial Plan information"),
"page" => 'views/form.dptemplate.php'
)
);
break;
default:
$this->pagedata = array(
"general" => array(
"name" => _("SCCP Model information"),
"page" => 'views/advserver.model.php'
),
"sccpkeyset" => array(
"name" => _("SCCP Device Keyset"),
"page" => 'views/advserver.keyset.php'
)
);
if ($this->sccpvalues['siptftp']['data'] == 'on') {
$this->pagedata["sccpdialplan"] = array(
"name" => _("SIP Dial Plan information"),
"page" => 'views/advserver.dialtemplate.php'
);
}
break;
}
$this->processPageData();
return $this->pagedata;
}
public function phoneShowPage() {
$request = $_REQUEST;
$action = !empty($request['action']) ? $request['action'] : '';
$inputform = !empty($request['tech_hardware']) ? $request['tech_hardware'] : '';
switch ($inputform) {
case "cisco":
$this->pagedata = array(
"general" => array(
"name" => _("Device configuration"),
"page" => 'views/form.adddevice.php'
),
"buttons" => array(
"name" => _("Device Buttons"),
"page" => 'views/form.buttons.php'
),
"advanced" => array(
"name" => _("Device SCCP Advanced"),
"page" => 'views/form.devadvanced.php'
)
);
break;
case "cisco-sip":
$this->pagedata = array(
"general" => array(
"name" => _("Sip device configuration"),
"page" => 'views/form.addsdevice.php'
),
"buttons" => array(
"name" => _("Sip device Buttons"),
"page" => 'views/form.sbuttons.php'
)
);
break;
case "r_user":
$this->pagedata = array(
"general" => array(
"name" => _("Roaming User configuration"),
"page" => 'views/form.addruser.php'
),
"buttons" => array(
"name" => _("Device Buttons"),
"page" => 'views/form.buttons.php'
),
);
break;
default:
$this->pagedata = array(
"general" => array(
"name" => _("SCCP Extension"),
"page" => 'views/hardware.extension.php'
),
"sccpdevice" => array(
"name" => _("SCCP Phone"),
"page" => 'views/hardware.phone.php'
)
);
if ($this->sccpvalues['siptftp']['data'] == 'on') {
$this->pagedata["sipdevice"] = array(
"name" => _("SIP CISCO Phone"),
"page" => 'views/hardware.sphone.php'
);
}
break;
}
$this->processPageData();
return $this->pagedata;
}
public function processPageData() {
foreach ($this->pagedata as &$page) {
ob_start();
include($page['page']);
$page['content'] = ob_get_contents();
ob_end_clean();
}
}
/*
*
* * Save Hardware Device Information to Db + ???? Create / update XML Profile
*
*/
function getPhoneButtons($get_settings, $ref_id = '', $ref_type = 'sccpdevice') {
// get Model Buttons info
$res = array();
$def_feature = array('parkinglot' => array('name' => 'P.slot', 'value' => 'default'),
'devstate' => array('name' => 'Coffee', 'value' => 'coffee'),
'monitor' => array('name' => 'Record Calls', 'value' => '')
);
// $lines_list = $this->dbinterface->getSccpDeviceTableData('SccpExtension');
$max_btn = ((!empty($get_settings['buttonscount']) ? $get_settings['buttonscount'] : 100));
$last_btn = $max_btn;
for ($it = $max_btn; $it >= 0; $it--) {
if (!empty($get_settings['button' . $it . '_type'])) {
$last_btn = $it;
$btn_t = $get_settings['button' . $it . '_type'];
if ($btn_t != 'empty') {
break;
}
}
}
for ($it = 0; $it <= $last_btn; $it++) {
if (!empty($get_settings['button' . $it . '_type'])) {
$btn_t = $get_settings['button' . $it . '_type'];
$btn_n = '';
$btn_opt = '';
if ($it == 0) {
$btn_opt = 'default';
}
switch ($btn_t) {
case 'feature':
$btn_f = $get_settings['button' . $it . '_feature'];
// $btn_opt = (empty($get_settings['button' . $it . '_fvalue'])) ? '' : $get_settings['button' . $it . '_fvalue'];
$btn_n = (empty($get_settings['button' . $it . '_flabel'])) ? $def_feature[$btn_f]['name'] : $get_settings['button' . $it . '_flabel'];
$btn_opt = $btn_f;
if (!empty($def_feature[$btn_f]['value'])) {
if (empty($get_settings['button' . $it . '_fvalue'])) {
$btn_opt .= ',' . $def_feature[$btn_f]['value'];
} else {
$btn_opt .= ',' . $get_settings['button' . $it . '_fvalue'];
}
if ($btn_f == 'parkinglot') {
if (!empty($get_settings['button' . $it . '_retrieve'])) {
$btn_opt .= ',RetrieveSingle';
}
}
}
break;
case 'monitor':
$btn_t = 'speeddial';
$btn_opt = (string) $get_settings['button' . $it . '_line'];
$db_res = $this->dbinterface->getSccpDeviceTableData('SccpExtension', array('name' => $btn_opt));
$btn_n = $db_res[0]['label'];
$btn_opt .= ',' . $btn_opt . $this->hint_context['default'];
break;
case 'speeddial':
if (!empty($get_settings['button' . $it . '_input'])) {
$btn_n = $get_settings['button' . $it . '_input'];
}
if (!empty($get_settings['button' . $it . '_phone'])) {
$btn_opt = $get_settings['button' . $it . '_phone'];
if (empty($btn_n)) {
$btn_n = $btn_opt;
}
}
if (!empty($get_settings['button' . $it . '_hint'])) {
if ($get_settings['button' . $it . '_hint'] == "hint") {
if (empty($btn_n)) {
$btn_t = 'line';
$btn_n = $get_settings['button' . $it . '_hline'] . '!silent';
$btn_opt = '';
} else {
// $btn_opt .= ',' . $get_settings['button' . $it . '_hline'] . $this->hint_context['default'];
$btn_opt .= ',' . $get_settings['button' . $it . '_hline'];
}
}
}
break;
case 'adv.line':
$btn_t = 'line';
$btn_n = (string) $get_settings['button' . $it . '_line'];
$btn_n .= '@' . (string) $get_settings['button' . $it . '_advline'];
$btn_opt = (string) $get_settings['button' . $it . '_advopt'];
break;
case 'line':
case 'silent':
if (isset($get_settings['button' . $it . '_line'])) {
$btn_n = (string) $get_settings['button' . $it . '_line'];
if ($it > 0) {
if ($btn_t == 'silent') {
$btn_n .= '!silent';
$btn_t = 'line';
}
}
} else {
$btn_t = 'empty';
$btn_n = '';
}
break;
case 'empty':
$btn_t = 'empty';
break;
}
if (!empty($btn_t)) {
$res[] = array('ref' => $ref_id, 'reftype' => $ref_type, 'instance' => (string) ($it + 1), 'type' => $btn_t, 'name' => $btn_n, 'options' => $btn_opt);
}
}
}
return $res;
}
function saveSccpDevice($get_settings, $validateonly = false) {
$hdr_prefix = 'sccp_hw_';
$hdr_arprefix = 'sccp_hw-ar_';
$hdr_vendPrefix = 'sccp_hw_vendorconfig';
$save_buttons = array();
$save_settings = array();
$save_codec = array();
$name_dev = '';
$db_field = $this->dbinterface->getSccpDeviceTableData("get_columns_sccpdevice");
$hw_id = (empty($get_settings['sccp_deviceid'])) ? 'new' : $get_settings['sccp_deviceid'];
$hw_type = (empty($get_settings['sccp_device_typeid'])) ? 'sccpdevice' : $get_settings['sccp_device_typeid'];
$update_hw = ($hw_id == 'new') ? 'add' : 'clear'; // Possible values are delete, replace, add, clear.
$hw_prefix = 'SEP';
if (!empty($get_settings[$hdr_prefix . 'type'])) {
$value = $get_settings[$hdr_prefix . 'type'];
if (strpos($value, 'ATA') !== false) {
$hw_prefix = 'ATA';
}
if (strpos($value, 'VG') !== false) {
$hw_prefix = 'VG';
}
}
foreach ($db_field as $data) {
$key = (string) $data['Field'];
$value = "";
switch ($key) {
case 'name':
if (!empty($get_settings[$hdr_prefix . 'mac'])) {
$value = $get_settings[$hdr_prefix . 'mac'];
$value = strtoupper(str_replace(array('.', '-', ':'), '', $value)); // Delete mac separators from string
$value = sprintf("%012s", $value);
if ($hw_prefix == 'VG') {
$value = $hw_prefix . $value . '0';
} else {
$value = $hw_prefix . $value;
}
$name_dev = $value;
}
break;
case 'phonecodepage':
$value = 'null';
// TODO: getExtConfig(sccp_lang ....) does not accept any additional arguments and will return an array
if (!empty($get_settings[$hdr_prefix . 'devlang'])) {
$lang_data = $this->extconfigs->getExtConfig('sccp_lang', $get_settings[$hdr_prefix . 'devlang']);
if (!empty($lang_data)) {
$value = $lang_data['codepage'];
}
}
break;
case '_hwlang':
if (empty($get_settings[$hdr_prefix . 'netlang']) || empty($get_settings[$hdr_prefix . 'devlang'])) {
$value = 'null';
} else {
$value = $get_settings[$hdr_prefix . 'netlang'] . ':' . $get_settings[$hdr_prefix . 'devlang'];
}
break;
default:
// handle vendor prefix
if (!empty($get_settings[$hdr_vendPrefix . $key])) {
$value = $get_settings[$hdr_vendPrefix . $key];
}
// handle array prefix
if (!empty($get_settings[$hdr_arprefix . $key])) {
$arr_data = '';
$arr_clear = false;
foreach ($get_settings[$hdr_arprefix . $key] as $vkey => $vval) {
$tmp_data = '';
foreach ($vval as $vkey => $vval) {
switch ($vkey) {
case 'inherit':
if ($vval == 'on') {
$arr_clear = true;
// Злобный ХАК ?!TODO!?
if ($key == 'permit') {
$save_settings['deny'] = 'NONE';
}
}
break;
case 'internal':
if ($vval == 'on') {
$tmp_data .= 'internal;';
}
break;
default:
$tmp_data .= $vval . '/';
break;
}
}
if (strlen($tmp_data) > 2) {
while (substr($tmp_data, -1) == '/') {
$tmp_data = substr($tmp_data, 0, -1);
}
$arr_data .= $tmp_data . ';';
}
}
while (substr($arr_data, -1) == ';') {
$arr_data = substr($arr_data, 0, -1);
}
if ($arr_clear) {
$value = 'NONE';
} else {
$value = $arr_data;
}
}
// Now only have normal prefix
if (!empty($get_settings["{$hdr_prefix}{$key}"])) {
$value = $get_settings["{$hdr_prefix}{$key}"];
} else if (!empty($get_settings["sccp_hw{$key}"])) {
//have an underscore db field
$value = $get_settings["sccp_hw{$key}"];
}
}
if (!empty($value)) {
$save_settings[$key] = $value;
}
}
// Save this device.
$this->dbinterface->write('sccpdevice', $save_settings, 'replace');
// Retrieve the phone buttons and write back to
// update sccpdeviceconfig via Trigger
$save_buttons = $this->getPhoneButtons($get_settings, $name_dev, $hw_type);
$this->dbinterface->write('sccpbuttons', $save_buttons, $update_hw, '', $name_dev);
// Create new XML for this device, and then reset or restart the device
// so that it loads the file from TFT.
$this->createSccpDeviceXML($name_dev);
if ($hw_id == 'new') {
$this->aminterface->sccpDeviceReset($name_dev, 'reset');
} else {
$this->aminterface->sccpDeviceReset($name_dev, 'restart');
}
return $save_settings;
}
function handleRoamingUsers($get_settings, $validateonly = false) {
$hdr_prefix = 'sccp_ru_';
$hdr_arprefix = 'sccp_ru-ar_';
$save_buttons = array();
$save_settings = array();
$name_dev = '';
$db_field = $this->dbinterface->getSccpDeviceTableData("get_columns_sccpuser");
$hw_prefix = 'SEP';
$name_dev = $get_settings[$hdr_prefix . 'id'];
$save_buttons = $this->getPhoneButtons($get_settings, $name_dev, 'sccpline');
foreach ($db_field as $data) {
$key = (string) $data['Field'];
$value = "";
switch ($key) {
case 'name':
$value = $name_dev;
break;
case '_hwlang':
if (empty($get_settings[$hdr_prefix . 'netlang']) || empty($get_settings[$hdr_prefix . 'devlang'])) {
$value = 'null';
} else {
$value = $get_settings[$hdr_prefix . 'netlang'] . ':' . $get_settings[$hdr_prefix . 'devlang'];
}
break;
default:
if (!empty($get_settings[$hdr_prefix . $key])) {
$value = $get_settings[$hdr_prefix . $key];
}
if (!empty($get_settings[$hdr_arprefix . $key])) {
$arr_data = '';
$arr_clear = false;
foreach ($get_settings[$hdr_arprefix . $key] as $vkey => $vval) {
$tmp_data = '';
foreach ($vval as $vkey => $vval) {
switch ($vkey) {
case 'inherit':
if ($vval == 'on') {
$arr_clear = true;
// Злобный ХАК ?!TODO!?
if ($key == 'permit') {
$save_settings['deny'] = 'NONE';
}
}
break;
case 'internal':
if ($vval == 'on') {
$tmp_data .= 'internal;';
}
break;
default:
$tmp_data .= $vval . '/';
break;
}
}
if (strlen($tmp_data) > 2) {
while (substr($tmp_data, -1) == '/') {
$tmp_data = substr($tmp_data, 0, -1);
}
$arr_data .= $tmp_data . ';';
}
}
while (substr($arr_data, -1) == ';') {
$arr_data = substr($arr_data, 0, -1);
}
if ($arr_clear) {
$value = 'NONE';
} else {
$value = $arr_data;
}
}
}
if (!empty($value)) {
$save_settings[$key] = $value;
}
}
$this->dbinterface->write('sccpuser', $save_settings, 'replace', 'name');
$this->dbinterface->write('sccpbuttons', $save_buttons, 'delete', '', $name_dev); //standardise to delete
return $save_buttons;
// Why is there a second return here???????
return $save_settings;
}
public function getCodecs($type, $showDefaults = false) {
$allSupported = array();
$sccpCodec = array_fill_keys(array('alaw', 'ulaw', 'g722', 'g723', 'g726', 'g729', 'gsm', 'h264', 'h263', 'h261'),0);
// First see if have any site defaults
$val = $this->sccpvalues['allow']['data'];
if (empty($val)) {
// No site defaults so return chan-sccp defaults
$val = $this->sccpvalues['allow']['systemdefault'];
}
$siteCodecs = array_fill_keys(explode(';',$val), 1);
switch ($type) {
case 'audio':
$fpbxCodecs = $this->FreePBX->Codecs->getAudio();
break;
case 'video':
$fpbxCodecs = $this->FreePBX->Codecs->getVideo();
break;
case 'text':
$siteCodecs = $this->getConfig('textcodecs');
$fpbxCodecs = $this->FreePBX->Codecs->getText(true);
break;
case 'image':
$siteCodecs = $this->getConfig('imagecodecs');
$fpbxCodecs = $this->FreePBX->Codecs->getImage(true);
break;
}
// Below could be squashed to 1 line, but would be unreadable.
// These have value set to 1
$enabledCodecs = array_intersect_key($siteCodecs, $sccpCodec, $fpbxCodecs);
// These have value set to 0
$allSupported = array_intersect_key($sccpCodec,$fpbxCodecs);
$disabledCodecs = array_diff_key($allSupported,$enabledCodecs);
$codecs = array_merge($enabledCodecs, $disabledCodecs);
return $codecs;
}
/**
* Retrieve Active Codecs
* return finds Language pack
*/
private function findInstLangs() {
//locales and languages are installed in the tftp_lang_path
$result = array();
$langDir = '/'; //set default for when called by installer on virgin system
if (!empty($this->sccppath["tftp_lang_path"])) {
$langDir = $this->sccppath["tftp_lang_path"];
}
$localeJar = 'be-sccp.jar'; // This jar should exist if the locale is populated
$langArr = $this->extconfigs->getExtConfig('sccp_lang');
$localeArray = array_combine(array_keys($langArr),array_column($langArr, 'locale'));
foreach (array_diff(scandir($langDir),array('.', '..')) as $subDir) {
if (is_dir($langDir . DIRECTORY_SEPARATOR . $subDir)) {
$filename = $langDir . DIRECTORY_SEPARATOR . $subDir . DIRECTORY_SEPARATOR . $localeJar;
if (file_exists($filename)) {
$result = array_merge(array_intersect($localeArray,array($subDir)),$result);
}
}
}
$this->installedLangs = $result;
}
/*
* Check tftp/xml file path and permissions
*/
private function initializeTFtpLanguagePath() {
$dir = $this->sccppath["tftp_lang_path"];
foreach ($this->extconfigs->getExtConfig('sccp_lang') as $langKey => $langValueArr) {
$localeDir = $dir . DIRECTORY_SEPARATOR . $langValueArr['locale'];
if (!is_dir($localeDir)) {
if (!mkdir($localeDir, 0755, true)) {
die("Error creating $localeDir directory");
}
}
}
}
/*
* Check file paths and permissions
*/
function initializeSccpPath() {
$this->sccppath = array(
'asterisk' => $this->sccpvalues['asterisk_etc_path']['data'],
'tftp_path' => $this->sccpvalues['tftp_path']['data'],
'tftp_templates_path' => $this->sccpvalues['tftp_templates_path']['data'],
'tftp_store_path' => $this->sccpvalues['tftp_store_path']['data'],
'tftp_lang_path' => $this->sccpvalues['tftp_lang_path']['data'],
'tftp_firmware_path' => $this->sccpvalues['tftp_firmware_path']['data'],
'tftp_dialplan_path' => $this->sccpvalues['tftp_dialplan_path']['data'],
'tftp_softkey_path' => $this->sccpvalues['tftp_softkey_path']['data']
);
$read_config = $this->cnf_read->getConfig('sccp.conf');
$this->sccp_conf_init['general'] = $read_config['general'];
foreach ($read_config as $key => $value) {
if (isset($read_config[$key]['type'])) { // copy soft key
if ($read_config[$key]['type'] == 'softkeyset') {
$this->sccp_conf_init[$key] = $read_config[$key];
}
}
}
$hint = $this->aminterface->core_list_hints();
foreach ($hint as $key => $value) {
if ($this->hint_context['default'] != $value) {
$this->hint_context[$key] = $value;
}
}
}
/*
* Soft Key
*/
function createSccpXmlSoftkey() {
foreach ($this->aminterface->sccp_list_keysets() as $keyl => $vall) {
$this->xmlinterface->create_xmlSoftkeyset($this->sccp_conf_init, $this->sccppath, $keyl);
}
}
/*
* DialPlan
*/
function getDialPlanList() {
$dir = $this->sccppath["tftp_dialplan_path"] . '/dial*.xml';
$base_len = strlen($this->sccppath["tftp_dialplan_path"]) + 1;
$res = glob($dir);
foreach ($res as $key => $value) {
$res[$key] = array('id' => substr($value, $base_len, -4), 'file' => substr($value, $base_len));
}
return $res;
}
function getDialPlan($get_file) {
$file = $this->sccppath["tftp_dialplan_path"] . '/' . $get_file . '.xml';
if (file_exists($file)) {
$fileContents = file_get_contents($file);
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$fileContents = strtolower($fileContents);
$res = (array) simplexml_load_string($fileContents);
}
return $res;
}
function deleteDialPlan($get_file) {
if (!empty($get_file)) {
$file = $this->sccppath["tftp_dialplan_path"] . '/' . $get_file . '.xml';
if (file_exists($file)) {
$res = unlink($file);
}
}
return $res;
}
function saveDialPlan($get_settings) {
$confDir = $this->sccppath["tftp_dialplan_path"];
return $this->xmlinterface->saveDialPlan($confDir, $get_settings);
}
/*
* Update buttons Labels on mysql DB
*/
private function updateSccpButtons($hw_list = array()) {
$save_buttons = array();
$button_list = array();
if (!empty($hw_list)) {
foreach ($hw_list as $value) {
$button_tmp = (array)$this->dbinterface->getSccpDeviceTableData("get_sccpdevice_buttons", array('buttontype' => 'speeddial', 'id' => $value['name']));
$button_list = array_merge($button_list, $button_tmp);
}
} else {
$button_list = $this->dbinterface->getSccpDeviceTableData("get_sccpdevice_buttons", array('buttontype' => 'speeddial'));
}
if (empty($button_list)) {
return array('Response' => ' 0 buttons found ', 'data' => '');
}
$copy_fld = array('ref', 'reftype', 'instance', 'buttontype');
$extList = $extList = $this->dbinterface->get_db_SccpTableByID("SccpExtension", array(), 'name');
foreach ($button_list as $value) {
$btn_opt = explode(',', $value['options']);
$btn_id = $btn_opt[0];
if (!empty($extList[$btn_id])) {
if ($extList[$btn_id]['label'] != $value['name']) {
$btn_data['name'] = $extList[$btn_id]['label'];
foreach ($copy_fld as $ckey) {
$btn_data[$ckey] = $value[$ckey];
}
$save_buttons[] = $btn_data;
}
}
}
if (empty($save_buttons)) {
return array('Response' => 'No update required', 'data' => ' 0 - records ');
}
$res = $this->dbinterface->write('sccpbuttons', $save_buttons, 'replace', '', '');
return array('Response' => 'Update records :' . count($save_buttons), 'data' => $res);
}
/*
* Save Config Value to mysql DB
*/
private function saveSccpSettings($save_value = array()) {
if (empty($save_value)) {
$this->dbinterface->write('sccpsettings', $this->sccpvalues, 'replace'); //Change to replace as clearer
} else {
$this->dbinterface->write('sccpsettings', $save_value, 'update');
}
return true;
}
/*
* Create XMLDefault.cnf.xml
*/
function createDefaultSccpXml() {
$data_value = array();
foreach ($this->sccpvalues as $key => $value) {
$data_value[$key] = $value['data'];
}
$data_value['server_if_list'] = $this->getIpInformation('ip4');
$model_information = $this->getSccpModelInformation($get = "enabled", $validate = false); // Get Active
if (empty($model_information)) {
$model_information = $this->getSccpModelInformation($get = "all", $validate = false); // Get All
}
$lang_data = $this->extconfigs->getExtConfig('sccp_lang');
$data_value['tftp_path'] = $this->sccppath["tftp_path"];
$this->xmlinterface->create_default_XML($this->sccppath["tftp_store_path"], $data_value, $model_information, $lang_data);
}
/*
* Create (SEP) dev_ID.cnf.xml
*/
function createSccpDeviceXML($dev_id = '') {
if (empty($dev_id)) {
return false;
}
$sccp_native = true;
$data_value = array();
$dev_line_data = null;
$dev_config = $this->dbinterface->getSccpDeviceTableData("get_sccpdevice_byid", array('id' => $dev_id));
// Support Cisco Sip Device
if (!empty($dev_config['type'])) {
if (strpos($dev_config['type'], 'sip') !== false) {
$sccp_native = false;
$tmp_bind = $this->sipconfigs->getSipConfig();
$dev_ext_config = $this->dbinterface->getSccpDeviceTableData("SccpDevice", array('name' => $dev_id, 'fields' => 'sip_ext'));
$data_value = array_merge($data_value, $dev_ext_config);
$data_tmp = explode(';', $dev_ext_config['sip_lines']);
$data_value['sbind'] = array();
foreach ($data_tmp as $value) {
$tmp_line = explode(',', $value);
switch ($tmp_line[0]) {
case 'line':
$dev_line_data = $this->sipconfigs->get_db_sip_TableData('DeviceById', array('id' => $tmp_line[1]));
$f_linetype = ($dev_line_data['dial'] == 'PJSIP') ? 'pjsip' : 'sip';
$dev_line_data['sbind'] = $tmp_bind[$f_linetype];
if ((!$this->array_key_exists_recursive('udp', $tmp_bind[$f_linetype])) && (!$this->array_key_exists_recursive('tcp', $tmp_bind[$f_linetype]))) {
print_r("Wrong sip server Config ! Not enabled UDP or TCP protocol");
die();
return -1;
}
if (!empty($dev_line_data)) {
$data_value['siplines'][] = $dev_line_data;
}
if ($tmp_line[2] == 'default') {
$data_value['sbind'] = $tmp_bind[$f_linetype];
}
break;
case 'speeddial':
$data_value['speeddial'][] = array("name" => $tmp_line[1], "dial" => $tmp_line[2]);
break;
default:
$data_value['sipfunctions'][] = $tmp_line;
break;
}
}
}
}
foreach ($this->sccpvalues as $key => $value) {
$data_value[$key] = $value['data'];
}
//Get Cisco Code only Old Device
$data_value['ntp_timezone_id'] = $this->extconfigs->getExtConfig('sccp_timezone', $data_value['ntp_timezone']); // Old Cisco Device
// $data_value['ntp_timezone_id'] = $data_value['ntp_timezone']; // New Cisco Device !
// $data_value['ntp_timezone_id'] = // SPA Cisco Device !
$data_value['server_if_list'] = $this->getIpInformation('ip4');
$dev_config = array_merge($dev_config, $this->sccppath);
$dev_config['tftp_firmware'] = '';
$dev_config['addon_info'] = array();
if (!empty($dev_config['addon'])) {
$hw_addon = explode(',', $dev_config['addon']);
foreach ($hw_addon as $key) {
$hw_data = $this->getSccpModelInformation('byid', false, "all", array('model' => $key));
$dev_config['addon_info'][$key] = $hw_data[0]['loadimage'];
}
}
$lang_data = $this->extconfigs->getExtConfig('sccp_lang');
if (!$sccp_native) {
return $this->xmlinterface->create_SEP_SIP_XML($this->sccppath["tftp_store_path"], $data_value, $dev_config, $dev_id, $lang_data);
}
return $this->xmlinterface->create_SEP_XML($this->sccppath["tftp_templates_path"], $data_value, $dev_config, $dev_id, $lang_data);
}
function deleteSccpDeviceXML($dev_id = '') {
if (empty($dev_id)) {
return false;
}
if ($dev_id == 'all') {
$xml_name = $this->sccppath["tftp_store_path"] . '/SEP*.cnf.xml';
array_map("unlink", glob($xml_name));
$xml_name = $this->sccppath["tftp_store_path"] . '/ATA*.cnf.xml';
array_map("unlink", glob($xml_name));
$xml_name = $this->sccppath["tftp_store_path"] . '/VG*.cnf.xml';
array_map("unlink", glob($xml_name));
} else {
if (!strpos($dev_id, 'SEP')) {
return false;
}
$xml_name = $this->sccppath["tftp_store_path"] . '/' . $dev_id . '.cnf.xml';
if (file_exists($xml_name)) {
unlink($xml_name);
}
}
}
private function createSccpBackup() {
global $amp_conf;
$dir_info = array();
$backup_files = array($amp_conf['ASTETCDIR'] . '/sccp', $amp_conf['ASTETCDIR'] . '/extensions', $amp_conf['ASTETCDIR'] . '/extconfig',
$amp_conf['ASTETCDIR'] . '/res_config_mysql', $amp_conf['ASTETCDIR'] . '/res_mysql');
$backup_ext = array('.conf', '_additional.conf', '_custom.conf');
$backup_info = $this->sccppath["tftp_path"] . '/sccp_dir.info';
$result = $this->dbinterface->dump_sccp_tables($this->sccppath["tftp_path"], $amp_conf['AMPDBNAME'], $amp_conf['AMPDBUSER'], $amp_conf['AMPDBPASS']);
$dir_info['asterisk'] = $this->findAllFiles($amp_conf['ASTETCDIR']);
$dir_info['tftpdir'] = $this->findAllFiles($this->sccppath["tftp_path"]);
$dir_info['driver'] = $this->FreePBX->Core->getAllDriversInfo();
$dir_info['core'] = $this->aminterface->getSCCPVersion();
$dir_info['realtime'] = $this->aminterface->getRealTimeStatus();
$dir_info['extconfigs'] = $this->extconfigs->info();
$dir_info['dbinterface'] = $this->dbinterface->info();
$dir_info['XML'] = $this->xmlinterface->info();
$fh = fopen($backup_info, 'w');
$dir_str = "Begin JSON data ------------\r\n";
fwrite($fh, $dir_str);
fwrite($fh, json_encode($dir_info));
$dir_str = "\r\n\r\nBegin TEXT data ------------\r\n";
foreach ($dir_info['asterisk'] as $data) {
$dir_str .= $data . "\r\n";
}
foreach ($dir_info['tftpdir'] as $data) {
$dir_str .= $data . "\r\n";
}
fputs($fh, $dir_str);
fclose($fh);
$zip = new \ZipArchive();
$filename = $result . "." . gethostname() . ".zip";
if ($zip->open($filename, \ZIPARCHIVE::CREATE)) {
$zip->addFile($result);
$zip->addFile($backup_info);
foreach ($backup_files as $file) {
foreach ($backup_ext as $b_ext) {
if (file_exists($file . $b_ext)) {
$zip->addFile($file . $b_ext);
}
}
}
$zip->close();
}
unlink($backup_info);
unlink($result);
return $filename;
}
function createDefaultSccpConfig() {
// Make sccp.conf data
// [general]
foreach ($this->sccpvalues as $key => $value) {
if ($value['seq'] == 0) {
switch ($key) {
case "allow":
case "disallow":
case "deny":
$this->sccp_conf_init['general'][$key] = explode(';', $value['data']);
break;
case "localnet":
case "permit":
$content = $value['data'];
if (strpos($content, 'internal') !== false) {
$content = str_replace(';0.0.0.0/0.0.0.0', '', $value['data']);
}
$this->sccp_conf_init['general'][$key] = explode(';', $content);
break;
case "devlang":
$lang_data = $this->extconfigs->getExtConfig('sccp_lang', $value['data']);
if (!empty($lang_data)) {
// TODO: getExtConfig(sccp_lang ....) does not accept any additional arguments and will return an array
// TODO: will always get here, but lang_data['codepage'] will be empty as not a valid key
$this->sccp_conf_init['general']['phonecodepage'] = $lang_data['codepage'];
}
break;
case "netlang": // Remove Key
case "tftp_path":
case "sccp_compatible": // This is equal to SccpDBmodel
break;
default:
if (!empty($value['data'])) {
$this->sccp_conf_init['general'][$key] = $value['data'];
}
}
}
}
// [Namesoftkeyset]
// type=softkeyset
//
// ----- It is a very bad idea to add an external configuration file "sccp_custom.conf" !!!!
// This will add problems when solving problems caused by unexpected solutions from users.
//
if (file_exists($this->sccppath["asterisk"] . "/sccp_custom.conf")) {
$this->sccp_conf_init['HEADER'] = array(
"; ;",
"; It is a very bad idea to add an external configuration file !!!! ;",
"; This will add problems when solving problems caused by unexpected solutions ;",
"; from users. ;",
";--------------------------------------------------------------------------------;",
"#include sccp_custom.conf"
);
}
// ----- It is a very bad idea to add an external configuration file "sccp_custom.conf" !!!!
// TODO: Should only rewrite the general section - if users have extensions, this may overwrite
// Should read first and then rewrite all existing sections.
$this->cnf_wr->writeConfig('sccp.conf', $this->sccp_conf_init);
}
function getSccpModelInformation($get = "all", $validate = false, $format_list = "all", $filter = array()) {
// $file_ext = array('.loads', '.LOADS', '.sbn', '.SBN', '.bin', '.BIN','.zup','.ZUP');
$file_ext = array('.loads', '.sbn', '.bin', '.zup');
// $dir = $this->sccppath["tftp_path"];
$dir = $this->sccppath['tftp_firmware_path'];
$dir_tepl = $this->sccppath['tftp_templates_path'];
$search_mode = '';
if (!empty($this->sccpvalues['tftp_rewrite'])) {
$search_mode = $this->sccpvalues['tftp_rewrite']['data'];
switch ($search_mode) {
case 'pro':
case 'on':
case 'internal':
$dir_list = $this->findAllFiles($dir, $file_ext, 'fileonly');
break;
case 'off':
default: // Place in root TFTP dir
$dir_list = $this->findAllFiles($dir, $file_ext);
break;
}
} else {
$dir_list = $this->findAllFiles($dir, $file_ext, 'fileonly');
}
$raw_settings = $this->dbinterface->getDb_model_info($get, $format_list, $filter);
if ($validate) {
for ($i = 0; $i < count($raw_settings); $i++) {
$raw_settings[$i]['validate'] = '-;-';
if (!empty($raw_settings[$i]['loadimage'])) {
$raw_settings[$i]['validate'] = 'no;';
if (((strtolower($raw_settings[$i]['vendor']) == 'cisco') || (strtolower($raw_settings[$i]['vendor']) == 'cisco-sip')) && !empty($dir_list)) {
foreach ($dir_list as $filek) {
switch ($search_mode) {
case 'pro':
case 'on':
case 'internal':
if (strpos(strtolower($filek), strtolower($raw_settings[$i]['loadimage'])) !== false) {
$raw_settings[$i]['validate'] = 'yes;';
}
break;
case 'internal2':
break;
case 'off':
default: // Place in root TFTP dir
if (strpos(strtolower($filek), strtolower($dir . '/' . $raw_settings[$i]['loadimage'])) !== false) {
$raw_settings[$i]['validate'] = 'yes;';
}
break;
}
}
}
} else {
$raw_settings[$i]['validate'] = '-;';
}
if (!empty($raw_settings[$i]['nametemplate'])) {
$file = $dir_tepl . '/' . $raw_settings[$i]['nametemplate'];
if (file_exists($file)) {
$raw_settings[$i]['validate'] .= 'yes';
} else {
$raw_settings[$i]['validate'] .= 'no';
}
} else {
$raw_settings[$i]['validate'] .= '-';
}
}
}
return $raw_settings;
}
function getHintInformation($sort = true, $filter = array()) {
$res = array();
$default_hint = '@ext-local';
if (empty($res)) {
// Old Req get all hints
$tmp_data = $this->aminterface->core_list_all_hints();
foreach ($tmp_data as $value) {
$res[$value] = array('key' => $value, 'exten' => $this->before('@', $value), 'label' => $value);
}
}
// Update info from sccp_db
$tmp_data = $this->dbinterface->getSccpDeviceTableData('SccpExtension');
foreach ($tmp_data as $value) {
$name_l = $value['name'];
if (!empty($res[$name_l . $default_hint])) {
$res[$name_l . $default_hint]['exten'] = $name_l;
$res[$name_l . $default_hint]['label'] = $value['label'];
} else {
// if not exist in system hints ..... ???????
$res[$name_l . $default_hint] = array('key' => $name_l . $default_hint, 'exten' => $name_l, 'label' => $value['label']);
}
}
if (!$sort) {
return $res;
}
foreach ($res as $key => $value) {
$data_sort[$value['exten']] = $key;
}
ksort($data_sort);
foreach ($data_sort as $key => $value) {
$res_sort[$value] = $res[$value];
}
// Update info from sip DB
/* !TODO!: Update Hint info from sip DB ??? */
return $res_sort;
}
}
?>