776 lines
26 KiB
PHP
776 lines
26 KiB
PHP
<?php
|
|
/**
|
|
* Extension to schedule tasks on Pandora FMS Console
|
|
*
|
|
* @category Wizard
|
|
* @package Pandora FMS
|
|
* @subpackage Host&Devices
|
|
* @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.
|
|
* ============================================================================
|
|
*/
|
|
|
|
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
|
|
|
|
/**
|
|
* CustomNetScan. Host and devices child class.
|
|
*/
|
|
class CustomNetScan extends Wizard
|
|
{
|
|
|
|
/**
|
|
* Number of pages to control breadcrum.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $MAXPAGES = 2;
|
|
|
|
/**
|
|
* Labels for breadcrum.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $pageLabels = [
|
|
'Netscan Custom definition',
|
|
'Netscan Custom script',
|
|
];
|
|
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param integer $page Page.
|
|
* @param array $breadcrum Breadcrum.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function __construct(int $page, array $breadcrum)
|
|
{
|
|
$this->url = ui_get_full_url(
|
|
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=hd'
|
|
);
|
|
|
|
$this->access = 'AW';
|
|
$this->page = $page;
|
|
$this->breadcrum = $breadcrum;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves and validates information given by user in NetScan wizard.
|
|
*
|
|
* @return boolean Data OK or not.
|
|
*/
|
|
public function parseNetScan()
|
|
{
|
|
global $config;
|
|
|
|
if (isset($this->page) === true && $this->page === 0) {
|
|
// Check if we're updating a task.
|
|
$task_id = get_parameter('task', null);
|
|
|
|
if (isset($task_id) === true) {
|
|
// We're updating this task.
|
|
$task = db_get_row(
|
|
'trecon_task',
|
|
'id_rt',
|
|
$task_id
|
|
);
|
|
|
|
if ($task !== false) {
|
|
$this->task = $task;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Validate response from page 0. No, not a bug, we're always 1 page
|
|
// from 'validation' page.
|
|
if (isset($this->page) === true && $this->page === 1) {
|
|
$task_id = get_parameter('task', null);
|
|
$taskname = io_safe_input(strip_tags(io_safe_output(get_parameter('taskname'))));
|
|
$comment = get_parameter('comment', '');
|
|
$server_id = get_parameter('id_recon_server', '');
|
|
$id_group = get_parameter('id_group', '');
|
|
$interval = get_parameter('interval', 0);
|
|
|
|
if (isset($task_id) === true) {
|
|
// We're updating this task.
|
|
$task = db_get_row(
|
|
'trecon_task',
|
|
'id_rt',
|
|
$task_id
|
|
);
|
|
|
|
if ($task !== false) {
|
|
$this->task = $task;
|
|
}
|
|
} else if (isset($taskname) === true) {
|
|
// Avoid double creation.
|
|
$task = db_get_row_filter(
|
|
'trecon_task',
|
|
['name' => $taskname]
|
|
);
|
|
|
|
if ($task !== false) {
|
|
$this->task = $task;
|
|
$this->msg = __('This task has been already defined. Please edit it or create a new one.');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ($task_id !== null
|
|
&& $taskname == null
|
|
&& $server_id == null
|
|
&& $id_group == null
|
|
&& $server == null
|
|
&& $datacenter == ''
|
|
&& $user == ''
|
|
&& $pass == ''
|
|
&& $encrypt == null
|
|
&& $interval == 0
|
|
) {
|
|
// Default values, no data received.
|
|
// User is accesing directly to this page.
|
|
if (check_acl(
|
|
$config['id_user'],
|
|
$this->task['id_group'],
|
|
$this->access
|
|
) != true
|
|
) {
|
|
$this->msg = __('You have no access to edit this task.');
|
|
return false;
|
|
}
|
|
} else {
|
|
if (isset($this->task['id_rt']) === false) {
|
|
// Disabled 2 Implies wizard non finished.
|
|
$this->task['disabled'] = 2;
|
|
}
|
|
|
|
if ($taskname == '') {
|
|
$this->msg = __('You must provide a task name.');
|
|
return false;
|
|
}
|
|
|
|
if ($server_id == '') {
|
|
$this->msg = __('You must select a Discovery Server.');
|
|
return false;
|
|
}
|
|
|
|
if ($id_group == '') {
|
|
$this->msg = __('You must select a valid group.');
|
|
return false;
|
|
}
|
|
|
|
// Assign fields.
|
|
$this->task['name'] = $taskname;
|
|
$this->task['description'] = $comment;
|
|
$this->task['id_recon_server'] = $server_id;
|
|
$this->task['id_group'] = $id_group;
|
|
$this->task['interval_sweep'] = $interval;
|
|
|
|
if (isset($this->task['id_rt']) === false) {
|
|
// Create.
|
|
$this->task['id_rt'] = db_process_sql_insert(
|
|
'trecon_task',
|
|
$this->task
|
|
);
|
|
} else {
|
|
// Update.
|
|
db_process_sql_update(
|
|
'trecon_task',
|
|
$this->task,
|
|
['id_rt' => $this->task['id_rt']]
|
|
);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Validate response from page 1.
|
|
if ($this->page == 2) {
|
|
$id_rt = get_parameter('task', -1);
|
|
|
|
$task = db_get_row(
|
|
'trecon_task',
|
|
'id_rt',
|
|
$id_rt
|
|
);
|
|
|
|
if ($task !== false) {
|
|
$this->task = $task;
|
|
} else {
|
|
$this->msg = __('Failed to find network scan task.');
|
|
return false;
|
|
}
|
|
|
|
$id_recon_script = get_parameter('id_recon_script', null);
|
|
$field1 = get_parameter('_field1_', '');
|
|
$field2 = get_parameter('_field2_', '');
|
|
$field3 = get_parameter('_field3_', '');
|
|
$field4 = get_parameter('_field4_', '');
|
|
|
|
// Get macros.
|
|
$macros = get_parameter('macros', null);
|
|
|
|
if (empty($macros) === false) {
|
|
$macros = json_decode(
|
|
base64_decode($macros),
|
|
true
|
|
);
|
|
|
|
foreach ($macros as $k => $m) {
|
|
$macros[$k]['value'] = get_parameter($m['macro'], '');
|
|
}
|
|
}
|
|
|
|
$this->task['id_recon_script'] = $id_recon_script;
|
|
$this->task['macros'] = io_json_mb_encode($macros);
|
|
$this->task['field1'] = $field1;
|
|
$this->task['field2'] = $field2;
|
|
$this->task['field3'] = $field3;
|
|
$this->task['field4'] = $field4;
|
|
|
|
if ($this->task['disabled'] == 2) {
|
|
// Wizard finished.
|
|
$this->task['disabled'] = 0;
|
|
}
|
|
|
|
// Update.
|
|
$res = db_process_sql_update(
|
|
'trecon_task',
|
|
$this->task,
|
|
['id_rt' => $this->task['id_rt']]
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Run function. It will be call into HostsDevices class.
|
|
* Page 0: Upload form.
|
|
* Page 1: Task resume.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function runCustomNetScan()
|
|
{
|
|
global $config;
|
|
|
|
if (!check_acl($config['id_user'], 0, $this->access)) {
|
|
db_pandora_audit(
|
|
'ACL Violation',
|
|
'Trying to access Custom Net Scan.'
|
|
);
|
|
include 'general/noaccess.php';
|
|
return;
|
|
}
|
|
|
|
if ($this->parseNetScan() === false) {
|
|
// Error.
|
|
ui_print_error_message(
|
|
$this->msg
|
|
);
|
|
|
|
$form = [
|
|
'form' => [
|
|
'method' => 'POST',
|
|
'action' => $this->url.'&mode=customnetscan&page='.($this->page - 1).'&task='.$this->task['id_rt'],
|
|
],
|
|
'inputs' => [
|
|
[
|
|
'arguments' => [
|
|
'type' => 'hidden',
|
|
'name' => 'task',
|
|
'value' => $this->task['id_rt'],
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'submit',
|
|
'label' => __('Go back'),
|
|
'type' => 'submit',
|
|
'attributes' => 'class="sub cancel"',
|
|
'return' => true,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
// Check ACL. If user is not able to manage target task,
|
|
// redirect him to main page.
|
|
if (check_acl(
|
|
$config['id_user'],
|
|
$this->task['id_group'],
|
|
$this->access
|
|
) != true
|
|
) {
|
|
$form['form']['action'] = $this->url.'&mode=customnetscan&page='.($this->page - 1);
|
|
}
|
|
|
|
$this->printForm($form);
|
|
return null;
|
|
}
|
|
|
|
$run_url = 'index.php?sec=gservers&sec2=godmode/servers/discovery';
|
|
|
|
$task_url = '';
|
|
if (isset($this->task['id_rt']) === true) {
|
|
$task_url = '&task='.$this->task['id_rt'];
|
|
}
|
|
|
|
$breadcrum = [
|
|
[
|
|
'link' => 'index.php?sec=gservers&sec2=godmode/servers/discovery',
|
|
'label' => 'Discovery',
|
|
],
|
|
[
|
|
'link' => $run_url.'&wiz=hd',
|
|
'label' => __('Host & Devices'),
|
|
],
|
|
];
|
|
|
|
for ($i = 0; $i < $this->MAXPAGES; $i++) {
|
|
$breadcrum[] = [
|
|
'link' => $run_url.'&wiz=hd&mode=customnetscan&page='.$i.$task_url,
|
|
'label' => __($this->pageLabels[$i]),
|
|
'selected' => (($i == $this->page) ? 1 : 0),
|
|
];
|
|
}
|
|
|
|
if ($this->page < $this->MAXPAGES) {
|
|
// Avoid to print header out of wizard.
|
|
$this->prepareBreadcrum($breadcrum);
|
|
|
|
// Header.
|
|
ui_print_page_header(__('NetScan Custom'), '', false, '', true, '', false, '', GENERIC_SIZE_TEXT, '', $this->printHeader(true));
|
|
}
|
|
|
|
$task_url = '';
|
|
if (isset($this->task['id_rt'])) {
|
|
$task_url = '&task='.$this->task['id_rt'];
|
|
}
|
|
|
|
$breadcrum[] = [
|
|
'link' => $run_url.'&wiz=hd',
|
|
'label' => __($this->label),
|
|
];
|
|
for ($i = 0; $i < $this->maxPagesNetScan; $i++) {
|
|
$breadcrum[] = [
|
|
'link' => $run_url.'&wiz=hd&mode=customnetscan&page='.$i.$task_url,
|
|
'label' => $this->pageLabelsNetScan[$i],
|
|
'selected' => (($i == $this->page) ? 1 : 0),
|
|
];
|
|
}
|
|
|
|
if ($this->page < $this->maxPagesNetScan) {
|
|
// Avoid to print header out of wizard.
|
|
$this->prepareBreadcrum($breadcrum);
|
|
|
|
// Header.
|
|
ui_print_page_header(__('NetScan Custom'), '', false, '', true, '', false, '', GENERIC_SIZE_TEXT, '', $this->printHeader(true));
|
|
}
|
|
|
|
if (isset($this->page) === true
|
|
&& $this->page !== 0
|
|
&& isset($this->task['id_rt']) === false
|
|
) {
|
|
// Error.
|
|
ui_print_error_message(
|
|
__('Internal error, please re-run this wizard.')
|
|
);
|
|
|
|
$form = [
|
|
'form' => [
|
|
'method' => 'POST',
|
|
'action' => $this->url.'&mode=customnetscan&page=0',
|
|
],
|
|
'inputs' => [
|
|
[
|
|
'arguments' => [
|
|
'type' => 'hidden',
|
|
'name' => 'page',
|
|
'value' => 0,
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'submit',
|
|
'label' => __('Go back'),
|
|
'type' => 'submit',
|
|
'attributes' => 'class="sub cancel"',
|
|
'return' => true,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$this->printForm($form);
|
|
return null;
|
|
}
|
|
|
|
// -------------------------------.
|
|
// Page 0. wizard starts HERE.
|
|
// -------------------------------.
|
|
if (isset($this->page) === true || $this->page == 0) {
|
|
if (isset($this->page) === false
|
|
|| $this->page == 0
|
|
) {
|
|
$form = [];
|
|
|
|
// Input task name.
|
|
$form['inputs'][] = [
|
|
'label' => __('Task name'),
|
|
'arguments' => [
|
|
'name' => 'taskname',
|
|
'value' => $this->task['name'],
|
|
'type' => 'text',
|
|
'size' => 50,
|
|
],
|
|
];
|
|
|
|
if (isset($this->task['id_rt']) === true) {
|
|
// Propagate id.
|
|
$form['inputs'][] = [
|
|
'arguments' => [
|
|
'name' => 'task',
|
|
'value' => $this->task['id_rt'],
|
|
'type' => 'hidden',
|
|
],
|
|
];
|
|
}
|
|
|
|
// Input task description.
|
|
$form['inputs'][] = [
|
|
'label' => __('Comment'),
|
|
'arguments' => [
|
|
'name' => 'comment',
|
|
'value' => $this->task['description'],
|
|
'type' => 'text',
|
|
'size' => 50,
|
|
],
|
|
];
|
|
|
|
// Input Discovery Server.
|
|
$form['inputs'][] = [
|
|
'label' => __('Discovery server').ui_print_help_tip(
|
|
__('You must select a Discovery Server to run the Task, otherwise the Recon Task will never run'),
|
|
true
|
|
),
|
|
'arguments' => [
|
|
'type' => 'select_from_sql',
|
|
'sql' => sprintf(
|
|
'SELECT id_server, name
|
|
FROM tserver
|
|
WHERE server_type = %d
|
|
ORDER BY name',
|
|
SERVER_TYPE_DISCOVERY
|
|
),
|
|
'name' => 'id_recon_server',
|
|
'selected' => $this->task['id_recon_server'],
|
|
'return' => true,
|
|
],
|
|
];
|
|
|
|
// Input Group.
|
|
$form['inputs'][] = [
|
|
'label' => __('Group'),
|
|
'arguments' => [
|
|
'name' => 'id_group',
|
|
'returnAllGroup' => false,
|
|
'privilege' => $this->access,
|
|
'type' => 'select_groups',
|
|
'selected' => $this->task['id_group'],
|
|
'return' => true,
|
|
'size' => '400px',
|
|
],
|
|
];
|
|
|
|
// Interval and schedules.
|
|
$interv_manual = 0;
|
|
if ((int) $this->task['interval_sweep'] == 0) {
|
|
$interv_manual = 1;
|
|
}
|
|
|
|
// Schedule.
|
|
$form['inputs'][] = [
|
|
'label' => __('Interval').ui_print_help_tip(
|
|
__('Manual interval means that it will be executed only On-demand'),
|
|
true
|
|
),
|
|
'arguments' => [
|
|
'type' => 'select',
|
|
'selected' => $interv_manual,
|
|
'fields' => [
|
|
0 => __('Defined'),
|
|
1 => __('Manual'),
|
|
],
|
|
'name' => 'interval_manual_defined',
|
|
'return' => true,
|
|
],
|
|
'extra' => '<span id="interval_manual_container">'.html_print_extended_select_for_time(
|
|
'interval',
|
|
$this->task['interval_sweep'],
|
|
'',
|
|
'',
|
|
'0',
|
|
false,
|
|
true,
|
|
false,
|
|
false
|
|
).ui_print_help_tip(
|
|
__('The minimum recomended interval for Recon Task is 5 minutes'),
|
|
true
|
|
).'</span>',
|
|
];
|
|
|
|
$str = __('Next');
|
|
|
|
if (isset($this->task['id_rt']) === true) {
|
|
$str = __('Update and continue');
|
|
}
|
|
|
|
// Submit button.
|
|
$form['inputs'][] = [
|
|
'arguments' => [
|
|
'name' => 'submit',
|
|
'label' => $str,
|
|
'type' => 'submit',
|
|
'attributes' => 'class="sub next"',
|
|
'return' => true,
|
|
],
|
|
];
|
|
|
|
$task_url = '';
|
|
if (isset($this->task['id_rt'])) {
|
|
$task_url = '&task='.$this->task['id_rt'];
|
|
}
|
|
|
|
$form['form'] = [
|
|
'method' => 'POST',
|
|
'action' => $this->url.'&mode=customnetscan&page='.($this->page + 1).$task_url,
|
|
];
|
|
|
|
// Default.
|
|
$interval = 600;
|
|
$unit = 60;
|
|
if (isset($this->task['interval_sweep']) === true) {
|
|
$interval = $this->task['interval_sweep'];
|
|
$unit = $this->getTimeUnit($interval);
|
|
}
|
|
|
|
$form['js'] = '
|
|
$("select#interval_manual_defined").change(function() {
|
|
if ($("#interval_manual_defined").val() == 1) {
|
|
$("#interval_manual_container").hide();
|
|
$("#text-interval_text").val(0);
|
|
$("#hidden-interval").val(0);
|
|
}
|
|
else {
|
|
$("#interval_manual_container").show();
|
|
$("#text-interval_text").val(10);
|
|
$("#hidden-interval").val('.$interval.');
|
|
$("#interval_units").val('.$unit.');
|
|
}
|
|
}).change();
|
|
';
|
|
|
|
// XXX: Could be improved validating inputs before continue (JS)
|
|
// Print NetScan page 0.
|
|
$this->printFormAsList($form);
|
|
}
|
|
}
|
|
|
|
if (isset($this->page) === true && $this->page === 1) {
|
|
$name_ipam = 'IPAM Recon';
|
|
// Recon script.
|
|
$form['inputs'][] = [
|
|
'label' => __('Recon script'),
|
|
'arguments' => [
|
|
'type' => 'select_from_sql',
|
|
'sql' => sprintf(
|
|
'SELECT id_recon_script, name FROM trecon_script WHERE name <> "%s" ORDER BY name',
|
|
$name_ipam
|
|
),
|
|
'name' => 'id_recon_script',
|
|
'selected' => $this->task['id_recon_script'],
|
|
'return' => true,
|
|
],
|
|
];
|
|
|
|
$form['inputs'][] = [
|
|
'hidden' => 1,
|
|
'arguments' => [
|
|
'type' => 'hidden',
|
|
'name' => 'task',
|
|
'value' => $this->task['id_rt'],
|
|
],
|
|
];
|
|
|
|
$form['inputs'][] = [
|
|
'hidden' => 1,
|
|
'arguments' => [
|
|
'type' => 'hidden_extended',
|
|
'name' => 'macros',
|
|
'value' => base64_encode($this->task['macros']),
|
|
'return' => true,
|
|
],
|
|
];
|
|
|
|
// Explanation.
|
|
$explanation = db_get_value(
|
|
'description',
|
|
'trecon_script',
|
|
'id_recon_script',
|
|
$this->task['id_recon_script']
|
|
);
|
|
|
|
$form['inputs'][] = [
|
|
'label' => __('Explanation').'<span id="spinner_recon_script" style="display: none;">'.html_print_image('images/spinner.gif', true).'</span>',
|
|
'arguments' => [
|
|
'type' => 'textarea',
|
|
'rows' => 4,
|
|
'columns' => 60,
|
|
'name' => 'explanation',
|
|
'value' => $explanation,
|
|
'return' => true,
|
|
'attributes' => 'style="width: 388px;"',
|
|
'class' => 'discovery_textarea_input',
|
|
],
|
|
];
|
|
|
|
$form['inputs'][] = [
|
|
'hidden' => 1,
|
|
'id' => 'table_recon-macro_field',
|
|
'label' => '<b>'.__('macro_desc').'</b>'.ui_print_help_tip('macro_help', true),
|
|
'arguments' => [
|
|
'name' => 'macro_name',
|
|
'value' => 'macro_value',
|
|
'type' => 'text',
|
|
'size' => 50,
|
|
'return' => true,
|
|
|
|
],
|
|
];
|
|
|
|
if (empty($this->task['macros']) === false) {
|
|
$macros = json_decode($this->task['macros'], true);
|
|
foreach ($macros as $k => $m) {
|
|
$label_macro = '';
|
|
$label_macro .= '<b>'.$m['desc'].'</b>';
|
|
if (!empty($m['help'])) {
|
|
$label_macro .= ui_print_help_tip(
|
|
$m['help'],
|
|
true
|
|
);
|
|
}
|
|
|
|
if ($m['hide']) {
|
|
$form['inputs'][] = [
|
|
'label' => $label_macro,
|
|
'id' => 'table_recon-macro'.$m['macro'],
|
|
'class' => 'macro_field',
|
|
'arguments' => [
|
|
'name' => $m['macro'],
|
|
'value' => $m['value'],
|
|
'type' => 'password',
|
|
'size' => 100,
|
|
'return' => true,
|
|
],
|
|
];
|
|
} else {
|
|
$form['inputs'][] = [
|
|
'label' => $label_macro,
|
|
'id' => 'table_recon-macro'.$m['macro'],
|
|
'class' => 'macro_field',
|
|
'arguments' => [
|
|
'name' => $m['macro'],
|
|
'value' => $m['value'],
|
|
'type' => 'text',
|
|
'size' => 100,
|
|
'return' => true,
|
|
],
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Submit button.
|
|
$form['inputs'][] = [
|
|
'arguments' => [
|
|
'name' => 'submit',
|
|
'label' => __('Finish'),
|
|
'type' => 'submit',
|
|
'attributes' => 'class="sub next"',
|
|
'return' => true,
|
|
],
|
|
];
|
|
|
|
$form['form'] = [
|
|
'method' => 'POST',
|
|
'action' => $this->url.'&mode=customnetscan&page='.($this->page + 1).'&task='.$this->task['id_rt'],
|
|
];
|
|
|
|
$id_task = (isset($this->task['id_rt']) === true) ? $this->task['id_rt'] : 0;
|
|
|
|
$url_ajax = $config['homeurl'].'ajax.php';
|
|
|
|
$change = '';
|
|
if (empty($this->task['macros']) !== false) {
|
|
$change = '.change();';
|
|
}
|
|
|
|
$form['js'] = '
|
|
$("select#id_recon_script").change(function() {
|
|
get_explanation_recon_script($(this).val(), "'.$id_task.'", "'.$url_ajax.'");
|
|
})'.$change;
|
|
|
|
$this->printFormAsList($form);
|
|
}
|
|
|
|
if (isset($this->page) === true && $this->page === 2) {
|
|
if ($this->task['id_rt']) {
|
|
// 0 - Is OK.
|
|
$this->result = 0;
|
|
$this->msg = __('Task configured.');
|
|
} else {
|
|
// 1 - Is NOT OK.
|
|
$this->result = 1;
|
|
$this->msg = __('Wizard failed. Cannot configure task.');
|
|
}
|
|
|
|
return [
|
|
'result' => $this->result,
|
|
'id' => $this->task['id_rt'],
|
|
'msg' => $this->msg,
|
|
];
|
|
}
|
|
|
|
ui_require_javascript_file('pandora_modules');
|
|
}
|
|
|
|
|
|
}
|