#9771 moved discovery to open

This commit is contained in:
Daniel Cebrian 2023-06-14 11:09:08 +02:00
parent 3583c81fb9
commit 308879fe05
15 changed files with 4834 additions and 9 deletions

View File

@ -30,6 +30,7 @@
// Begin.
require_once 'include/config.php';
require_once 'include/functions_menu.php';
require_once $config['homedir'].'/godmode/wizards/ManageExtensions.class.php';
check_login();
@ -78,10 +79,91 @@ if ((bool) check_acl($config['id_user'], 0, 'AR') === true
}
if ((bool) check_acl($config['id_user'], 0, 'AW') === true) {
enterprise_hook('applications_menu');
enterprise_hook('cloud_menu');
enterprise_hook('custom_menu');
enterprise_hook('manage_extensions_menu');
// Applications.
$sub2 = [];
if (enterprise_installed() === true) {
$sub2['godmode/servers/discovery&wiz=app&mode=MicrosoftSQLServer']['text'] = __('Microsoft SQL Server');
$sub2['godmode/servers/discovery&wiz=app&mode=mysql']['text'] = __('Mysql');
$sub2['godmode/servers/discovery&wiz=app&mode=oracle']['text'] = __('Oracle');
$sub2['godmode/servers/discovery&wiz=app&mode=vmware']['text'] = __('VMware');
$sub2['godmode/servers/discovery&wiz=app&mode=SAP']['text'] = __('SAP');
$sub2['godmode/servers/discovery&wiz=app&mode=DB2']['text'] = __('DB2');
}
$extensions = ManageExtensions::getExtensionBySection('app');
if ($extensions !== false) {
foreach ($extensions as $key => $extension) {
$url = sprintf(
'godmode/servers/discovery&wiz=app&mode=%s',
$extension['short_name']
);
$sub2[$url]['text'] = __($extension['name']);
}
}
if ($extensions !== false || enterprise_installed() === true) {
$sub['godmode/servers/discovery&wiz=app']['text'] = __('Applications');
$sub['godmode/servers/discovery&wiz=app']['id'] = 'app';
$sub['godmode/servers/discovery&wiz=app']['type'] = 'direct';
$sub['godmode/servers/discovery&wiz=app']['subtype'] = 'nolink';
$sub['godmode/servers/discovery&wiz=app']['sub2'] = $sub2;
}
// Cloud.
$sub2 = [];
if (enterprise_installed() === true) {
$sub2['godmode/servers/discovery&wiz=cloud&mode=amazonws']['text'] = __('Amazon Web Services');
$sub2['godmode/servers/discovery&wiz=cloud&mode=azure']['text'] = __('Microsoft Azure');
$sub2['godmode/servers/discovery&wiz=cloud&mode=gcp']['text'] = __('Google Compute Platform');
}
$extensions = ManageExtensions::getExtensionBySection('cloud');
if ($extensions !== false) {
foreach ($extensions as $key => $extension) {
$url = sprintf(
'godmode/servers/discovery&wiz=cloud&mode=%s',
$extension['short_name']
);
$sub2[$url]['text'] = __($extension['name']);
}
}
if ($extensions !== false || enterprise_installed() === true) {
$sub['godmode/servers/discovery&wiz=cloud']['text'] = __('Cloud');
$sub['godmode/servers/discovery&wiz=cloud']['id'] = 'cloud';
$sub['godmode/servers/discovery&wiz=cloud']['type'] = 'direct';
$sub['godmode/servers/discovery&wiz=cloud']['subtype'] = 'nolink';
$sub['godmode/servers/discovery&wiz=cloud']['sub2'] = $sub2;
}
// Custom.
$sub2 = [];
$extensions = ManageExtensions::getExtensionBySection('custom');
if ($extensions !== false) {
foreach ($extensions as $key => $extension) {
$url = sprintf(
'godmode/servers/discovery&wiz=custom&mode=%s',
$extension['short_name']
);
$sub2[$url]['text'] = __($extension['name']);
}
$sub['godmode/servers/discovery&wiz=custom']['text'] = __('Custom');
$sub['godmode/servers/discovery&wiz=custom']['id'] = 'customExt';
$sub['godmode/servers/discovery&wiz=custom']['type'] = 'direct';
$sub['godmode/servers/discovery&wiz=custom']['subtype'] = 'nolink';
$sub['godmode/servers/discovery&wiz=custom']['sub2'] = $sub2;
}
if (check_acl($config['id_user'], 0, 'RW')
|| check_acl($config['id_user'], 0, 'RM')
|| check_acl($config['id_user'], 0, 'PM')
) {
$sub['godmode/servers/discovery&wiz=magextensions']['text'] = __('Manage extensions');
$sub['godmode/servers/discovery&wiz=magextensions']['id'] = 'mextensions';
}
enterprise_hook('console_task_menu');
}
}

View File

@ -0,0 +1,221 @@
<?php
/**
* Applications wizard manager.
*
* @category Wizard
* @package Pandora FMS
* @subpackage Applications
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2021 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
require_once $config['homedir'].'/include/functions_users.php';
require_once $config['homedir'].'/include/class/ExtensionsDiscovery.class.php';
/**
* Implements Wizard to provide generic Applications wizard.
*/
class Applications extends Wizard
{
/**
* Sub-wizard to be launch (vmware,oracle...).
*
* @var string
*/
public $mode;
/**
* Constructor.
*
* @param integer $page Start page, by default 0.
* @param string $msg Default message to show to users.
* @param string $icon Target icon to be used.
* @param string $label Target label to be displayed.
*
* @return mixed
*/
public function __construct(
int $page=0,
string $msg='Default message. Not set.',
string $icon='images/wizard/applications.png',
string $label='Applications'
) {
$this->setBreadcrum([]);
$this->access = 'AW';
$this->task = [];
$this->msg = $msg;
$this->icon = $icon;
$this->class = $class_style;
$this->label = $label;
$this->page = $page;
$this->url = ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=app'
);
return $this;
}
/**
* Run wizard manager.
*
* @return mixed Returns null if wizard is ongoing. Result if done.
*/
public function run()
{
global $config;
// Load styles.
parent::run();
// Load current wiz. sub-styles.
ui_require_css_file(
'application',
ENTERPRISE_DIR.'/include/styles/wizards/'
);
$mode = get_parameter('mode', null);
// Load application wizards.
$enterprise_classes = glob(
$config['homedir'].'/'.ENTERPRISE_DIR.'/include/class/*.app.php'
);
$extensions = new ExtensionsDiscovery('app', $mode);
foreach ($enterprise_classes as $classpath) {
enterprise_include_once(
'include/class/'.basename($classpath)
);
}
switch ($mode) {
case 'DB2':
$classname_selected = 'DB2';
break;
case 'SAP':
$classname_selected = 'SAP';
break;
case 'vmware':
$classname_selected = 'VMware';
break;
case 'mysql':
$classname_selected = 'MySQL';
break;
case 'oracle':
$classname_selected = 'Oracle';
break;
case 'MicrosoftSQLServer':
$classname_selected = 'MicrosoftSQLServer';
break;
default:
$classname_selected = null;
break;
}
// Else: class not found pseudo exception.
if ($classname_selected !== null) {
$wiz = new $classname_selected($this->page);
$result = $wiz->run();
if (is_array($result) === true) {
return $result;
}
}
if ($classname_selected === null) {
if ($mode !== null) {
// Load extension if exist.
$extensions->run();
return;
}
// Load classes and print selector.
$wiz_data = [];
foreach ($enterprise_classes as $classpath) {
$classname = basename($classpath, '.app.php');
$obj = new $classname();
$wiz_data[] = $obj->load();
}
$wiz_data = array_merge($wiz_data, $extensions->loadExtensions());
$this->prepareBreadcrum(
[
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery'
),
'label' => __('Discovery'),
],
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=app'
),
'label' => __('Applications'),
'selected' => true,
],
]
);
// Header.
ui_print_page_header(
__('Applications'),
'',
false,
'',
true,
'',
false,
'',
GENERIC_SIZE_TEXT,
'',
$this->printHeader(true)
);
Wizard::printBigButtonsList($wiz_data);
echo '<div class="app_mssg"><i>*'.__('All company names used here are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.').'</i></div>';
}
return $result;
}
/**
* Check if section have extensions.
*
* @return boolean Return true if section is empty.
*/
public function isEmpty()
{
$extensions = new ExtensionsDiscovery('app');
$listExtensions = $extensions->getExtensionsApps();
if ($listExtensions > 0 || enterprise_installed() === true) {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,661 @@
<?php
/**
* Cloud wizard manager.
*
* @category Wizard
* @package Pandora FMS
* @subpackage Cloud
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2021 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
global $config;
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
require_once $config['homedir'].'/include/functions_users.php';
require_once $config['homedir'].'/include/class/CredentialStore.class.php';
/**
* Implements Wizard to provide generic Cloud wizard.
*/
class Cloud extends Wizard
{
/**
* Sub-wizard to be launch (vmware,oracle...).
*
* @var string
*/
public $mode;
/**
* Discovery task data.
*
* @var array.
*/
public $task;
/**
* General maxPages.
*
* @var integer
*/
public $maxPages;
/**
* Product string.
*
* @var string
*/
protected $product = '';
/**
* Credentials store identifier.
*
* @var string
*/
protected $keyIdentifier = null;
/**
* Credentials store product identifier.
*
* @var string
*/
protected $keyStoreType = null;
/**
* Constructor.
*
* @param integer $page Start page, by default 0.
* @param string $msg Default message to show to users.
* @param string $icon Target icon to be used.
* @param string $label Target label to be displayed.
*
* @return mixed
*/
public function __construct(
int $page=0,
string $msg='Default message. Not set.',
string $icon='images/wizard/cloud.png',
string $label='Cloud'
) {
$this->setBreadcrum([]);
$this->access = 'AW';
$this->task = [];
$this->msg = $msg;
$this->icon = $icon;
$this->label = $label;
$this->page = $page;
$this->url = ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=cloud'
);
return $this;
}
/**
* Run wizard manager.
*
* @return mixed Returns null if wizard is ongoing. Result if done.
*/
public function run()
{
global $config;
// Load styles.
parent::run();
// Load current wiz. sub-styles.
ui_require_css_file(
'cloud',
ENTERPRISE_DIR.'/include/styles/wizards/'
);
$mode = get_parameter('mode', null);
// Load cloud wizards.
$enterprise_classes = glob(
$config['homedir'].'/'.ENTERPRISE_DIR.'/include/class/*.cloud.php'
);
$extensions = new ExtensionsDiscovery('cloud', $mode);
foreach ($enterprise_classes as $classpath) {
enterprise_include_once(
'include/class/'.basename($classpath)
);
}
switch ($mode) {
case 'amazonws':
$classname_selected = 'Aws';
break;
case 'azure':
$classname_selected = 'Azure';
break;
case 'gcp':
$classname_selected = 'Google';
break;
default:
$classname_selected = null;
break;
}
// Else: class not found pseudo exception.
if ($classname_selected !== null) {
$wiz = new $classname_selected($this->page);
$result = $wiz->run();
if (is_array($result) === true) {
return $result;
}
}
if ($classname_selected === null) {
if ($mode !== null) {
// Load extension if exist.
$extensions->run();
return;
}
// Load classes and print selector.
$wiz_data = [];
foreach ($enterprise_classes as $classpath) {
$classname = basename($classpath, '.cloud.php');
$obj = new $classname();
$wiz_data[] = $obj->load();
}
$wiz_data = array_merge($wiz_data, $extensions->loadExtensions());
$this->prepareBreadcrum(
[
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery'
),
'label' => __('Discovery'),
],
[
'link' => $this->url,
'label' => __('Cloud'),
'selected' => true,
],
],
true
);
// Header.
ui_print_page_header(
__('Cloud'),
'',
false,
'',
true,
'',
false,
'',
GENERIC_SIZE_TEXT,
'',
$this->printHeader(true)
);
Wizard::printBigButtonsList($wiz_data);
echo '<div class="app_mssg"><i>*'.__('All company names used here are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.').'</i></div>';
}
return $result;
}
/**
* Run credentials wizard.
*
* @return boolean True if credentials wizard is displayed and false if not.
*/
public function runCredentials()
{
global $config;
if ($this->status === false) {
$empty_account = true;
}
// Checks credentials. If check not passed. Show the form to fill it.
if ($this->checkCredentials()) {
return true;
}
// Add breadcrum and print header.
$this->prepareBreadcrum(
[
[
'link' => $this->url.'&credentials=1',
'label' => __('%s credentials', $this->product),
'selected' => true,
],
],
true
);
// Header.
ui_print_page_header(
__('%s credentials', $this->product),
'',
false,
$this->product.'_credentials_tab',
true,
'',
false,
'',
GENERIC_SIZE_TEXT,
'',
$this->printHeader(true)
);
if ($this->product === 'Aws') {
ui_print_warning_message(
__(
'If a task with the selected credentials is already running, it will be edited. To create a new one, another account from the credential store must be selected.'
)
);
}
if ($this->status === true) {
ui_print_success_message($this->msg);
} else if ($this->status === false) {
ui_print_error_message($this->msg);
}
if ($empty_account === true) {
ui_print_error_message($this->msg);
}
$link_to_cs = '';
if (check_acl($config['id_user'], 0, 'UM')) {
$link_to_cs = '<a class="ext_link" href="'.ui_get_full_url(
'index.php?sec=gmodules&sec2=godmode/groups/group_list&tab=credbox'
).'" >';
$link_to_cs .= __('Manage accounts').'</a>';
}
$this->getCredentials();
$this->printFormAsList(
[
'form' => [
'action' => $this->url,
'method' => 'POST',
'id' => 'form-credentials',
],
'inputs' => [
[
'label' => __('Cloud tool full path'),
'arguments' => [
'name' => 'cloud_util_path',
'value' => isset($config['cloud_util_path']) ? io_safe_output($config['cloud_util_path']) : '/usr/bin/pandora-cm-api',
'type' => 'text',
],
],
[
'label' => __('Account'),
'extra' => $link_to_cs,
'arguments' => [
'name' => 'account_identifier',
'type' => 'select',
'fields' => CredentialStore::getKeys($this->keyStoreType),
'selected' => $this->keyIdentifier,
'return' => true,
],
],
[
'arguments' => [
'name' => 'parse_credentials',
'value' => 1,
'type' => 'hidden',
'return' => true,
],
],
],
]
);
$buttons_form = $this->printInput(
[
'name' => 'submit',
'label' => __('Validate'),
'type' => 'submit',
'attributes' => [
'icon' => 'wand',
'form' => 'form-credentials',
],
'return' => true,
'width' => 'initial',
]
);
$buttons_form .= $this->printGoBackButton(
ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=cloud'
),
true
);
html_print_action_buttons($buttons_form);
return false;
}
/**
* Check credentials.
*
* @return boolean True if credentials are OK.
*/
public function checkCredentials()
{
global $config;
$pandora = io_safe_output($config['cloud_util_path']);
if (isset($pandora) === false) {
config_update_value('cloud_util_path', '/usr/bin/pandora-cm-api');
}
if ((bool) get_parameter('disconnect_account', false) === true) {
$this->status = null;
return false;
}
if ($this->keyIdentifier === null) {
// Ask user for available credentials.
$this->msg = __('Select a set of credentials from the list');
$this->status = null;
return false;
}
$credentials = $this->getCredentials($this->keyIdentifier);
if (empty($credentials['username']) === true
|| empty($credentials['password']) === true
|| isset($pandora) === false
|| is_executable($pandora) === false
) {
if (is_executable($pandora) === false) {
$this->msg = (__('Path %s is not executable.', $pandora));
$this->status = false;
} else {
$this->msg = __('Invalid username or password');
$this->status = false;
}
return false;
}
try {
$value = $this->executeCMCommand('--get availability');
} catch (Exception $e) {
$this->msg = $e->getMessage();
$this->status = false;
return false;
}
if ($value == '1') {
return true;
}
$this->status = false;
// Error message directly from pandora-cm-api.
$this->msg = str_replace('"', '', $value);
return false;
}
/**
* Handle the click on disconnect account link.
*
* @return void But it prints some info to user.
*/
protected function parseDisconnectAccount()
{
// Check if disconection account link is pressed.
if ((bool) get_parameter('disconnect_account') === false) {
return;
}
$ret = $this->setCredentials(null);
if ($ret) {
$this->msg = __('Account disconnected');
} else {
$this->msg = __('Failed disconnecting account');
}
$this->status = $ret;
$this->page = 0;
}
/**
* Build an array with Product credentials.
*
* @return array with credentials (pass and id).
*/
public function getCredentials()
{
return CredentialStore::getKey($this->keyIdentifier);
}
/**
* Set Product credentials.
*
* @param string|null $identifier Credential store identifier.
*
* @return boolean True if success.
*/
public function setCredentials($identifier)
{
if ($identifier === null) {
unset($this->keyIdentifier);
return true;
}
if (isset($identifier) === false) {
return false;
}
$all = CredentialStore::getKeys($this->type);
if (in_array($identifier, $all) === true) {
$this->keyIdentifier = $identifier;
return true;
}
return false;
}
/**
* Parse credentials form.
*
* @return void But it prints a message.
*/
protected function parseCredentials()
{
global $config;
if (!$this->keyIdentifier) {
$this->setCredentials(get_parameter('ki', null));
}
// Check if credentials form is submitted.
if ((bool) get_parameter('parse_credentials') === false) {
return;
}
$this->page = 0;
$ret = $this->setCredentials(
get_parameter('account_identifier')
);
$path = get_parameter('cloud_util_path');
$ret_path = config_update_value('cloud_util_path', $path);
if ($ret_path) {
$config['cloud_util_path'] = $path;
}
if ($ret && $ret_path) {
$this->msg = __('Credentials successfully updated');
} else {
$this->msg = __('Failed updating credentials process');
}
$this->status = ($ret && $ret_path);
}
/**
* This method must be implemented.
*
* Execute a pandora-cm-api request.
*
* @param string $command Command to execute.
*
* @return void But must return string STDOUT of executed command.
* @throws Exception If not implemented.
*/
protected function executeCMCommand($command)
{
throw new Exception('executeCMCommand must be implemented.');
}
/**
* Get a recon token value
*
* @param string $token The recon key to retrieve.
*
* @return string String with the value.
*/
protected function getConfigReconElement($token)
{
if ($this->reconConfig === false
|| isset($this->reconConfig[0][$token]) === false
) {
if (is_array($this->task) === true
&& isset($this->task[$token]) === true
) {
return $this->task[$token];
} else {
return '';
}
} else {
return $this->reconConfig[0][$token];
}
}
/**
* Print global inputs
*
* @param boolean $last True if is last element.
*
* @return array Array with all global inputs.
*/
protected function getGlobalInputs(bool $last=false)
{
$task_id = $this->task['id_rt'];
if (!$task_id) {
$task_id = $this->getConfigReconElement('id_rt');
}
return [
[
'arguments' => [
'name' => 'page',
'value' => ($this->page + 1),
'type' => 'hidden',
'return' => true,
],
],
[
'arguments' => [
'name' => 'submit',
'label' => ($last) ? __('Finish') : __('Next'),
'type' => 'submit',
'attributes' => 'class="sub '.(($last) ? 'wand' : 'next').'"',
'return' => true,
],
],
[
'arguments' => [
'name' => 'task',
'value' => $task_id,
'type' => 'hidden',
'return' => true,
],
],
[
'arguments' => [
'name' => 'parse_form',
'value' => 1,
'type' => 'hidden',
'return' => true,
],
],
];
}
/**
* Print required css in some points.
*
* @return string With js code.
*/
protected function cloudJS()
{
return '
function toggleCloudSubmenu(curr_elem, id_csm){
if (document.getElementsByName(curr_elem)[0].checked){
$("#li-"+id_csm).show();
} else {
$("#li-"+id_csm).hide();
}
};
';
}
/**
* Check if section have extensions.
*
* @return boolean Return true if section is empty.
*/
public function isEmpty()
{
$extensions = new ExtensionsDiscovery('cloud');
$listExtensions = $extensions->getExtensionsApps();
if ($listExtensions > 0 || enterprise_installed() === true) {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,160 @@
<?php
/**
* Custom wizard manager.
*
* @category Wizard
* @package Pandora FMS
* @subpackage Custom
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2021 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
require_once $config['homedir'].'/include/functions_users.php';
require_once $config['homedir'].'/include/class/ExtensionsDiscovery.class.php';
/**
* Implements Wizard to provide generic Custom wizard.
*/
class Custom extends Wizard
{
/**
* Sub-wizard to be launch (vmware,oracle...).
*
* @var string
*/
public $mode;
/**
* Constructor.
*
* @param integer $page Start page, by default 0.
* @param string $msg Default message to show to users.
* @param string $icon Target icon to be used.
* @param string $label Target label to be displayed.
*
* @return mixed
*/
public function __construct(
int $page=0,
string $msg='Default message. Not set.',
string $icon='/images/wizard/Custom_apps@svg.svg',
string $label='Custom'
) {
$this->setBreadcrum([]);
$this->access = 'AW';
$this->task = [];
$this->msg = $msg;
$this->icon = $icon;
$this->class = $class_style;
$this->label = $label;
$this->page = $page;
$this->url = ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=custom'
);
return $this;
}
/**
* Run wizard manager.
*
* @return mixed Returns null if wizard is ongoing. Result if done.
*/
public function run()
{
global $config;
// Load styles.
parent::run();
// Load current wiz. sub-styles.
ui_require_css_file(
'custom',
ENTERPRISE_DIR.'/include/styles/wizards/'
);
$mode = get_parameter('mode', null);
$extensions = new ExtensionsDiscovery('custom', $mode);
if ($mode !== null) {
// Load extension if exist.
$extensions->run();
return;
}
// Load classes and print selector.
$wiz_data = $extensions->loadExtensions();
$this->prepareBreadcrum(
[
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery'
),
'label' => __('Discovery'),
],
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=custom'
),
'label' => __('Custom'),
'selected' => true,
],
]
);
// Header.
ui_print_page_header(
__('Custom'),
'',
false,
'',
true,
'',
false,
'',
GENERIC_SIZE_TEXT,
'',
$this->printHeader(true)
);
Wizard::printBigButtonsList($wiz_data);
echo '<div class="app_mssg"><i>*'.__('All company names used here are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.').'</i></div>';
return $result;
}
/**
* Check if section have extensions.
*
* @return boolean Return true if section is empty.
*/
public function isEmpty()
{
$extensions = new ExtensionsDiscovery('custom');
$listExtensions = $extensions->getExtensionsApps();
if ($listExtensions > 0) {
return false;
} else {
return true;
}
}
}

View File

@ -164,11 +164,9 @@ class DiscoveryTaskList extends HTML
if (is_reporting_console_node() === false) {
$ret2 = $this->showList(__('Host & devices tasks'), [0, 1]);
if (enterprise_installed()) {
$ret2 .= $this->showList(__('Applications tasks'), [3, 4, 5, 10, 11, 12], 'app');
$ret2 .= $this->showList(__('Cloud tasks'), [6, 7, 8, 13, 14], 'cloud');
$ret2 .= $this->showList(__('Custom tasks'), [-1], 'custom');
}
$ret2 .= $this->showList(__('Applications tasks'), [3, 4, 5, 10, 11, 12], 'app');
$ret2 .= $this->showList(__('Cloud tasks'), [6, 7, 8, 13, 14], 'cloud');
$ret2 .= $this->showList(__('Custom tasks'), [-1], 'custom');
}
if ($ret === false && $ret2 === false) {

View File

@ -0,0 +1,986 @@
<?php
/**
* Manage Extensions wizard for Pandora FMS Discovery
*
* @category Wizard
* @package Pandora FMS
* @subpackage ManageExtensions
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2021 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
use PandoraFMS\Tools\Files;
require_once $config['homedir'].'/include/class/ExtensionsDiscovery.class.php';
/**
* Manage interface for upload new extensions in discovery.
*/
class ManageExtensions extends HTML
{
/**
* Allowed methods to be called using AJAX request.
*
* @var array
*/
public $AJAXMethods = [
'getExtensionsInstalled',
'validateIniName',
];
/**
* Url of controller.
*
* @var string
*/
public $ajaxController;
/**
* Icon of section
*
* @var string
*/
public $icon = '/images/wizard/Configurar_app@svg.svg';
/**
* Name of section
*
* @var string
*/
public $label = 'Manage extensions';
/**
* Url of section
*
* @var string
*/
public $url;
/**
* Path of the installation extension.
*
* @var string
*/
public $path = 'attachment/discovery';
/**
* Ini file from extension.
*
* @var array
*/
public $iniFile;
/**
* Default logo
*
* @var string
*/
public $defaultLogo = '/images/wizard/app_generico.svg';
/**
* Constructor
*/
public function __construct()
{
global $config;
$this->ajaxController = $config['homedir'].'/include/ajax/manage_extensions.ajax';
$this->url = ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=magextensions'
);
}
/**
* Checks if target method is available to be called using AJAX.
*
* @param string $method Target method.
*
* @return boolean True allowed, false not.
*/
public function ajaxMethod($method)
{
// Check access.
check_login();
return in_array($method, $this->AJAXMethods);
}
/**
* Implements load method.
*
* @return mixed Skeleton for button.
*/
public function load()
{
return [
'icon' => $this->icon,
'label' => $this->label,
'url' => $this->url,
];
}
/**
* Generates a JSON error.
*
* @param string $msg Error message.
*
* @return void
*/
public function errorAjax(string $msg)
{
echo json_encode(
['error' => $msg]
);
}
/**
* Implements run method.
*
* @return void
*/
public function run()
{
global $config;
// Load styles.
parent::run();
$uploadDisco = get_parameter('upload_disco', '');
$action = get_parameter('action', '');
$shortName = get_parameter('short_name', '');
if (empty($uploadDisco) === false) {
if ($_FILES['file']['error'] == 0) {
$result = $this->uploadExtension($_FILES['file']);
if ($result === true) {
ui_print_success_message(
__('Uploaded extension')
);
} else {
if (is_string($result)) {
echo $this->error($result);
} else {
echo $this->error(__('Failed to upload extension'));
}
}
} else {
echo $this->error(__('Failed to upload extension'));
}
}
if (empty($action) === false && empty($shortName) === false) {
switch ($action) {
case 'delete':
$result = $this->uninstallExtension($shortName);
if ($result === true) {
ui_print_success_message(
__('Deleted extension')
);
} else {
echo $this->error(__('Fail delete extension'));
}
case 'sync_server':
$syncAction = get_parameter('sync_action', '');
if ($syncAction === 'refresh') {
$installationFolder = $config['homedir'].'/'.$this->path.'/'.$shortName;
$result = $this->copyExtensionToServer($installationFolder, $shortName);
if ($result === true) {
ui_print_success_message(
__('Extension folder created successfully')
);
} else {
echo $this->error(__('Fail created extension folder'));
}
}
break;
default:
continue;
}
}
$this->prepareBreadcrum(
[
[
'link' => ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery'
),
'label' => __('Discovery'),
],
[
'link' => '',
'label' => _('Manage extensions'),
'selected' => 1,
],
]
);
// Header.
ui_print_page_header(
__('Manage extensions'),
'',
false,
'',
true,
'',
false,
'',
GENERIC_SIZE_TEXT,
'',
$this->printHeader(true)
);
$table = new stdClass();
$table->width = '100%';
$table->class = 'databox filters';
$table->size = [];
$table->size[0] = '80%';
$table->align[3] = 'right';
$table->data = [];
$table->data[0][0] = html_print_label_input_block(
__('Load DISCO'),
html_print_div(
[
'id' => 'upload_file',
'content' => html_print_input_file(
'file',
true,
['style' => 'width:100%']
),
'class' => 'mrgn_top_15px',
],
true
)
);
$table->data[0][3] = html_print_submit_button(
__('Upload DISCO'),
'upload_button',
false,
[
'class' => 'sub ok float-right',
'icon' => 'next',
],
true
);
echo '<form id="uploadExtension" enctype="multipart/form-data" action="index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=magextensions" method="POST">';
html_print_input_hidden('upload_disco', 1);
html_print_table($table);
echo '<div class="action-buttons w700px">';
echo '</div>';
echo '</form>';
echo '<script type="text/javascript">
var page = "'.$this->ajaxController.'";
var textsToTranslate = {
"Warning": "'.__('Warning').'",
"Confirm": "'.__('Confirm').'",
"Cancel": "'.__('Cancel').'",
"Error": "'.__('Error').'",
"Ok": "'.__('Ok').'",
"Failed to upload extension": "'.__('Failed to upload extension').'",
};
var url = "'.ui_get_full_url('ajax.php', false, false, false).'";
</script>';
ui_require_javascript_file('manage_extensions');
try {
$columns = [
'name',
'short_name',
'section',
'description',
'version',
[
'text' => 'actions',
'class' => 'flex flex-items-center',
],
];
$columnNames = [
__('Name'),
__('Short name'),
__('Section'),
__('Description'),
__('Version'),
__('Actions'),
];
// Load datatables user interface.
ui_print_datatable(
[
'id' => 'list_extensions',
'class' => 'info_table',
'style' => 'width: 99%',
'dom_elements' => 'plfti',
'filter_main_class' => 'box-flat white_table_graph fixed_filter_bar',
'columns' => $columns,
'column_names' => $columnNames,
'ajax_url' => $this->ajaxController,
'ajax_data' => ['method' => 'getExtensionsInstalled'],
'no_sortable_columns' => [-1],
'order' => [
'field' => 'name',
'direction' => 'asc',
],
'search_button_class' => 'sub filter float-right',
]
);
} catch (Exception $e) {
echo $e->getMessage();
}
}
/**
* Upload extension to server.
*
* @param array $disco File disco tu upload.
*
* @return boolean $result Of operation, true if is ok.
*/
private function uploadExtension($disco)
{
global $config;
if (substr($disco['name'], -6) !== '.disco') {
return false;
}
$nameFile = str_replace('.disco', '.zip', $disco['name']);
$nameTempDir = $config['attachment_store'].'/downloads/';
if (file_exists($nameTempDir) === false) {
mkdir($nameTempDir);
}
$tmpPath = Files::tempdirnam(
$nameTempDir,
'extensions_uploaded_'
);
$result = move_uploaded_file($disco['tmp_name'], $tmpPath.'/'.$nameFile);
if ($result === true) {
$unzip = Files::unzip($tmpPath.'/'.$nameFile, $tmpPath);
if ($unzip === true) {
unlink($tmpPath.'/'.$nameFile);
db_process_sql_begin();
$this->iniFile = parse_ini_file($tmpPath.'/discovery_definition.ini', true, INI_SCANNER_TYPED);
if ($this->iniFile === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return __('Failed to upload extension: Error while parsing dicovery_definition.ini');
}
$error = ExtensionsDiscovery::validateIni($this->iniFile);
if ($error !== false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return $error;
}
$id = $this->installExtension();
if ($id === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return false;
}
$result = $this->autoLoadConfigExec($id);
if ($result === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return false;
}
$result = $this->autoUpdateDefaultMacros($id);
if ($result === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return false;
}
$nameFolder = $this->iniFile['discovery_extension_definition']['short_name'];
$installationFolder = $config['homedir'].'/'.$this->path.'/'.$nameFolder;
if (file_exists($installationFolder) === false) {
mkdir($installationFolder, 0777, true);
} else {
Files::rmrf($installationFolder, true);
}
$result = Files::move($tmpPath, $installationFolder, true);
if ($result === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return false;
}
chmod($installationFolder, 0777);
foreach (glob($installationFolder.'/*') as $file) {
chmod($file, 0777);
}
$result = $this->copyExtensionToServer($installationFolder, $nameFolder);
if ($result === false) {
db_process_sql_rollback();
Files::rmrf($tmpPath);
return false;
}
Files::rmrf($tmpPath);
db_process_sql_commit();
return true;
}
} else {
Files::rmrf($tmpPath);
return false;
}
}
/**
* Copy the extension folder into remote path server.
*
* @param string $path Path extension folder.
* @param string $nameFolder Name of extension folder.
*
* @return boolean Result of operation.
*/
public function copyExtensionToServer($path, $nameFolder)
{
global $config;
$filesToExclude = [
'discovery_definition.ini',
'logo.png',
];
$serverPath = $config['remote_config'].'/discovery/'.$nameFolder;
if (file_exists($serverPath) === false) {
mkdir($serverPath, 0777, true);
} else {
Files::rmrf($serverPath, true);
}
$result = $this->copyFolder($path, $serverPath, $filesToExclude);
chmod($serverPath, 0777);
foreach (glob($serverPath.'/*') as $file) {
chmod($file, 0777);
}
return $result;
}
/**
* Copy from $source path to $destination
*
* @param string $source Initial folder path.
* @param string $destination Destination folder path.
* @param array $exclude Files to exlcude in copy.
*
* @return boolean Result of operation.
*/
public function copyFolder($source, $destination, $exclude=[])
{
if (file_exists($destination) === false) {
mkdir($destination, 0777, true);
}
$files = scandir($source);
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
if (is_dir($source.'/'.$file)) {
$result = $this->copyFolder($source.'/'.$file, $destination.'/'.$file);
if ($result === false) {
return false;
}
} else {
if (in_array($file, $exclude) === false) {
$result = copy($source.'/'.$file, $destination.'/'.$file);
if ($result === false) {
return false;
}
}
}
}
}
return true;
}
/**
* Delete extension from database and delete folder
*
* @param integer $shortName Short name app for delete.
*
* @return boolean Result of operation.
*/
private function uninstallExtension($shortName)
{
global $config;
$result = db_process_sql_delete(
'tdiscovery_apps',
['short_name' => $shortName]
);
if ($result !== false) {
Files::rmrf($config['homedir'].'/'.$this->path.'/'.$shortName);
Files::rmrf($config['remote_config'].'/discovery/'.$shortName);
return true;
} else {
return false;
}
}
/**
* Load the basic information of the app into database.
*
* @return boolean Result of query.
*/
private function installExtension()
{
$exist = db_get_row_filter(
'tdiscovery_apps',
[
'short_name' => $this->iniFile['discovery_extension_definition']['short_name'],
]
);
$version = $this->iniFile['discovery_extension_definition']['version'];
if ($version === null) {
$version = '';
}
$description = $this->iniFile['discovery_extension_definition']['description'];
if ($description === null) {
$description = '';
}
if ($exist === false) {
return db_process_sql_insert(
'tdiscovery_apps',
[
'short_name' => $this->iniFile['discovery_extension_definition']['short_name'],
'name' => io_safe_input($this->iniFile['discovery_extension_definition']['name']),
'description' => io_safe_input($description),
'section' => $this->iniFile['discovery_extension_definition']['section'],
'version' => $version,
]
);
} else {
$result = db_process_sql_update(
'tdiscovery_apps',
[
'name' => io_safe_input($this->iniFile['discovery_extension_definition']['name']),
'description' => io_safe_input($description),
'section' => $this->iniFile['discovery_extension_definition']['section'],
'version' => $version,
],
[
'short_name' => $this->iniFile['discovery_extension_definition']['short_name'],
]
);
if ($result !== false) {
return $exist['id_app'];
}
}
}
/**
* Return all extension installed by ajax.
*
* @return void
*/
public function getExtensionsInstalled()
{
global $config;
$data = [];
$start = get_parameter('start', 0);
$length = get_parameter('length', $config['block_size']);
$orderDatatable = get_datatable_order(true);
$pagination = '';
$order = '';
try {
ob_start();
if (isset($orderDatatable)) {
$order = sprintf(
' ORDER BY %s %s',
$orderDatatable['field'],
$orderDatatable['direction']
);
}
if (isset($length) && $length > 0
&& isset($start) && $start >= 0
) {
$pagination = sprintf(
' LIMIT %d OFFSET %d ',
$length,
$start
);
}
$sql = sprintf(
'SELECT short_name, name, section, description, version
FROM tdiscovery_apps
%s %s',
$order,
$pagination
);
$data = db_get_all_rows_sql($sql);
$sqlCount = sprintf(
'SELECT short_name, name, section, description, version
FROM tdiscovery_apps
%s',
$order,
);
$count = db_get_num_rows($sqlCount);
foreach ($data as $key => $row) {
$logo = $this->path.'/'.$row['short_name'].'/logo.png';
if (file_exists($logo) === false) {
$logo = $this->defaultLogo;
}
$logo = html_print_image($logo, true, ['style' => 'max-width: 30px; margin-right: 15px;']);
$data[$key]['name'] = $logo.io_safe_output($row['name']);
$data[$key]['short_name'] = $row['short_name'];
$data[$key]['description'] = io_safe_output($row['description']);
$data[$key]['version'] = $row['version'];
$data[$key]['actions'] = '<form name="grupo" method="post" class="rowPair table_action_buttons" action="'.$this->url.'&action=delete">';
$data[$key]['actions'] .= html_print_input_image(
'button_delete',
'images/delete.svg',
'',
'',
true,
[
'onclick' => 'if (!confirm(\''.__('Deleting this application will also delete all the discovery tasks using it. Do you want to delete it?').'\')) return false;',
'class' => 'main_menu_icon invert_filter action_button_hidden',
]
);
$data[$key]['actions'] .= html_print_input_hidden('short_name', $row['short_name'], true);
$data[$key]['actions'] .= '</form>';
if ($this->checkFolderConsole($row['short_name']) === true) {
$data[$key]['actions'] .= '<form name="grupo" method="post" class="rowPair table_action_buttons" action="'.$this->url.'&action=sync_server">';
$data[$key]['actions'] .= html_print_input_image(
'button_refresh',
'images/refresh@svg.svg',
'',
'',
true,
[
'onclick' => 'if (!confirm(\''.__('Are you sure you want to reapply?').'\')) return false;',
'class' => 'main_menu_icon invert_filter action_button_hidden',
]
);
$data[$key]['actions'] .= html_print_input_hidden('sync_action', 'refresh', true);
$data[$key]['actions'] .= html_print_input_hidden('short_name', $row['short_name'], true);
$data[$key]['actions'] .= '</form>';
} else {
$data[$key]['actions'] .= html_print_image(
'images/error_red.png',
true,
[
'title' => __('The extension directory or .ini does not exist in console.'),
'alt' => __('The extension directory or .ini does not exist in console.'),
'class' => 'main_menu_icon invert_filter',
],
);
}
}
if (empty($data) === true) {
$total = 0;
$data = [];
} else {
$total = $count;
}
echo json_encode(
[
'data' => $data,
'recordsTotal' => $total,
'recordsFiltered' => $total,
]
);
// Capture output.
$response = ob_get_clean();
} catch (Exception $e) {
echo json_encode(['error' => $e->getMessage()]);
exit;
}
json_decode($response);
if (json_last_error() === JSON_ERROR_NONE) {
echo $response;
} else {
echo json_encode(
[
'success' => false,
'error' => $response,
]
);
}
exit;
}
/**
* Insert new the default values for extension.
*
* @param integer $id Id of extension.
*
* @return boolean Result of query.
*/
private function autoUpdateDefaultMacros($id)
{
$defaultValues = $this->iniFile['discovery_extension_definition']['default_value'];
foreach ($defaultValues as $macro => $value) {
$sql = 'INSERT IGNORE INTO `tdiscovery_apps_tasks_macros`
(`id_task`, `macro`, `type`, `value`, `temp_conf`)
SELECT `id_rt`, "'.$macro.'", "custom", "'.(string) io_safe_input($value).'", "0"
FROM `trecon_task`
WHERE `id_app` = "'.$id.'";';
$result = db_process_sql($sql);
if ($result === false) {
return false;
}
}
$tempFiles = $this->iniFile['tempfile_confs']['file'];
foreach ($tempFiles as $macro => $value) {
$sql = 'INSERT IGNORE INTO `tdiscovery_apps_tasks_macros`
(`id_task`, `macro`, `type`, `value`, `temp_conf`)
SELECT `id_rt`, "'.$macro.'", "custom", "'.(string) io_safe_input($value).'", "1"
FROM `trecon_task`
WHERE `id_app` = "'.$id.'";';
$result = db_process_sql($sql);
if ($result === false) {
return false;
}
}
return true;
}
/**
* Load the exec files in database
*
* @param integer $id Id of extension.
*
* @return boolean Result of query.
*/
private function autoLoadConfigExec($id)
{
$executionFiles = $this->iniFile['discovery_extension_definition']['execution_file'];
foreach ($executionFiles as $key => $value) {
$exist = db_get_row_filter(
'tdiscovery_apps_scripts',
[
'id_app' => $id,
'macro' => $key,
]
);
if ($exist === false) {
$result = db_process_sql_insert(
'tdiscovery_apps_scripts',
[
'id_app' => $id,
'macro' => $key,
'value' => io_safe_input($value),
]
);
if ($result === false) {
return false;
}
} else {
$result = db_process_sql_update(
'tdiscovery_apps_scripts',
['value' => io_safe_input($value)],
[
'id_app' => $id,
'macro' => $key,
]
);
if ($result === false) {
return false;
}
}
}
$execCommands = $this->iniFile['discovery_extension_definition']['exec'];
$result = db_process_sql_delete(
'tdiscovery_apps_executions',
['id_app' => $id]
);
if ($result === false) {
return false;
}
foreach ($execCommands as $key => $value) {
$result = db_process_sql_insert(
'tdiscovery_apps_executions',
[
'id_app' => $id,
'execution' => io_safe_input($value),
]
);
if ($result === false) {
return false;
}
}
return true;
}
/**
* Check if exist folder extension in console.
*
* @param string $shortName Name of folder.
*
* @return boolean Return true if exist folder
*/
private function checkFolderConsole($shortName)
{
global $config;
$folderPath = $config['homedir'].'/'.$this->path.'/'.$shortName;
$iniPath = $config['homedir'].'/'.$this->path.'/'.$shortName.'/discovery_definition.ini';
if (file_exists($folderPath) === false || file_exists($iniPath) === false) {
return false;
} else {
return true;
}
}
/**
* Validate the ini name by ajax.
*
* @return void
*/
public function validateIniName()
{
global $config;
$uploadDisco = get_parameter('upload_disco', '');
if (empty($uploadDisco) === false) {
if ($_FILES['file']['error'] == 0) {
$disco = $_FILES['file'];
} else {
echo json_encode(['success' => false, 'message' => 'Failed to upload extension']);
return;
}
}
if (substr($disco['name'], -6) !== '.disco') {
echo json_encode(['success' => false, 'message' => 'Failed to upload extension']);
return;
}
$nameFile = str_replace('.disco', '.zip', $disco['name']);
$nameTempDir = $config['attachment_store'].'/downloads/';
if (file_exists($nameTempDir) === false) {
mkdir($nameTempDir);
}
$tmpPath = Files::tempdirnam(
$nameTempDir,
'extensions_uploaded_'
);
$result = move_uploaded_file($disco['tmp_name'], $tmpPath.'/'.$nameFile);
if ($result === true) {
$unzip = Files::unzip($tmpPath.'/'.$nameFile, $tmpPath);
if ($unzip === true) {
unlink($tmpPath.'/'.$nameFile);
$this->iniFile = parse_ini_file($tmpPath.'/discovery_definition.ini', true, INI_SCANNER_TYPED);
if ($this->iniFile === false) {
Files::rmrf($tmpPath);
echo json_encode(['success' => false, 'message' => __('Failed to upload extension: Error while parsing dicovery_definition.ini')]);
return;
}
$message = false;
$shortName = $this->iniFile['discovery_extension_definition']['short_name'];
if (strpos($shortName, 'pandorafms.') === 0) {
$message = __('The \'short_name\' starting with \'pandorafms.\' is reserved for Pandora FMS applications. If this is not an official Pandora FMS application, consider changing the \'short_name\'. Do you want to continue?');
}
$exist = db_get_row_filter(
'tdiscovery_apps',
['short_name' => $shortName]
);
if ($exist !== false) {
$message = __('There is another application with the same \'short_name\': \'%s\'. Do you want to overwrite the application and all of its contents?', $shortName);
}
if ($message !== false) {
echo json_encode(
[
'success' => true,
'warning' => true,
'message' => $message,
]
);
} else {
echo json_encode(['success' => true]);
}
Files::rmrf($tmpPath);
return;
}
} else {
Files::rmrf($tmpPath);
echo json_encode(['success' => false, 'message' => __('Failed to upload extension')]);
return;
}
}
/**
* Return all extensions from section.
*
* @param string $section Section to filter.
*
* @return array List of sections.
*/
static public function getExtensionBySection($section)
{
return db_get_all_rows_filter(
'tdiscovery_apps',
['section' => $section]
);
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="462px" height="462px" viewBox="0 0 462 462" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
<title>Configurar app@svg</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M170.651341,0 L170.651,0.004 L172.111579,0.00817671226 C263.146802,0.548182735 340,27.8694245 340,92.0575424 L340,247.942458 C340,312.77894 261.586371,340 169.348659,340 L170.651,339.996 L170.651341,340 L170,339.998 L169.348659,340 L169.348659,340 L169.348,339.996 L167.888421,339.991823 C128.247423,339.756679 91.2955334,334.44344 62.2073113,323.219366 L161.855602,223.57095 C187.013424,231.95857 215.800358,226.422038 235.828233,206.394148 C254.435585,187.786783 260.775236,161.559784 254.857225,137.762234 C253.732853,133.229606 248.060798,131.693633 244.757955,134.996478 L207.432822,172.321638 L173.360336,166.644559 L167.683262,132.572049 L205.008395,95.2468889 C208.331316,91.9239659 206.73009,86.2619459 202.167348,85.1275341 C178.384873,79.2346161 152.19805,85.5843105 133.610776,104.166578 C113.713408,124.06396 108.237114,152.90613 116.519318,178.053931 L10.1129522,284.45776 C3.58111026,273.936239 0,261.798287 0,247.942458 L0,92.0575424 C0,27.2210597 78.4136287,0 170.651341,0 L169.348,0.004 L169.348659,0 L170,0.002 L170.651341,0 L170.651341,0 Z" id="path-1"></path>
</defs>
<g id="Configurar-app" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rectangle" transform="translate(61.000000, 61.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Mask" stroke="#555555" stroke-width="14" stroke-linejoin="round" xlink:href="#path-1"></use>
</g>
<g id="Group" transform="translate(107.000000, 136.000000)" stroke="#555555" stroke-width="7">
<circle id="Oval" cx="14.5" cy="14.5" r="14.5"></circle>
<circle id="Oval-Copy" cx="14.5" cy="61.5" r="14.5"></circle>
<circle id="Oval-Copy-2" cx="142.5" cy="208.5" r="14.5"></circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="462px" height="462px" viewBox="0 0 462 462" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
<title>Custom apps@svg</title>
<desc>Created with Sketch.</desc>
<g id="Custom-apps" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(61.000000, 61.000000)" stroke="#555555">
<path d="M0,315.724835 L0,274.275165 C0,257.178072 20.6773253,250 45,250 L45,250 C69.3226747,250 90,257.178072 90,274.275165 L90,315.724835 C90,332.821928 69.3226747,340 45,340 L45,340 C20.6773253,340 0,332.821928 0,315.724835 Z" id="Mask" stroke-width="14" stroke-linejoin="round"></path>
<path d="M0,190.724835 L0,149.275165 C0,132.178072 20.6773253,125 45,125 L45,125 C69.3226747,125 90,132.178072 90,149.275165 L90,190.724835 C90,207.821928 69.3226747,215 45,215 L45,215 C20.6773253,215 0,207.821928 0,190.724835 Z" id="Mask-Copy" stroke-width="14" stroke-linejoin="round"></path>
<path d="M0,65.7248353 L0,24.2751647 C0,7.17807242 20.6773253,0 45,0 L45,0 C69.3226747,0 90,7.17807242 90,24.2751647 L90,65.7248353 C90,82.8219276 69.3226747,90 45,90 L45,90 C20.6773253,90 0,82.8219276 0,65.7248353 Z" id="Mask-Copy-2" stroke-width="14" stroke-linejoin="round"></path>
<path d="M125,315.724835 L125,274.275165 C125,257.178072 145.677325,250 170,250 L170,250 C194.322675,250 215,257.178072 215,274.275165 L215,315.724835 C215,332.821928 194.322675,340 170,340 L170,340 C145.677325,340 125,332.821928 125,315.724835 Z" id="Mask" stroke-width="14" stroke-linejoin="round"></path>
<path d="M125,190.724835 L125,149.275165 C125,132.178072 145.677325,125 170,125 L170,125 C194.322675,125 215,132.178072 215,149.275165 L215,190.724835 C215,207.821928 194.322675,215 170,215 L170,215 C145.677325,215 125,207.821928 125,190.724835 Z" id="Mask-Copy" stroke-width="14" stroke-linejoin="round"></path>
<path d="M125,65.7248353 L125,24.2751647 C125,7.17807242 145.677325,0 170,0 L170,0 C194.322675,0 215,7.17807242 215,24.2751647 L215,65.7248353 C215,82.8219276 194.322675,90 170,90 L170,90 C145.677325,90 125,82.8219276 125,65.7248353 Z" id="Mask-Copy-2" stroke-width="14" stroke-linejoin="round"></path>
<path d="M250,190.724835 L250,149.275165 C250,132.178072 270.677325,125 295,125 L295,125 C319.322675,125 340,132.178072 340,149.275165 L340,190.724835 C340,207.821928 319.322675,215 295,215 L295,215 C270.677325,215 250,207.821928 250,190.724835 Z" id="Mask-Copy" stroke-width="14" stroke-linejoin="round"></path>
<path d="M250,65.7248353 L250,24.2751647 C250,7.17807242 270.677325,0 295,0 L295,0 C319.322675,0 340,7.17807242 340,24.2751647 L340,65.7248353 C340,82.8219276 319.322675,90 295,90 L295,90 C270.677325,90 250,82.8219276 250,65.7248353 Z" id="Mask-Copy-2" stroke-width="14" stroke-linejoin="round"></path>
<circle id="Oval" stroke-width="7" cx="45" cy="45" r="15"></circle>
<polygon id="Polygon" stroke-width="7" points="295 155 309.265848 165.364745 303.816779 182.135255 286.183221 182.135255 280.734152 165.364745"></polygon>
<rect id="Rectangle" stroke-width="7" x="155" y="280" width="30" height="30"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="462px" height="462px" viewBox="0 0 462 462" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
<title>App genérico@svg</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M340,247.942458 C340,312.77894 261.586371,340 169.348659,340 L170.651,339.996 L170.651341,340 L170,339.998 L169.348659,340 L169.348659,340 L169.348,339.996 L167.888421,339.991823 C76.8531975,339.451817 0,312.130576 0,247.942458 L0,92.0575424 C0,27.2210597 78.4136287,0 170.651341,0 L169.348,0.004 L169.348659,0 L170,0.002 L170.651341,0 L170.651341,0 L170.651,0.004 L172.111579,0.00817671226 C263.146802,0.548182735 340,27.8694245 340,92.0575424 Z" id="path-1"></path>
</defs>
<g id="App-genérico" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rectangle" transform="translate(61.000000, 61.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Mask" stroke="#555555" stroke-width="14" stroke-linejoin="round" xlink:href="#path-1"></use>
<path d="M243.089632,66.6385397 C255.811455,68.1348967 268.474117,71.8213332 276.910371,78.4128805 C279.780827,80.6195335 283.214489,83.0345401 285.04609,85.6744737 C286.108609,87.2039779 287.599447,90.7246786 286.747539,92.8105813 C285.689754,95.3439706 281.820673,95.5831036 278.614186,95.5168093 C267.669538,95.2682057 257.661988,94.0985848 247.077034,95.3534412 C232.071625,97.1623285 219.643237,101.345972 208.921031,105.81847 C186.274482,115.196745 166.808389,130.69067 151.450385,146.338491 C135.966961,162.071549 121.652544,181.903015 110.248812,202.274305 C97.5530192,224.954058 87.9619574,248.876829 80.0344822,274 C62.0000677,250.340039 50.8566406,221.118459 50,189.124358 L50,189.079372 L50,189.079372 C67.1635754,162.156784 86.968065,137.803101 110.459422,117.133486 C126.655136,102.842329 145.730771,90.113824 166.841519,80.8823431 C170.384035,79.3102211 173.820063,77.3284952 177.646549,76.1044183 C181.43044,74.8637679 185.379979,73.6325881 189.417075,72.3019668 C204.850804,67.2470266 226.07514,64.7278433 243.089632,66.6385397 Z M249.443746,111.548575 C251.871655,112.938928 254.490313,115.160583 256.507696,116.816952 C263.206733,122.210025 268.91885,129.801891 273.814061,136.838864 C280.819956,146.997376 286.722822,158.745753 288.862533,171.957223 C294.066675,204.579596 280.685187,228.427576 263.552985,242.99199 C254.774364,250.4841 243.209143,256.901753 230.756521,260.222805 C216.819372,263.942882 201.165478,264.946679 186.253848,262.930771 C158.17014,259.167051 132.95804,241.350168 116,224.649308 C117.944815,220.058442 118.525357,218.38129 120.519932,213.865241 C123.851827,217.348397 129.769207,221.999533 132.402378,223.828397 C150.61895,236.584729 174.427383,247.587012 205.998488,245.822573 C221.986194,244.978802 236.82733,239.450643 247.36209,231.008769 C257.579625,222.849539 266.134322,211.117788 265.976747,194.763997 C265.812951,177.460443 257.372288,163.326228 248.149968,153.85354 C244.990162,150.594836 241.573259,147.109602 238.121109,144.540878 C232.659869,140.477889 226.584914,137.325176 220.476785,134.344958 C214.262915,131.264983 207.879029,128.18293 200.468828,126.561891 C212.714113,118.797529 245.558263,109.318607 249.443746,111.548575 Z" id="Path-3" stroke="#555555" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,60 @@
<?php
/**
* Manager extensions ajax
*
* @category Ajax library.
* @package Pandora FMS
* @subpackage Modules.
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ============================================================================
*/
// Begin.
global $config;
require_once $config['homedir'].'/godmode/wizards/ManageExtensions.class.php';
if (is_ajax() === false) {
exit;
}
// Control call flow.
try {
// User access and validation is being processed on class constructor.
$actions = new ManageExtensions();
} catch (Exception $e) {
exit;
}
// Ajax controller.
$method = get_parameter('method', '');
if (method_exists($actions, $method) === true) {
if ($actions->ajaxMethod($method) === true) {
$actions->{$method}();
} else {
$actions->errorAjax('Unavailable method.');
}
} else {
$actions->errorAjax('Method not found. ['.$method.']');
}
// Stop any execution.
exit;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
/* globals $, page, url, textsToTranslate, confirmDialog*/
$(document).ready(function() {
function loading(status) {
if (status) {
$(".spinner-fixed").show();
$("#button-upload_button").attr("disabled", "true");
} else {
$(".spinner-fixed").hide();
$("#button-upload_button").removeAttr("disabled");
}
}
$("#uploadExtension").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
formData.append("page", page);
formData.append("method", "validateIniName");
loading(true);
$.ajax({
method: "POST",
url: url,
data: formData,
processData: false,
contentType: false,
success: function(data) {
loading(false);
data = JSON.parse(data);
if (data.success) {
if (data.warning) {
confirmDialog({
title: textsToTranslate["Warning"],
message: data.message,
strOKButton: textsToTranslate["Confirm"],
strCancelButton: textsToTranslate["Cancel"],
onAccept: function() {
loading(true);
$("#uploadExtension")[0].submit();
},
onDeny: function() {
return false;
}
});
} else {
$("#uploadExtension")[0].submit();
}
} else {
confirmDialog({
title: textsToTranslate["Error"],
message: data.message,
ok: textsToTranslate["Ok"],
hideCancelButton: true,
onAccept: function() {
return false;
}
});
}
},
error: function() {
loading(false);
confirmDialog({
title: textsToTranslate["Error"],
message: textsToTranslate["Failed to upload extension"],
ok: textsToTranslate["Ok"],
hideCancelButton: true,
onAccept: function() {
return false;
}
});
}
});
});
});