diff --git a/extras/docker/build_and_push.sh b/extras/docker/build_and_push.sh index 91e6fa15e5..c58a73bf8e 100755 --- a/extras/docker/build_and_push.sh +++ b/extras/docker/build_and_push.sh @@ -1,3 +1,4 @@ #!/bin/bash docker build --rm=true --pull --no-cache --build-arg BRANCH="develop" --build-arg DB_PASS="pandora" -t pandorafms/pandorafms:7 . && \ +[ "$QA_ENV" == "" ] && \ docker push pandorafms/pandorafms:7 diff --git a/pandora_agents/Dockerfile b/pandora_agents/Dockerfile index 109718ae21..945a74b1c9 100644 --- a/pandora_agents/Dockerfile +++ b/pandora_agents/Dockerfile @@ -14,6 +14,7 @@ RUN yum -y install \ # Install Pandora FMS agent RUN cd /tmp/pandora_agent/unix \ + && chmod +x pandora_agent_installer \ && ./pandora_agent_installer --install # Set default variables @@ -40,7 +41,7 @@ if [ $TIMEZONE != "" ]; then\n \ fi\n \ /etc/init.d/pandora_agent_daemon start\n \ rm -f $0\n \ -bash' \ +tail -f /var/log/pandora/pandora_agent.log' \ >> /entrypoint.sh && \ chmod +x /entrypoint.sh diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 8de0b5d54f..15a54e51db 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.738-190821 +Version: 7.0NG.738-190919 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index a26e778649..c8154f495f 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.738-190821" +pandora_version="7.0NG.738-190919" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index ae770d40a8..f97ba2fc4e 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -42,7 +42,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.738'; -use constant AGENT_BUILD => '190821'; +use constant AGENT_BUILD => '190919'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 0e93bba00b..e1c252eef8 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.738 -%define release 190821 +%define release 190919 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index b3441e3945..c94e3f3656 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.738 -%define release 190821 +%define release 190919 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index 7056ce4102..0c65224531 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.738" -PI_BUILD="190821" +PI_BUILD="190919" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index b5ec69f3d6..9eb3a6cd07 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{190821} +{190919} ViewReadme {Yes} diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index a4d9553c20..4c84910ac5 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -1214,7 +1214,8 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_source, module_eventtype, module_eventcode, - module_pattern); + module_pattern, + module_application); } else if (module_wmiquery != "") { module = new Pandora_Module_WMIQuery (module_name, module_wmiquery, module_wmicolumn); diff --git a/pandora_agents/win32/modules/pandora_module_logchannel.cc b/pandora_agents/win32/modules/pandora_module_logchannel.cc index 4ec72df63c..3c1c4666dd 100755 --- a/pandora_agents/win32/modules/pandora_module_logchannel.cc +++ b/pandora_agents/win32/modules/pandora_module_logchannel.cc @@ -53,7 +53,7 @@ static EvtUpdateBookmarkT EvtUpdateBookmarkF = NULL; * @param name Module name. * @param service_name Service internal name to check. */ -Pandora_Module_Logchannel::Pandora_Module_Logchannel (string name, string source, string type, string id, string pattern) +Pandora_Module_Logchannel::Pandora_Module_Logchannel (string name, string source, string type, string id, string pattern, string application) : Pandora_Module (name) { int i; vector query; @@ -93,6 +93,13 @@ Pandora_Module_Logchannel::Pandora_Module_Logchannel (string name, string source query.push_back(ss.str()); } + // Set the application + if (application != "") { + wstringstream ss; + ss << L"*[System/Provider[@Name='" << application.c_str() << L"']]"; + query.push_back(ss.str()); + } + // Fill the filter if (query.size() == 0) { this->filter = L"*"; @@ -579,4 +586,4 @@ Pandora_Module_Logchannel::GetMessageString(EVT_HANDLE hMetadata, EVT_HANDLE hEv } return pBuffer; -} \ No newline at end of file +} diff --git a/pandora_agents/win32/modules/pandora_module_logchannel.h b/pandora_agents/win32/modules/pandora_module_logchannel.h index 19cde78b93..c008c0aac1 100755 --- a/pandora_agents/win32/modules/pandora_module_logchannel.h +++ b/pandora_agents/win32/modules/pandora_module_logchannel.h @@ -75,7 +75,7 @@ namespace Pandora_Modules { LPWSTR GetMessageString(EVT_HANDLE hMetadata, EVT_HANDLE hEvent, EVT_FORMAT_MESSAGE_FLAGS FormatId); public: - Pandora_Module_Logchannel (string name, string source, string type, string id, string pattern); + Pandora_Module_Logchannel (string name, string source, string type, string id, string pattern, string application); void run (); }; } diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 9863811ef2..8101c88e2e 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.738(Build 190821)") +#define PANDORA_VERSION ("7.0NG.738(Build 190919)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index a672879c29..77616f62dd 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.738(Build 190821))" + VALUE "ProductVersion", "(7.0NG.738(Build 190919))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 999adf9b50..428fe52564 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.738-190821 +Version: 7.0NG.738-190919 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index 1dd37982e9..c7f7078f73 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.738-190821" +pandora_version="7.0NG.738-190919" package_pear=0 package_pandora=1 diff --git a/pandora_console/extensions/files_repo/files_repo_form.php b/pandora_console/extensions/files_repo/files_repo_form.php index 2035cfbd1a..b8e6a084b9 100644 --- a/pandora_console/extensions/files_repo/files_repo_form.php +++ b/pandora_console/extensions/files_repo/files_repo_form.php @@ -44,24 +44,16 @@ $groups = groups_get_all(); // Add the All group to the beginning to be always the first // Use this instead array_unshift to keep the array keys $groups = ([0 => __('All')] + $groups); -$html = ''; -$style = 'style="padding: 2px 10px; display: inline-block;"'; +$groups_selected = []; foreach ($groups as $id => $name) { - $checked = in_array($id, $file['groups']); - $all_checked = false; - if ($id === 0) { - $checkbox = html_print_checkbox_extended('groups[]', $id, $checked, false, '', 'class="chkb_all"', true); - $all_checked = $checked; - } else { - $checkbox = html_print_checkbox_extended('groups[]', $id, $checked, $all_checked, '', 'class="chkb_group"', true); + if (in_array($id, $file['groups'])) { + $groups_selected[] = $id; } - - $html .= "
$name $checkbox
"; } $row = []; $row[0] = __('Groups'); -$row[1] = $html; +$row[1] = html_print_select($groups, 'groups[]', $groups_selected, '', '', '', true, true, '', '', ''); $table->data[] = $row; $table->colspan[][1] = 3; diff --git a/pandora_console/extensions/files_repo/functions_files_repo.php b/pandora_console/extensions/files_repo/functions_files_repo.php index 3d9bdccd38..32ce4c216c 100644 --- a/pandora_console/extensions/files_repo/functions_files_repo.php +++ b/pandora_console/extensions/files_repo/functions_files_repo.php @@ -193,7 +193,7 @@ function files_repo_add_file($file_input_name='upfile', $description='', $groups global $config; $attachment_path = io_safe_output($config['attachment_store']); - $files_repo_path = $attachment_path.'/'.'files_repo'; + $files_repo_path = $attachment_path.'/files_repo'; $result = []; $result['status'] = false; diff --git a/pandora_console/extras/mr/32.sql b/pandora_console/extras/mr/32.sql new file mode 100644 index 0000000000..56855a02d8 --- /dev/null +++ b/pandora_console/extras/mr/32.sql @@ -0,0 +1,11 @@ +START TRANSACTION; + +UPDATE `tlayout_data` SET `height` = 70 , `width` = 70 WHERE `height` = 0 && `width` = 0 && image NOT LIKE '%dot%' && ((`type` IN (0,5)) || +(`type` = 10 && `image` IS NOT NULL && `image` != '' && `image` != 'none') || +(`type` = 11 && `image` IS NOT NULL && `image` != '' && `image` != 'none' && `show_statistics` = 0)); + +ALTER TABLE `treport_content` ADD COLUMN `uncompressed_module` TINYINT DEFAULT '0'; +ALTER TABLE `treport_content_template` ADD COLUMN `uncompressed_module` TINYINT DEFAULT '0'; + + +COMMIT; \ No newline at end of file diff --git a/pandora_console/extras/pandora_diag.php b/pandora_console/extras/pandora_diag.php index 9258a3be42..eb9a199456 100644 --- a/pandora_console/extras/pandora_diag.php +++ b/pandora_console/extras/pandora_diag.php @@ -726,7 +726,7 @@ render_info_data( echo "".__(' Pandora FMS Licence Information').''; render_row(html_print_textarea('keys[customer_key]', 10, 255, $settings->customer_key, 'style="height:40px; width:450px;"', true), 'Customer key'); - render_row($license['expiry_date'], 'Expires'); + render_row($license['expiry_date'], $license['expiry_caption']); render_row($license['limit'].' agents', 'Platform Limit'); render_row($license['count'].' agents', 'Current Platform Count'); render_row($license['count_enabled'].' agents', 'Current Platform Count (enabled: items)'); diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 964441c6c1..5e42ebb514 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -798,6 +798,7 @@ ALTER TABLE `treport_content_template` ADD COLUMN `agent_min_value` TINYINT(1) D ALTER TABLE `treport_content_template` ADD COLUMN `current_month` TINYINT(1) DEFAULT '1'; ALTER TABLE `treport_content_template` ADD COLUMN `failover_mode` tinyint(1) DEFAULT '1'; ALTER TABLE `treport_content_template` ADD COLUMN `failover_type` tinyint(1) DEFAULT '1'; +ALTER TABLE `treport_content_template` ADD COLUMN `uncompressed_module` TINYINT DEFAULT '0'; -- ----------------------------------------------------- -- Table `treport_content_sla_com_temp` (treport_content_sla_combined_template) @@ -1243,7 +1244,7 @@ ALTER TABLE titem MODIFY `source_data` int(10) unsigned; INSERT INTO `tconfig` (`token`, `value`) VALUES ('big_operation_step_datos_purge', '100'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('small_operation_step_datos_purge', '1000'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('days_autodisable_deletion', '30'); -INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 30); +INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 31); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_docs_logo', 'default_docs.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_support_logo', 'default_support.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_logo_white_bg_preview', 'pandora_logo_head_white_bg.png'); @@ -1454,6 +1455,7 @@ ALTER TABLE `treport_content` ADD COLUMN `current_month` TINYINT(1) DEFAULT '1'; ALTER TABLE `treport_content` ADD COLUMN `failover_mode` tinyint(1) DEFAULT '0'; ALTER TABLE `treport_content` ADD COLUMN `failover_type` tinyint(1) DEFAULT '0'; ALTER table `treport_content` MODIFY COLUMN `name` varchar(300) NULL; +ALTER TABLE `treport_content` ADD COLUMN `uncompressed_module` TINYINT DEFAULT '0'; -- --------------------------------------------------------------------- -- Table `tmodule_relationship` diff --git a/pandora_console/general/login_page.php b/pandora_console/general/login_page.php index d8ac4cb91e..5aecfcc92c 100755 --- a/pandora_console/general/login_page.php +++ b/pandora_console/general/login_page.php @@ -389,9 +389,12 @@ if (isset($login_failed)) { echo '

'.__('ERROR').'

'; echo '

'.$config['auth_error'].'

'; echo ''; - echo '
'; - echo '

Remaining attempts: '.$attemps.'

'; - echo '
'; + if ($config['enable_pass_policy']) { + echo '
'; + echo '

Remaining attempts: '.$attemps.'

'; + echo '
'; + } + echo '
'; html_print_submit_button('Ok', 'hide-login-error', false); echo '
'; diff --git a/pandora_console/general/logon_ok.php b/pandora_console/general/logon_ok.php index a02f6c11ac..cdbc09c9f9 100644 --- a/pandora_console/general/logon_ok.php +++ b/pandora_console/general/logon_ok.php @@ -172,6 +172,7 @@ unset($table); echo ''; - if (defined('METACONSOLE')) { + if (is_metaconsole()) { echo ''; } } diff --git a/pandora_console/include/graphs/flot/jquery.flot.pie.js b/pandora_console/include/graphs/flot/jquery.flot.pie.js index 9c19db998b..37a8135e08 100644 --- a/pandora_console/include/graphs/flot/jquery.flot.pie.js +++ b/pandora_console/include/graphs/flot/jquery.flot.pie.js @@ -56,765 +56,897 @@ More detail and specific examples can be found in the included HTML file. */ (function($) { + // Maximum redraw attempts when fitting labels within the plot - // Maximum redraw attempts when fitting labels within the plot + var REDRAW_ATTEMPTS = 10; - var REDRAW_ATTEMPTS = 10; + // Factor by which to shrink the pie when fitting labels within the plot - // Factor by which to shrink the pie when fitting labels within the plot + var REDRAW_SHRINK = 0.95; - var REDRAW_SHRINK = 0.95; + function init(plot) { + var canvas = null, + target = null, + options = null, + maxRadius = null, + centerLeft = null, + centerTop = null, + processed = false, + ctx = null; - function init(plot) { + // interactive variables - var canvas = null, - target = null, - options = null, - maxRadius = null, - centerLeft = null, - centerTop = null, - processed = false, - ctx = null; + var highlights = []; - // interactive variables + // add hook to determine if pie plugin in enabled, and then perform necessary operations - var highlights = []; + plot.hooks.processOptions.push(function(plot, options) { + if (options.series.pie.show) { + options.grid.show = false; - // add hook to determine if pie plugin in enabled, and then perform necessary operations + // set labels.show - plot.hooks.processOptions.push(function(plot, options) { - if (options.series.pie.show) { + if (options.series.pie.label.show == "auto") { + if (options.legend.show) { + options.series.pie.label.show = false; + } else { + options.series.pie.label.show = true; + } + } - options.grid.show = false; + // set radius - // set labels.show + if (options.series.pie.radius == "auto") { + if (options.series.pie.label.show) { + options.series.pie.radius = 3 / 4; + } else { + options.series.pie.radius = 1; + } + } - if (options.series.pie.label.show == "auto") { - if (options.legend.show) { - options.series.pie.label.show = false; - } else { - options.series.pie.label.show = true; - } - } + // ensure sane tilt - // set radius + if (options.series.pie.tilt > 1) { + options.series.pie.tilt = 1; + } else if (options.series.pie.tilt < 0) { + options.series.pie.tilt = 0; + } + } + }); - if (options.series.pie.radius == "auto") { - if (options.series.pie.label.show) { - options.series.pie.radius = 3/4; - } else { - options.series.pie.radius = 1; - } - } + plot.hooks.bindEvents.push(function(plot, eventHolder) { + var options = plot.getOptions(); + if (options.series.pie.show) { + if (options.grid.hoverable) { + eventHolder.unbind("mousemove").mousemove(onMouseMove); + } + if (options.grid.clickable) { + eventHolder.unbind("click").click(onClick); + } + } + }); - // ensure sane tilt + plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) { + var options = plot.getOptions(); + if (options.series.pie.show) { + processDatapoints(plot, series, data, datapoints); + } + }); - if (options.series.pie.tilt > 1) { - options.series.pie.tilt = 1; - } else if (options.series.pie.tilt < 0) { - options.series.pie.tilt = 0; - } - } - }); + plot.hooks.drawOverlay.push(function(plot, octx) { + var options = plot.getOptions(); + if (options.series.pie.show) { + drawOverlay(plot, octx); + } + }); - plot.hooks.bindEvents.push(function(plot, eventHolder) { - var options = plot.getOptions(); - if (options.series.pie.show) { - if (options.grid.hoverable) { - eventHolder.unbind("mousemove").mousemove(onMouseMove); - } - if (options.grid.clickable) { - eventHolder.unbind("click").click(onClick); - } - } - }); + plot.hooks.draw.push(function(plot, newCtx) { + var options = plot.getOptions(); + if (options.series.pie.show) { + draw(plot, newCtx); + } + }); - plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) { - var options = plot.getOptions(); - if (options.series.pie.show) { - processDatapoints(plot, series, data, datapoints); - } - }); + function processDatapoints(plot) { + if (!processed) { + processed = true; + canvas = plot.getCanvas(); + target = $(canvas).parent(); + options = plot.getOptions(); + plot.setData(combine(plot.getData())); + } + } - plot.hooks.drawOverlay.push(function(plot, octx) { - var options = plot.getOptions(); - if (options.series.pie.show) { - drawOverlay(plot, octx); - } - }); + function combine(data) { + var total = 0, + combined = 0, + numCombined = 0, + color = options.series.pie.combine.color, + newdata = []; - plot.hooks.draw.push(function(plot, newCtx) { - var options = plot.getOptions(); - if (options.series.pie.show) { - draw(plot, newCtx); - } - }); + // Fix up the raw data from Flot, ensuring the data is numeric - function processDatapoints(plot, series, datapoints) { - if (!processed) { - processed = true; - canvas = plot.getCanvas(); - target = $(canvas).parent(); - options = plot.getOptions(); - plot.setData(combine(plot.getData())); - } - } + for (var i = 0; i < data.length; ++i) { + var value = data[i].data; - function combine(data) { + // If the data is an array, we'll assume that it's a standard + // Flot x-y pair, and are concerned only with the second value. - var total = 0, - combined = 0, - numCombined = 0, - color = options.series.pie.combine.color, - newdata = []; + // Note how we use the original array, rather than creating a + // new one; this is more efficient and preserves any extra data + // that the user may have stored in higher indexes. - // Fix up the raw data from Flot, ensuring the data is numeric + if ($.isArray(value) && value.length == 1) { + value = value[0]; + } - for (var i = 0; i < data.length; ++i) { + if ($.isArray(value)) { + // Equivalent to $.isNumeric() but compatible with jQuery < 1.7 + if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) { + value[1] = +value[1]; + } else { + value[1] = 0; + } + } else if (!isNaN(parseFloat(value)) && isFinite(value)) { + value = [1, +value]; + } else { + value = [1, 0]; + } - var value = data[i].data; + data[i].data = [value]; + } - // If the data is an array, we'll assume that it's a standard - // Flot x-y pair, and are concerned only with the second value. + // Sum up all the slices, so we can calculate percentages for each - // Note how we use the original array, rather than creating a - // new one; this is more efficient and preserves any extra data - // that the user may have stored in higher indexes. + for (var i = 0; i < data.length; ++i) { + total += data[i].data[0][1]; + } - if ($.isArray(value) && value.length == 1) { - value = value[0]; - } + // Count the number of slices with percentages below the combine + // threshold; if it turns out to be just one, we won't combine. - if ($.isArray(value)) { - // Equivalent to $.isNumeric() but compatible with jQuery < 1.7 - if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) { - value[1] = +value[1]; - } else { - value[1] = 0; - } - } else if (!isNaN(parseFloat(value)) && isFinite(value)) { - value = [1, +value]; - } else { - value = [1, 0]; - } + for (var i = 0; i < data.length; ++i) { + var value = data[i].data[0][1]; + if (value / total <= options.series.pie.combine.threshold) { + combined += value; + numCombined++; + if (!color) { + color = data[i].color; + } + } + } - data[i].data = [value]; - } - - // Sum up all the slices, so we can calculate percentages for each - - for (var i = 0; i < data.length; ++i) { - total += data[i].data[0][1]; - } - - // Count the number of slices with percentages below the combine - // threshold; if it turns out to be just one, we won't combine. - - for (var i = 0; i < data.length; ++i) { - var value = data[i].data[0][1]; - if (value / total <= options.series.pie.combine.threshold) { - combined += value; - numCombined++; - if (!color) { - color = data[i].color; - } - } - } - - for (var i = 0; i < data.length; ++i) { - var value = data[i].data[0][1]; - if (numCombined < 2 || value / total > options.series.pie.combine.threshold) { - newdata.push( - $.extend(data[i], { /* extend to allow keeping all other original data values + for (var i = 0; i < data.length; ++i) { + var value = data[i].data[0][1]; + if ( + numCombined < 2 || + value / total > options.series.pie.combine.threshold + ) { + newdata.push( + $.extend(data[i], { + /* extend to allow keeping all other original data values and using them e.g. in labelFormatter. */ - data: [[1, value]], - color: data[i].color, - label: data[i].label, - angle: value * Math.PI * 2 / total, - percent: value / (total / 100) - }) - ); - } - } - - if (numCombined > 1) { - newdata.push({ - data: [[1, combined]], - color: color, - label: options.series.pie.combine.label, - angle: combined * Math.PI * 2 / total, - percent: combined / (total / 100) - }); - } - - return newdata; - } - - function draw(plot, newCtx) { - - if (!target) { - return; // if no series were passed - } - - var canvasWidth = plot.getPlaceholder().width(), - canvasHeight = plot.getPlaceholder().height(), - legendWidth = target.children().filter(".legend").children().width() || 0; - - ctx = newCtx; - - // WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE! - - // When combining smaller slices into an 'other' slice, we need to - // add a new series. Since Flot gives plugins no way to modify the - // list of series, the pie plugin uses a hack where the first call - // to processDatapoints results in a call to setData with the new - // list of series, then subsequent processDatapoints do nothing. - - // The plugin-global 'processed' flag is used to control this hack; - // it starts out false, and is set to true after the first call to - // processDatapoints. - - // Unfortunately this turns future setData calls into no-ops; they - // call processDatapoints, the flag is true, and nothing happens. - - // To fix this we'll set the flag back to false here in draw, when - // all series have been processed, so the next sequence of calls to - // processDatapoints once again starts out with a slice-combine. - // This is really a hack; in 0.9 we need to give plugins a proper - // way to modify series before any processing begins. - - processed = false; - - // calculate maximum radius and center point - - maxRadius = Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2; - centerTop = canvasHeight / 2 + options.series.pie.offset.top; - centerLeft = canvasWidth / 2; - - if (options.series.pie.offset.left == "auto") { - if (options.legend.position.match("w")) { - centerLeft += legendWidth / 2; - } else { - centerLeft -= legendWidth / 2; - } - if (centerLeft < maxRadius) { - centerLeft = maxRadius; - } else if (centerLeft > canvasWidth - maxRadius) { - centerLeft = canvasWidth - maxRadius; - } - } else { - centerLeft += options.series.pie.offset.left; - } - - var slices = plot.getData(), - attempts = 0; - - // Keep shrinking the pie's radius until drawPie returns true, - // indicating that all the labels fit, or we try too many times. - - do { - if (attempts > 0) { - maxRadius *= REDRAW_SHRINK; - } - attempts += 1; - clear(); - if (options.series.pie.tilt <= 0.8) { - drawShadow(); - } - } while (!drawPie() && attempts < REDRAW_ATTEMPTS) - - if (attempts >= REDRAW_ATTEMPTS) { - clear(); - target.prepend("
Could not draw pie with labels contained inside canvas
"); - } - - if (plot.setSeries && plot.insertLegend) { - plot.setSeries(slices); - plot.insertLegend(); - } - - // we're actually done at this point, just defining internal functions at this point - - function clear() { - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - target.children().filter(".pieLabel, .pieLabelBackground").remove(); - } - - function drawShadow() { - - var shadowLeft = options.series.pie.shadow.left; - var shadowTop = options.series.pie.shadow.top; - var edge = 10; - var alpha = options.series.pie.shadow.alpha; - var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) { - return; // shadow would be outside canvas, so don't draw it - } - - ctx.save(); - ctx.translate(shadowLeft,shadowTop); - ctx.globalAlpha = alpha; - ctx.fillStyle = "#000"; - - // center and rotate to starting position - - ctx.translate(centerLeft,centerTop); - ctx.scale(1, options.series.pie.tilt); - - //radius -= edge; - - for (var i = 1; i <= edge; i++) { - ctx.beginPath(); - ctx.arc(0, 0, radius, 0, Math.PI * 2, false); - ctx.fill(); - radius -= i; - } - - ctx.restore(); - } - - function drawPie() { - - var startAngle = Math.PI * options.series.pie.startAngle; - var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - // center and rotate to starting position - - ctx.save(); - ctx.translate(centerLeft,centerTop); - ctx.scale(1, options.series.pie.tilt); - //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera - - // draw slices - - ctx.save(); - var currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) { - slices[i].startAngle = currentAngle; - drawSlice(slices[i].angle, slices[i].color, true); - } - ctx.restore(); - - // draw slice outlines - - if (options.series.pie.stroke.width > 0) { - ctx.save(); - ctx.lineWidth = options.series.pie.stroke.width; - currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) { - drawSlice(slices[i].angle, options.series.pie.stroke.color, false); - } - ctx.restore(); - } - - // draw donut hole - - drawDonutHole(ctx); - - ctx.restore(); - - // Draw the labels, returning true if they fit within the plot - - if (options.series.pie.label.show) { - return drawLabels(); - } else return true; - - function drawSlice(angle, color, fill) { - - if (angle <= 0 || isNaN(angle)) { - return; - } - - if (fill) { - ctx.fillStyle = color; - } else { - ctx.strokeStyle = color; - ctx.lineJoin = "round"; - } - - ctx.beginPath(); - if (Math.abs(angle - Math.PI * 2) > 0.000000001) { - ctx.moveTo(0, 0); // Center of the pie - } - - //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera - ctx.arc(0, 0, radius,currentAngle, currentAngle + angle / 2, false); - ctx.arc(0, 0, radius,currentAngle + angle / 2, currentAngle + angle, false); - ctx.closePath(); - //ctx.rotate(angle); // This doesn't work properly in Opera - currentAngle += angle; - - if (fill) { - ctx.fill(); - } else { - ctx.stroke(); - } - } - - function drawLabels() { - - var currentAngle = startAngle; - var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius; - - for (var i = 0; i < slices.length; ++i) { - if (slices[i].percent >= options.series.pie.label.threshold * 100) { - if (!drawLabel(slices[i], currentAngle, i)) { - return false; - } - } - currentAngle += slices[i].angle; - } - - return true; - - function drawLabel(slice, startAngle, index) { - - if (slice.data[0][1] == 0) { - return true; - } - - // format label text - - var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter; - - if (lf) { - text = lf(slice.label, slice); - } else { - text = slice.label; - } - - if (plf) { - text = plf(text, slice); - } - - var halfAngle = ((startAngle + slice.angle) + startAngle) / 2; - var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); - var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt; - - var html = "" + text + ""; - target.append(html); - - var label = target.children("#pieLabel" + index); - var labelTop = (y - label.height() / 2); - var labelLeft = (x - label.width() / 2); - - label.css("top", labelTop); - label.css("left", labelLeft); - - // check to make sure that the label is not outside the canvas - - if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) { - return false; - } - - if (options.series.pie.label.background.opacity != 0) { - - // put in the transparent background separately to avoid blended labels and label boxes - - var c = options.series.pie.label.background.color; - - if (c == null) { - c = slice.color; - } - - var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;"; - $("
") - .css("opacity", options.series.pie.label.background.opacity) - .insertBefore(label); - } - - return true; - } // end individual label function - } // end drawLabels function - } // end drawPie function - } // end draw function - - // Placed here because it needs to be accessed from multiple locations - - function drawDonutHole(layer) { - if (options.series.pie.innerRadius > 0) { - - // subtract the center - - layer.save(); - var innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius; - layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color - layer.beginPath(); - layer.fillStyle = options.series.pie.stroke.color; - layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); - layer.fill(); - layer.closePath(); - layer.restore(); - - // add inner stroke - - layer.save(); - layer.beginPath(); - layer.strokeStyle = options.series.pie.stroke.color; - layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); - layer.stroke(); - layer.closePath(); - layer.restore(); - - // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. - } - } - - //-- Additional Interactive related functions -- - - function isPointInPoly(poly, pt) { - for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) - ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1])) - && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) - && (c = !c); - return c; - } - - function findNearbySlice(mouseX, mouseY) { - - var slices = plot.getData(), - options = plot.getOptions(), - radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius, - x, y; - - for (var i = 0; i < slices.length; ++i) { - - var s = slices[i]; - - if (s.pie.show) { - - ctx.save(); - ctx.beginPath(); - ctx.moveTo(0, 0); // Center of the pie - //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. - ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle / 2, false); - ctx.arc(0, 0, radius, s.startAngle + s.angle / 2, s.startAngle + s.angle, false); - ctx.closePath(); - x = mouseX - centerLeft; - y = mouseY - centerTop; - - if (ctx.isPointInPath) { - if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) { - ctx.restore(); - return { - datapoint: [s.percent, s.data], - dataIndex: 0, - series: s, - seriesIndex: i - }; - } - } else { - - // excanvas for IE doesn;t support isPointInPath, this is a workaround. - - var p1X = radius * Math.cos(s.startAngle), - p1Y = radius * Math.sin(s.startAngle), - p2X = radius * Math.cos(s.startAngle + s.angle / 4), - p2Y = radius * Math.sin(s.startAngle + s.angle / 4), - p3X = radius * Math.cos(s.startAngle + s.angle / 2), - p3Y = radius * Math.sin(s.startAngle + s.angle / 2), - p4X = radius * Math.cos(s.startAngle + s.angle / 1.5), - p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5), - p5X = radius * Math.cos(s.startAngle + s.angle), - p5Y = radius * Math.sin(s.startAngle + s.angle), - arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]], - arrPoint = [x, y]; - - // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? - - if (isPointInPoly(arrPoly, arrPoint)) { - ctx.restore(); - return { - datapoint: [s.percent, s.data], - dataIndex: 0, - series: s, - seriesIndex: i - }; - } - } - - ctx.restore(); - } - } - - return null; - } - - function onMouseMove(e) { - triggerClickHoverEvent("plothover", e); - } - - function onClick(e) { - triggerClickHoverEvent("plotclick", e); - } - - // trigger click or hover event (they send the same parameters so we share their code) - - function triggerClickHoverEvent(eventname, e) { - - var offset = plot.offset(); - var canvasX = parseInt(e.pageX - offset.left); - var canvasY = parseInt(e.pageY - offset.top); - var item = findNearbySlice(canvasX, canvasY); - - if (options.grid.autoHighlight) { - - // clear auto-highlights - - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.auto == eventname && !(item && h.series == item.series)) { - unhighlight(h.series); - } - } - } - - // highlight the slice - - if (item) { - highlight(item.series, eventname); - } - - // trigger any hover bind events - - var pos = { pageX: e.pageX, pageY: e.pageY }; - target.trigger(eventname, [pos, item]); - } - - function highlight(s, auto) { - //if (typeof s == "number") { - // s = series[s]; - //} - - var i = indexOfHighlight(s); - - if (i == -1) { - highlights.push({ series: s, auto: auto }); - plot.triggerRedrawOverlay(); - } else if (!auto) { - highlights[i].auto = false; - } - } - - function unhighlight(s) { - if (s == null) { - highlights = []; - plot.triggerRedrawOverlay(); - } - - //if (typeof s == "number") { - // s = series[s]; - //} - - var i = indexOfHighlight(s); - - if (i != -1) { - highlights.splice(i, 1); - plot.triggerRedrawOverlay(); - } - } - - function indexOfHighlight(s) { - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.series == s) - return i; - } - return -1; - } - - function drawOverlay(plot, octx) { - - var options = plot.getOptions(); - - var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - octx.save(); - octx.translate(centerLeft, centerTop); - octx.scale(1, options.series.pie.tilt); - - for (var i = 0; i < highlights.length; ++i) { - drawHighlight(highlights[i].series); - } - - drawDonutHole(octx); - - octx.restore(); - - function drawHighlight(series) { - - if (series.angle <= 0 || isNaN(series.angle)) { - return; - } - - //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); - octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor - octx.beginPath(); - if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) { - octx.moveTo(0, 0); // Center of the pie - } - octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle / 2, false); - octx.arc(0, 0, radius, series.startAngle + series.angle / 2, series.startAngle + series.angle, false); - octx.closePath(); - octx.fill(); - } - } - } // end init (plugin body) - - // define pie specific options and their default values - - var options = { - series: { - pie: { - show: false, - radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) - innerRadius: 0, /* for donut */ - startAngle: 3/2, - tilt: 1, - shadow: { - left: 5, // shadow left offset - top: 15, // shadow top offset - alpha: 0.02 // shadow alpha - }, - offset: { - top: 0, - left: "auto" - }, - stroke: { - color: "#fff", - width: 1 - }, - label: { - show: "auto", - formatter: function(label, slice) { - return "
" + label + "
" + Math.round(slice.percent) + "%
"; - }, // formatter function - radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) - background: { - color: null, - opacity: 0 - }, - threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow) - }, - combine: { - threshold: -1, // percentage at which to combine little slices into one larger slice - color: null, // color to give the new slice (auto-generated if null) - label: "Other" // label to give the new slice - }, - highlight: { - //color: "#fff", // will add this functionality once parseColor is available - opacity: 0.5 - } - } - } - }; - - $.plot.plugins.push({ - init: init, - options: options, - name: "pie", - version: "1.1" - }); - + data: [[1, value]], + color: data[i].color, + label: data[i].label, + angle: (value * Math.PI * 2) / total, + percent: value / (total / 100) + }) + ); + } + } + + if (numCombined > 1) { + newdata.push({ + data: [[1, combined]], + color: color, + label: options.series.pie.combine.label, + angle: (combined * Math.PI * 2) / total, + percent: combined / (total / 100) + }); + } + + return newdata; + } + + function draw(plot, newCtx) { + if (!target) { + return; // if no series were passed + } + + var canvasWidth = plot.getPlaceholder().width(), + canvasHeight = plot.getPlaceholder().height(), + legendWidth = + target + .children() + .filter(".legend") + .children() + .width() || 0; + + ctx = newCtx; + + // WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE! + + // When combining smaller slices into an 'other' slice, we need to + // add a new series. Since Flot gives plugins no way to modify the + // list of series, the pie plugin uses a hack where the first call + // to processDatapoints results in a call to setData with the new + // list of series, then subsequent processDatapoints do nothing. + + // The plugin-global 'processed' flag is used to control this hack; + // it starts out false, and is set to true after the first call to + // processDatapoints. + + // Unfortunately this turns future setData calls into no-ops; they + // call processDatapoints, the flag is true, and nothing happens. + + // To fix this we'll set the flag back to false here in draw, when + // all series have been processed, so the next sequence of calls to + // processDatapoints once again starts out with a slice-combine. + // This is really a hack; in 0.9 we need to give plugins a proper + // way to modify series before any processing begins. + + processed = false; + + // calculate maximum radius and center point + + maxRadius = + Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2; + centerTop = canvasHeight / 2 + options.series.pie.offset.top; + centerLeft = canvasWidth / 2; + + if (options.series.pie.offset.left == "auto") { + if (options.legend.position.match("w")) { + centerLeft += legendWidth / 2; + } else { + centerLeft -= legendWidth / 2; + } + if (centerLeft < maxRadius) { + centerLeft = maxRadius; + } else if (centerLeft > canvasWidth - maxRadius) { + centerLeft = canvasWidth - maxRadius; + } + } else { + centerLeft += options.series.pie.offset.left; + } + + var slices = plot.getData(), + attempts = 0; + + // Keep shrinking the pie's radius until drawPie returns true, + // indicating that all the labels fit, or we try too many times. + + do { + if (attempts > 0) { + maxRadius *= REDRAW_SHRINK; + } + attempts += 1; + clear(); + if (options.series.pie.tilt <= 0.8) { + drawShadow(); + } + } while (!drawPie() && attempts < REDRAW_ATTEMPTS); + + if (attempts >= REDRAW_ATTEMPTS) { + clear(); + target.prepend( + "
Could not draw pie with labels contained inside canvas
" + ); + } + + if (plot.setSeries && plot.insertLegend) { + plot.setSeries(slices); + plot.insertLegend(); + } + + // we're actually done at this point, just defining internal functions at this point + + function clear() { + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + target + .children() + .filter(".pieLabel, .pieLabelBackground") + .remove(); + } + + function drawShadow() { + var shadowLeft = options.series.pie.shadow.left; + var shadowTop = options.series.pie.shadow.top; + var edge = 10; + var alpha = options.series.pie.shadow.alpha; + var radius = + options.series.pie.radius > 1 + ? options.series.pie.radius + : maxRadius * options.series.pie.radius; + + if ( + radius >= canvasWidth / 2 - shadowLeft || + radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || + radius <= edge + ) { + return; // shadow would be outside canvas, so don't draw it + } + + ctx.save(); + ctx.translate(shadowLeft, shadowTop); + ctx.globalAlpha = alpha; + ctx.fillStyle = "#000"; + + // center and rotate to starting position + + ctx.translate(centerLeft, centerTop); + ctx.scale(1, options.series.pie.tilt); + + //radius -= edge; + + for (var i = 1; i <= edge; i++) { + ctx.beginPath(); + ctx.arc(0, 0, radius, 0, Math.PI * 2, false); + ctx.fill(); + radius -= i; + } + + ctx.restore(); + } + + function drawPie() { + var startAngle = Math.PI * options.series.pie.startAngle; + var radius = + options.series.pie.radius > 1 + ? options.series.pie.radius + : maxRadius * options.series.pie.radius; + + // center and rotate to starting position + + ctx.save(); + ctx.translate(centerLeft, centerTop); + ctx.scale(1, options.series.pie.tilt); + //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera + + // draw slices + + ctx.save(); + var currentAngle = startAngle; + for (var i = 0; i < slices.length; ++i) { + slices[i].startAngle = currentAngle; + drawSlice(slices[i].angle, slices[i].color, true); + } + ctx.restore(); + + // draw slice outlines + + if (options.series.pie.stroke.width > 0) { + ctx.save(); + ctx.lineWidth = options.series.pie.stroke.width; + currentAngle = startAngle; + for (var i = 0; i < slices.length; ++i) { + drawSlice(slices[i].angle, options.series.pie.stroke.color, false); + } + ctx.restore(); + } + + // draw donut hole + + drawDonutHole(ctx); + + ctx.restore(); + + // Draw the labels, returning true if they fit within the plot + + if (options.series.pie.label.show) { + return drawLabels(); + } else return true; + + function drawSlice(angle, color, fill) { + if (angle <= 0 || isNaN(angle)) { + return; + } + + if (fill) { + ctx.fillStyle = color; + } else { + ctx.strokeStyle = color; + ctx.lineJoin = "round"; + } + + ctx.beginPath(); + if (Math.abs(angle - Math.PI * 2) > 0.000000001) { + ctx.moveTo(0, 0); // Center of the pie + } + + //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera + ctx.arc(0, 0, radius, currentAngle, currentAngle + angle / 2, false); + ctx.arc( + 0, + 0, + radius, + currentAngle + angle / 2, + currentAngle + angle, + false + ); + ctx.closePath(); + //ctx.rotate(angle); // This doesn't work properly in Opera + currentAngle += angle; + + if (fill) { + ctx.fill(); + } else { + ctx.stroke(); + } + } + + function drawLabels() { + var labels = []; + var currentAngle = startAngle; + var radius = + options.series.pie.label.radius > 1 + ? options.series.pie.label.radius + : maxRadius * options.series.pie.label.radius; + + for (var i = 0; i < slices.length; ++i) { + if (slices[i].percent >= options.series.pie.label.threshold * 100) { + if (!drawLabel(slices[i], currentAngle, i)) { + return false; + } + } + currentAngle += slices[i].angle; + } + + return true; + + function drawLabel(slice, startAngle, index) { + if (slice.data[0][1] == 0) { + return true; + } + + // format label text + + var lf = options.legend.labelFormatter, + text, + plf = options.series.pie.label.formatter; + + if (lf) { + text = lf(slice.label, slice); + } else { + text = slice.label; + } + + if (plf) { + text = plf(text, slice); + } + + var halfAngle = (startAngle + slice.angle + startAngle) / 2; + var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); + var y = + centerTop + + Math.round(Math.sin(halfAngle) * radius) * + options.series.pie.tilt; + + var html = + "" + + text + + ""; + target.append(html); + + var label = target.children("#pieLabel" + index); + var labelTop = y - label.height() / 2; + var labelLeft = x - label.width() / 2; + + label.css("top", labelTop); + label.css("left", labelLeft); + + // check to make sure that the label doesn't overlap one of the other labels + var label_pos = getPositions(label); + for (var j = 0; j < labels.length; j++) { + var tmpPos = getPositions(labels[j]); + var horizontalMatch = comparePositions(label_pos[0], tmpPos[0]); + var verticalMatch = comparePositions(label_pos[1], tmpPos[1]); + var match = horizontalMatch && verticalMatch; + if (match) { + var newTop = tmpPos[1][0] - (label.height() + 1); + label.css("top", newTop); + labelTop = newTop; + } + } + + function getPositions(box) { + var $box = $(box); + var pos = $box.position(); + var width = $box.width(); + var height = $box.height(); + return [ + [pos.left, pos.left + width], + [pos.top, pos.top + height] + ]; + } + + function comparePositions(p1, p2) { + var x1 = p1[0] < p2[0] ? p1 : p2; + var x2 = p1[0] < p2[0] ? p2 : p1; + return x1[1] > x2[0] || x1[0] === x2[0] ? true : false; + } + labels.push(label); + + // check to make sure that the label is not outside the canvas + + if ( + 0 - labelTop > 0 || + 0 - labelLeft > 0 || + canvasHeight - (labelTop + label.height()) < 0 || + canvasWidth - (labelLeft + label.width()) < 0 + ) { + return false; + } + + if (options.series.pie.label.background.opacity != 0) { + // put in the transparent background separately to avoid blended labels and label boxes + + var c = options.series.pie.label.background.color; + + if (c == null) { + c = slice.color; + } + + var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;"; + $( + "
" + ) + .css("opacity", options.series.pie.label.background.opacity) + .insertBefore(label); + } + + return true; + } // end individual label function + } // end drawLabels function + } // end drawPie function + } // end draw function + + // Placed here because it needs to be accessed from multiple locations + + function drawDonutHole(layer) { + if (options.series.pie.innerRadius > 0) { + // subtract the center + + layer.save(); + var innerRadius = + options.series.pie.innerRadius > 1 + ? options.series.pie.innerRadius + : maxRadius * options.series.pie.innerRadius; + layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color + layer.beginPath(); + layer.fillStyle = options.series.pie.stroke.color; + layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); + layer.fill(); + layer.closePath(); + layer.restore(); + + // add inner stroke + + layer.save(); + layer.beginPath(); + layer.strokeStyle = options.series.pie.stroke.color; + layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); + layer.stroke(); + layer.closePath(); + layer.restore(); + + // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. + } + } + + //-- Additional Interactive related functions -- + + function isPointInPoly(poly, pt) { + for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) + ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || + (poly[j][1] <= pt[1] && pt[1] < poly[i][1])) && + pt[0] < + ((poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1])) / + (poly[j][1] - poly[i][1]) + + poly[i][0] && + (c = !c); + return c; + } + + function findNearbySlice(mouseX, mouseY) { + var slices = plot.getData(), + options = plot.getOptions(), + radius = + options.series.pie.radius > 1 + ? options.series.pie.radius + : maxRadius * options.series.pie.radius, + x, + y; + + for (var i = 0; i < slices.length; ++i) { + var s = slices[i]; + + if (s.pie.show) { + ctx.save(); + ctx.beginPath(); + ctx.moveTo(0, 0); // Center of the pie + //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. + ctx.arc( + 0, + 0, + radius, + s.startAngle, + s.startAngle + s.angle / 2, + false + ); + ctx.arc( + 0, + 0, + radius, + s.startAngle + s.angle / 2, + s.startAngle + s.angle, + false + ); + ctx.closePath(); + x = mouseX - centerLeft; + y = mouseY - centerTop; + + if (ctx.isPointInPath) { + if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) { + ctx.restore(); + return { + datapoint: [s.percent, s.data], + dataIndex: 0, + series: s, + seriesIndex: i + }; + } + } else { + // excanvas for IE doesn;t support isPointInPath, this is a workaround. + + var p1X = radius * Math.cos(s.startAngle), + p1Y = radius * Math.sin(s.startAngle), + p2X = radius * Math.cos(s.startAngle + s.angle / 4), + p2Y = radius * Math.sin(s.startAngle + s.angle / 4), + p3X = radius * Math.cos(s.startAngle + s.angle / 2), + p3Y = radius * Math.sin(s.startAngle + s.angle / 2), + p4X = radius * Math.cos(s.startAngle + s.angle / 1.5), + p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5), + p5X = radius * Math.cos(s.startAngle + s.angle), + p5Y = radius * Math.sin(s.startAngle + s.angle), + arrPoly = [ + [0, 0], + [p1X, p1Y], + [p2X, p2Y], + [p3X, p3Y], + [p4X, p4Y], + [p5X, p5Y] + ], + arrPoint = [x, y]; + + // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? + + if (isPointInPoly(arrPoly, arrPoint)) { + ctx.restore(); + return { + datapoint: [s.percent, s.data], + dataIndex: 0, + series: s, + seriesIndex: i + }; + } + } + + ctx.restore(); + } + } + + return null; + } + + function onMouseMove(e) { + triggerClickHoverEvent("plothover", e); + } + + function onClick(e) { + triggerClickHoverEvent("plotclick", e); + } + + // trigger click or hover event (they send the same parameters so we share their code) + + function triggerClickHoverEvent(eventname, e) { + var offset = plot.offset(); + var canvasX = parseInt(e.pageX - offset.left); + var canvasY = parseInt(e.pageY - offset.top); + var item = findNearbySlice(canvasX, canvasY); + + if (options.grid.autoHighlight) { + // clear auto-highlights + + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.auto == eventname && !(item && h.series == item.series)) { + unhighlight(h.series); + } + } + } + + // highlight the slice + + if (item) { + highlight(item.series, eventname); + } + + // trigger any hover bind events + + var pos = { pageX: e.pageX, pageY: e.pageY }; + target.trigger(eventname, [pos, item]); + } + + function highlight(s, auto) { + //if (typeof s == "number") { + // s = series[s]; + //} + + var i = indexOfHighlight(s); + + if (i == -1) { + highlights.push({ series: s, auto: auto }); + plot.triggerRedrawOverlay(); + } else if (!auto) { + highlights[i].auto = false; + } + } + + function unhighlight(s) { + if (s == null) { + highlights = []; + plot.triggerRedrawOverlay(); + } + + //if (typeof s == "number") { + // s = series[s]; + //} + + var i = indexOfHighlight(s); + + if (i != -1) { + highlights.splice(i, 1); + plot.triggerRedrawOverlay(); + } + } + + function indexOfHighlight(s) { + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.series == s) return i; + } + return -1; + } + + function drawOverlay(plot, octx) { + var options = plot.getOptions(); + + var radius = + options.series.pie.radius > 1 + ? options.series.pie.radius + : maxRadius * options.series.pie.radius; + + octx.save(); + octx.translate(centerLeft, centerTop); + octx.scale(1, options.series.pie.tilt); + + for (var i = 0; i < highlights.length; ++i) { + drawHighlight(highlights[i].series); + } + + drawDonutHole(octx); + + octx.restore(); + + function drawHighlight(series) { + if (series.angle <= 0 || isNaN(series.angle)) { + return; + } + + //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); + octx.fillStyle = + "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor + octx.beginPath(); + if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) { + octx.moveTo(0, 0); // Center of the pie + } + octx.arc( + 0, + 0, + radius, + series.startAngle, + series.startAngle + series.angle / 2, + false + ); + octx.arc( + 0, + 0, + radius, + series.startAngle + series.angle / 2, + series.startAngle + series.angle, + false + ); + octx.closePath(); + octx.fill(); + } + } + } // end init (plugin body) + + // define pie specific options and their default values + + var options = { + series: { + pie: { + show: false, + radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) + innerRadius: 0 /* for donut */, + startAngle: 3 / 2, + tilt: 1, + shadow: { + left: 5, // shadow left offset + top: 15, // shadow top offset + alpha: 0.02 // shadow alpha + }, + offset: { + top: 0, + left: "auto" + }, + stroke: { + color: "#fff", + width: 1 + }, + label: { + show: "auto", + formatter: function(label, slice) { + return ( + "
" + + label + + "
" + + Math.round(slice.percent) + + "%
" + ); + }, // formatter function + radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) + background: { + color: null, + opacity: 0 + }, + threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow) + }, + combine: { + threshold: -1, // percentage at which to combine little slices into one larger slice + color: null, // color to give the new slice (auto-generated if null) + label: "Other" // label to give the new slice + }, + highlight: { + //color: "#fff", // will add this functionality once parseColor is available + opacity: 0.5 + } + } + } + }; + + $.plot.plugins.push({ + init: init, + options: options, + name: "pie", + version: "1.1" + }); })(jQuery); diff --git a/pandora_console/include/graphs/flot/pandora.flot.js b/pandora_console/include/graphs/flot/pandora.flot.js index f0976cb98f..c62614ccd3 100644 --- a/pandora_console/include/graphs/flot/pandora.flot.js +++ b/pandora_console/include/graphs/flot/pandora.flot.js @@ -1,4 +1,5 @@ /* global $ */ +/* exported pandoraFlotPie, pandoraFlotPieCustom */ function pandoraFlotPie( graph_id, @@ -14,7 +15,7 @@ function pandoraFlotPie( colors, hide_labels ) { - var labels = labels.split(separator); + labels = labels.split(separator); var data = values.split(separator); if (colors != "") { @@ -92,7 +93,7 @@ function pandoraFlotPie( function pieHover(event, pos, obj) { if (!obj) return; - index = obj.seriesIndex; + var index = obj.seriesIndex; legends.css("color", "#3F3F3D"); legends.eq(index).css("color", ""); } @@ -144,21 +145,14 @@ function pandoraFlotPieCustom( .pop() .split(".") .shift(); - var labels = labels.split(separator); - var legend = legend.split(separator); + labels = labels.split(separator); + legend = legend.split(separator); var data = values.split(separator); var no_data = 0; if (colors != "") { colors = colors.split(separator); } - var colors_data = [ - "#e63c52", - "#FFA631", - "#f3b200", - "#5BB6E5", - "#F2919D", - "#82b92e" - ]; + var color = null; for (var i = 0; i < data.length; i++) { if (colors != "") { @@ -174,28 +168,31 @@ function pandoraFlotPieCustom( if (width <= 450) { show_legend = false; - label_conf = { - show: false - }; - } else { label_conf = { show: true, - radius: 0.75, + radius: 5 / 8, formatter: function(label, series) { + console.log(series); return ( '
' + - series.percent.toFixed(2) + - "%
" + "pt; font-weight:bolder;" + + "text-align:center;padding:2px;color:rgb(63, 63, 61)" + + '">' + + label + + ":
" + + series.data[0][1] + + "" ); }, background: { - opacity: 0.5, - color: "" + opacity: 0.5 } }; + } else { + label_conf = { + show: false + }; } var conf_pie = { @@ -203,8 +200,8 @@ function pandoraFlotPieCustom( pie: { show: true, radius: 3 / 4, - innerRadius: 0.4 - //label: label_conf + innerRadius: 0.4, + label: label_conf } }, legend: { @@ -234,7 +231,7 @@ function pandoraFlotPieCustom( var legends = $("#" + graph_id + " .legendLabel"); var j = 0; legends.each(function() { - //$(this).css('width', $(this).width()); + //$(this).css("width", $(this).width()); $(this).css("font-size", font_size + "pt"); $(this).removeClass("legendLabel"); $(this).addClass(font); @@ -264,19 +261,6 @@ function pandoraFlotPieCustom( return false; }); - var pielegends = $("#" + graph_id + " .pieLabelBackground"); - pielegends.each(function() { - $(this) - .css("transform", "rotate(-35deg)") - .css("color", "black"); - }); - var labelpielegends = $("#" + graph_id + " .pieLabel"); - labelpielegends.each(function() { - $(this) - .css("transform", "rotate(-35deg)") - .css("color", "black"); - }); - // Events $("#" + graph_id).bind("plothover", pieHover); $("#" + graph_id).bind("plotclick", Clickpie); @@ -287,16 +271,17 @@ function pandoraFlotPieCustom( function pieHover(event, pos, obj) { if (!obj) return; - index = obj.seriesIndex; + var index = obj.seriesIndex; legends.css("color", "#3F3F3D"); legends.eq(index).css("color", ""); } function Clickpie(event, pos, obj) { if (!obj) return; - percent = parseFloat(obj.series.percent).toFixed(2); - valor = parseFloat(obj.series.data[0][1]); + var percent = parseFloat(obj.series.percent).toFixed(2); + var valor = parseFloat(obj.series.data[0][1]); + var value = ""; if (valor > 1000000) { value = Math.round((valor / 1000000) * 100) / 100; value = value + "M"; @@ -325,42 +310,6 @@ function pandoraFlotPieCustom( $("#watermark_image_" + graph_id).attr("src") ); } - /* - window.onresize = function(event) { - $.plot($('#' + graph_id), data, conf_pie); - if (no_data == data.length) { - $('#'+graph_id+' .overlay').remove(); - $('#'+graph_id+' .base').remove(); - $('#'+graph_id).prepend(""); - } - var legends = $('#'+graph_id+' .legendLabel'); - var j = 0; - legends.each(function () { - //$(this).css('width', $(this).width()); - $(this).css('font-size', font_size+'pt'); - $(this).removeClass("legendLabel"); - $(this).addClass(font); - $(this).text(legend[j]); - j++; - }); - - if ($('input[name="custom_graph"]').val()) { - $('.legend>div').css('right',($('.legend>div').height()*-1)); - $('.legend>table').css('right',($('.legend>div').height()*-1)); - } - //$('.legend>table').css('border',"1px solid #E2E2E2"); - $('.legend>table').css('background-color',"transparent"); - - var pielegends = $('#'+graph_id+' .pieLabelBackground'); - pielegends.each(function () { - $(this).css('transform', "rotate(-35deg)").css('color', 'black'); - }); - var labelpielegends = $('#'+graph_id+' .pieLabel'); - labelpielegends.each(function () { - $(this).css('transform', "rotate(-35deg)").css('color', 'black'); - }); - } -*/ } function pandoraFlotHBars( diff --git a/pandora_console/include/graphs/functions_flot.php b/pandora_console/include/graphs/functions_flot.php index 8e32673b48..309ddf364b 100644 --- a/pandora_console/include/graphs/functions_flot.php +++ b/pandora_console/include/graphs/functions_flot.php @@ -24,7 +24,7 @@ function include_javascript_dependencies_flot_graph($return=false) $is_include_javascript = true; $metaconsole_hack = ''; - if (defined('METACONSOLE')) { + if (is_metaconsole()) { $metaconsole_hack = '../../'; } diff --git a/pandora_console/include/load_session.php b/pandora_console/include/load_session.php index 8b243d808a..39e0973287 100644 --- a/pandora_console/include/load_session.php +++ b/pandora_console/include/load_session.php @@ -91,6 +91,11 @@ function pandora_session_write($session_id, $data) { $session_id = addslashes($session_id); + // If it's an api call, the session must not be created. + if (get_parameter('op', false) && get_parameter('op2', false)) { + return true; + } + if (is_ajax()) { // Avoid session upadte while processing ajax responses - notifications. if (get_parameter('check_new_notifications', false)) { @@ -159,7 +164,26 @@ function pandora_session_gc($max_lifetime=300) global $config; if (isset($config['session_timeout'])) { - $max_lifetime = $config['session_timeout']; + $session_timeout = $config['session_timeout']; + } else { + // if $config doesn`t work ... + $session_timeout = db_get_value( + 'value', + 'tconfig', + 'token', + 'session_timeout' + ); + } + + if (!empty($session_timeout)) { + if ($session_timeout == -1) { + // The session expires in 10 years + $session_timeout = 315576000; + } else { + $session_timeout *= 60; + } + + $max_lifetime = $session_timeout; } $time_limit = (time() - $max_lifetime); @@ -171,6 +195,11 @@ function pandora_session_gc($max_lifetime=300) ] ); + // Deleting cron and empty sessions. + $sql = "DELETE FROM tsessions_php WHERE + data IS NULL OR id_session REGEXP '^cron-'"; + db_process_sql($sql); + return $retval; } diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php b/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php index cbbe877f8d..53f2adcadd 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php @@ -291,21 +291,9 @@ final class Group extends Item $width = (int) $data['width']; $height = (int) $data['height']; if ($width === 0 || $height === 0) { - // TODO: This will be the default behaviour after we finish the - // builder. Don't delete this code. - // $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - // $data['width'] = $sizeImage[0]; - // $data['height'] = $sizeImage[1]; $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - $imageHeight = $sizeImage[1]; - - if ($width === 0) { - $data['width'] = 70; - } - - if ($height === 0) { - $data['height'] = ($imageHeight > 70) ? 70 : $imageHeight; - } + $data['width'] = $sizeImage[0]; + $data['height'] = $sizeImage[1]; } $data['html'] = ''; diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/Icon.php b/pandora_console/include/rest-api/models/VisualConsole/Items/Icon.php index 29605ffb4f..e67c76a6a7 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/Icon.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/Icon.php @@ -120,21 +120,9 @@ final class Icon extends Item $width = (int) $data['width']; $height = (int) $data['height']; if ($width === 0 || $height === 0) { - // TODO: This will be the default behaviour after we finish the - // builder. Don't delete this code. - // $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - // $data['width'] = $sizeImage[0]; - // $data['height'] = $sizeImage[1]; $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - $imageHeight = $sizeImage[1]; - - if ($width === 0) { - $data['width'] = 70; - } - - if ($height === 0) { - $data['height'] = ($imageHeight > 70) ? 70 : $imageHeight; - } + $data['width'] = $sizeImage[0]; + $data['height'] = $sizeImage[1]; } return $data; diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php b/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php index 9af4287d26..c43fb39136 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php @@ -184,23 +184,9 @@ final class StaticGraph extends Item $width = (int) $data['width']; $height = (int) $data['height']; if ($width === 0 || $height === 0) { - // TODO: This will be the default behaviour after we finish the - // builder. Don't delete this code. - // $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - // $data['width'] = $sizeImage[0]; - // $data['height'] = $sizeImage[1]; - // Default value. Will be replaced by a dynamic image size - // calculation after the phase 3. $sizeImage = getimagesize($config['homedir'].'/'.$imagePath); - $imageHeight = $sizeImage[1]; - - if ($width === 0) { - $data['width'] = 70; - } - - if ($height === 0) { - $data['height'] = ($imageHeight > 70) ? 70 : $imageHeight; - } + $data['width'] = $sizeImage[0]; + $data['height'] = $sizeImage[1]; } // Get last value. diff --git a/pandora_console/include/styles/pandoraPDF.css b/pandora_console/include/styles/pandoraPDF.css index 5bb0e15174..9a55b6a1e4 100644 --- a/pandora_console/include/styles/pandoraPDF.css +++ b/pandora_console/include/styles/pandoraPDF.css @@ -27,6 +27,10 @@ * GNU General Public License for more details. * ============================================================================ */ +table { + text-align: center; +} + table.header_table { width: 100%; } diff --git a/pandora_console/include/styles/pandora_black.css b/pandora_console/include/styles/pandora_black.css index a52c994ed2..6f0c74d16b 100644 --- a/pandora_console/include/styles/pandora_black.css +++ b/pandora_console/include/styles/pandora_black.css @@ -392,3 +392,11 @@ div#box_online * { #text_wizard { color: #555; } + +div#code_license_dialog div#code, +div#form_activate_licence #code { + margin-top: 20px; + margin-bottom: 20px; + border: 0px; + background-color: #222; +} diff --git a/pandora_console/install.php b/pandora_console/install.php index c9b93d5147..5ba3926259 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -129,7 +129,7 @@
'; $data[0] .= ''; - $data[0] .= ' '.$agent['alias'].''; + $data[0] .= ' '.$agent['alias'].''; $data[0] .= ''; if ($agent['quiet']) { @@ -772,7 +779,7 @@ foreach ($agents as $agent) { $data[0] .= '
'; - $data[1] = ui_print_truncate_text($agent['description'], 'description', false, true, true, '[…]', 'font-size: 6.5pt'); + $data[1] = ui_print_truncate_text($agent['description'], 'description', false, true, true, '[…]', $description_font_size); $data[10] = ''; diff --git a/pandora_console/operation/agentes/graphs.php b/pandora_console/operation/agentes/graphs.php index 79ff02b021..308481d8e0 100644 --- a/pandora_console/operation/agentes/graphs.php +++ b/pandora_console/operation/agentes/graphs.php @@ -244,14 +244,18 @@ $htmlForm = ''; -$htmlForm .= html_print_button( - __('Save as custom graph'), - 'save_custom_graph', - false, - '', - 'class="sub add" style=""', - true -).'  '.html_print_submit_button(__('Filter'), 'filter_button', false, 'class="sub upd" style=""', true); +if (check_acl($config['id_user'], 0, 'RW') || check_acl($config['id_user'], 0, 'RM')) { + $htmlForm .= html_print_button( + __('Save as custom graph'), + 'save_custom_graph', + false, + '', + 'class="sub add" style=""', + true + ); +} + +$htmlForm .= '  '.html_print_submit_button(__('Filter'), 'filter_button', false, 'class="sub upd" style=""', true); $htmlForm .= ''; $htmlForm .= ''; diff --git a/pandora_console/operation/agentes/pandora_networkmap.php b/pandora_console/operation/agentes/pandora_networkmap.php index 35eb712146..2aa1404e30 100644 --- a/pandora_console/operation/agentes/pandora_networkmap.php +++ b/pandora_console/operation/agentes/pandora_networkmap.php @@ -795,7 +795,7 @@ switch ($tab) { echo "
"; echo '
'; html_print_input_hidden('new_networkmap', 1); - html_print_submit_button(__('Create networkmap'), 'crt', false, 'class="sub next" style="float: right;"'); + html_print_submit_button(__('Create network map'), 'crt', false, 'class="sub next" style="float: right;"'); echo '
'; echo '
'; @@ -803,7 +803,7 @@ switch ($tab) { echo "
"; echo '
'; html_print_input_hidden('new_empty_networkmap', 1); - html_print_submit_button(__('Create empty networkmap'), 'crt', false, 'class="sub next" style="float: right; margin-right:20px;"'); + html_print_submit_button(__('Create empty network map'), 'crt', false, 'class="sub next" style="float: right; margin-right:20px;"'); echo '
'; echo '
'; } diff --git a/pandora_console/operation/events/event_statistics.php b/pandora_console/operation/events/event_statistics.php index a4a5b1632a..00dd1f4bc6 100644 --- a/pandora_console/operation/events/event_statistics.php +++ b/pandora_console/operation/events/event_statistics.php @@ -62,7 +62,7 @@ echo ''; echo ''; echo "'; echo ''; @@ -83,7 +83,7 @@ if (!users_is_admin()) { echo ''; echo "'; echo "'; echo ''; diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index 52eac8b77e..851bce345a 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -246,6 +246,8 @@ if (is_ajax()) { $fields[] = 'ta.server_name as server_name'; } else { $fields[] = 'ts.server_name as server_name'; + $fields[] = 'te.id_agentmodule'; + $fields[] = 'te.server_id'; } $events = events_get_all( @@ -982,7 +984,7 @@ if (is_metaconsole()) { 'SELECT id, server_name FROM tmetaconsole_setup', 'server_id', $server_id, - 'script', + '', __('All'), '0', true @@ -1029,15 +1031,14 @@ $adv_inputs[] = $in; // Only alert events. $data = html_print_select( [ - '-1' => __('All'), - '0' => __('Filter alert events'), - '1' => __('Only alert events'), + '0' => __('Filter alert events'), + '1' => __('Only alert events'), ], 'filter_only_alert', $filter_only_alert, '', - '', - '', + __('All'), + -1, true ); $in = '
'; @@ -1246,6 +1247,14 @@ try { ]; } + // Identifies column instructions to make it unsortable. + if (in_array('instructions', $fields) > 0) { + $fields[array_search('instructions', $fields)] = [ + 'text' => 'instructions', + 'class' => 'column-instructions', + ]; + } + $evento_id = array_search('evento', $fields); if ($evento_id !== false) { $fields[$evento_id] = [ @@ -1410,6 +1419,7 @@ try { 'no_sortable_columns' => [ -1, -2, + 'column-instructions', ], 'ajax_postprocess' => 'process_datatables_item(item)', 'drawCallback' => 'process_datatables_callback(this, settings)', diff --git a/pandora_console/operation/events/events_marquee.php b/pandora_console/operation/events/events_marquee.php index 4834207172..b3332e56bf 100644 --- a/pandora_console/operation/events/events_marquee.php +++ b/pandora_console/operation/events/events_marquee.php @@ -17,7 +17,7 @@ error_reporting(1); $MAX_MARQUEE_EVENTS = 10; $MARQUEE_INTERVAL = 90; $MARQUEE_FONT_SIZE = '32px'; -$MARQUEE_SPEED = 12; +$MARQUEE_SPEED = 9; $output = ''; diff --git a/pandora_console/operation/reporting/reporting_viewer.php b/pandora_console/operation/reporting/reporting_viewer.php index e8431ddeb2..0bba865711 100755 --- a/pandora_console/operation/reporting/reporting_viewer.php +++ b/pandora_console/operation/reporting/reporting_viewer.php @@ -17,7 +17,6 @@ global $config; check_login(); enterprise_hook('open_meta_frame'); - $id_report = (int) get_parameter('id'); if (! $id_report) { diff --git a/pandora_console/operation/search_graphs.getdata.php b/pandora_console/operation/search_graphs.getdata.php index 4dc6f3ba74..4235ea40c6 100644 --- a/pandora_console/operation/search_graphs.getdata.php +++ b/pandora_console/operation/search_graphs.getdata.php @@ -43,7 +43,7 @@ if ($searchGraphs) { $totalGraphs = (int) db_get_value_filter('COUNT(id_graph) AS count', 'tgraph', $filter); - if (! $only_count && $totalGraphs > 0) { + if ($totalGraphs > 0) { $filter['limit'] = $config['block_size']; $filter['offset'] = (int) get_parameter('offset'); $graphs = db_get_all_rows_filter('tgraph', $filter, $columns); diff --git a/pandora_console/operation/search_policies.getdata.php b/pandora_console/operation/search_policies.getdata.php index a8c05ea071..5186f1f0a9 100644 --- a/pandora_console/operation/search_policies.getdata.php +++ b/pandora_console/operation/search_policies.getdata.php @@ -16,7 +16,7 @@ global $config; enterprise_include_once('include/functions_policies.php'); -$searchpolicies = check_acl($config['id'], 0, 'AW'); +$searchpolicies = check_acl($config['id_user'], 0, 'AW'); $selectpolicieIDUp = ''; $selectpolicieIDDown = ''; diff --git a/pandora_console/operation/snmpconsole/snmp_statistics.php b/pandora_console/operation/snmpconsole/snmp_statistics.php index afe05be977..076ca806d7 100755 --- a/pandora_console/operation/snmpconsole/snmp_statistics.php +++ b/pandora_console/operation/snmpconsole/snmp_statistics.php @@ -155,7 +155,7 @@ foreach ($traps_generated_by_source as $trap) { $row['source'] = ''.$trap['source'].''; } else { $agent_id = $agent['id_agente']; - $agent_name = ui_print_truncate_text($agent['nombre'], 'agent_medium', true, true, true, '[…]', ''); + $agent_name = ui_print_truncate_text($agent['alias'], 'agent_medium', true, true, true, '[…]', ''); $row['source'] = "'; $row['source'] .= "$agent_name"; } diff --git a/pandora_console/operation/snmpconsole/snmp_view.php b/pandora_console/operation/snmpconsole/snmp_view.php index c7f69b4109..677a7a625a 100755 --- a/pandora_console/operation/snmpconsole/snmp_view.php +++ b/pandora_console/operation/snmpconsole/snmp_view.php @@ -1,17 +1,31 @@ $name) { $i++; } -$url = 'index.php?sec=estado&'.'sec2=operation/snmpconsole/snmp_view&'.'filter_severity='.$filter_severity.'&'.'filter_fired='.$filter_fired.'&'.'free_search_string='.$free_search_string.'&'.'pagination='.$pagination.'&'.'offset='.$offset.'&'.'trap_type='.$trap_type.'&'.'group_by='.$group_by.'&'.'date_from_trap='.$date_from_trap.'&'.'date_to_trap='.$date_to_trap.'&'.'time_from_trap='.$time_from_trap.'&'.'time_to_trap='.$time_to_trap; +$url = 'index.php?sec=estado&sec2=operation/snmpconsole/snmp_view&filter_severity='.$filter_severity.'&filter_fired='.$filter_fired.'&free_search_string='.$free_search_string.'&pagination='.$pagination.'&offset='.$offset.'&trap_type='.$trap_type.'&group_by='.$group_by.'&date_from_trap='.$date_from_trap.'&date_to_trap='.$date_to_trap.'&time_from_trap='.$time_from_trap.'&time_to_trap='.$time_to_trap; $statistics['text'] = ''.html_print_image('images/op_reporting.png', true, ['title' => __('Statistics')]).''; $list['text'] = ''.html_print_image('images/op_snmp.png', true, ['title' => __('List')]).''; @@ -70,7 +84,7 @@ $list['active'] = true; if ($config['pure']) { $fullscreen['text'] = ''.html_print_image('images/normal_screen.png', true, ['title' => __('Normal screen')]).''; } else { - // Fullscreen + // Fullscreen. $fullscreen['text'] = ''.html_print_image('images/full_screen.png', true, ['title' => __('Full screen')]).''; } @@ -131,7 +145,7 @@ if (isset($_GET['check'])) { } } -// Mass-process DELETE +// Mass-process DELETE. if (isset($_POST['deletebt'])) { $trap_ids = get_parameter_post('snmptrapid', []); if (is_array($trap_ids) && check_acl($config['id_user'], 0, 'IW')) { @@ -161,7 +175,7 @@ if (isset($_POST['deletebt'])) { } } -// Mass-process UPDATE +// Mass-process UPDATE. if (isset($_POST['updatebt'])) { $trap_ids = get_parameter_post('snmptrapid', []); if (is_array($trap_ids) && check_acl($config['id_user'], 0, 'IW')) { @@ -178,14 +192,14 @@ if (isset($_POST['updatebt'])) { } } -// All traps +// All traps. $all_traps = db_get_all_rows_sql('SELECT DISTINCT source FROM ttrap'); if (empty($all_traps)) { $all_traps = []; } -// Set filters +// Set filters. $agents = []; $oids = []; $severities = get_priorities(); @@ -206,7 +220,7 @@ foreach ($all_traps as $trap) { $prea = array_keys($user_groups); $ids = join(',', $prea); -// Cuantos usuarios hay operadores con un grupo que exista y no lo tenga ningun usuario +// Cuantos usuarios hay operadores con un grupo que exista y no lo tenga ningun usuario. $user_in_group_wo_agents = db_get_value_sql('select count(DISTINCT(id_usuario)) from tusuario_perfil where id_usuario ="'.$config['id_user'].'" and id_perfil = 1 and id_grupo in (select id_grupo from tgrupo where id_grupo in ('.$ids.') and id_grupo not in (select id_grupo from tagente))'); switch ($config['dbtype']) { @@ -244,6 +258,10 @@ switch ($config['dbtype']) { } } break; + + default: + // Default. + break; } if (empty($address_by_user_groups)) { @@ -293,6 +311,10 @@ switch ($config['dbtype']) { ) OR source='' OR source NOT IN (SELECT direccion FROM tagente WHERE direccion IS NOT NULL)) %s ORDER BY timestamp DESC"; break; + + default: + // Default. + break; } switch ($config['dbtype']) { @@ -335,6 +357,10 @@ switch ($config['dbtype']) { ) OR source='' OR source NOT IN (SELECT direccion FROM tagente WHERE direccion IS NOT NULL)) %s"; break; + + default: + // Default. + break; } // $whereSubquery = 'WHERE 1=1'; @@ -372,6 +398,10 @@ if ($free_search_string != '') { text LIKE \'%'.$free_search_string.'%\' OR description LIKE \'%'.$free_search_string.'%\')'; break; + + default: + // Default. + break; } } @@ -422,7 +452,7 @@ if ($trap_type == 5) { $whereSubquery .= ' AND type = '.$trap_type; } -// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive +// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive. if ($group_by && $config['dbtype'] != 'oracle') { $where_without_group = $whereSubquery; $whereSubquery .= ' GROUP BY source,oid'; @@ -444,6 +474,10 @@ switch ($config['dbtype']) { $sql = sprintf($sql, $whereSubquery); $sql = oracle_recode_query($sql, $set); break; + + default: + // Default. + break; } $sql_all = sprintf($sql_all, $whereSubquery); @@ -458,7 +492,7 @@ $table->size = []; $table->size[0] = '120px'; $table->data = []; -// Alert status select +// Alert status select. $table->data[1][0] = ''.__('Alert').''; $table->data[1][1] = html_print_select( $alerted, @@ -470,7 +504,7 @@ $table->data[1][1] = html_print_select( true ); -// Block size for pagination select +// Block size for pagination select. $table->data[2][0] = ''.__('Block size for pagination').''; $paginations[25] = 25; $paginations[50] = 50; @@ -487,7 +521,7 @@ $table->data[2][1] = html_print_select( true ); -// Severity select +// Severity select. $table->data[1][2] = ''.__('Severity').''; $table->data[1][3] = html_print_select( $severities, @@ -499,7 +533,7 @@ $table->data[1][3] = html_print_select( true ); -// Status +// Status. $table->data[3][0] = ''.__('Status').''; $status_array[-1] = __('All'); @@ -515,7 +549,7 @@ $table->data[3][1] = html_print_select( true ); -// Free search (search by all alphanumeric fields) +// Free search (search by all alphanumeric fields). $table->data[2][3] = ''.__('Free search').''.ui_print_help_tip( __( 'Search by any alphanumeric field in the trap. @@ -542,7 +576,7 @@ $table->data[5][1] = html_print_input_text('time_from_trap', $time_from_trap, fa $table->data[5][2] = ''.__('To (Time)').''; $table->data[5][3] = html_print_input_text('time_to_trap', $time_to_trap, false, 15, 10, true); -// Type filter (ColdStart, WarmStart, LinkDown, LinkUp, authenticationFailure, Other) +// Type filter (ColdStart, WarmStart, LinkDown, LinkUp, authenticationFailure, Other). $table->data[6][1] = ''.__('Trap type').''.ui_print_help_tip(__('Search by trap type'), true); $trap_types = [ -1 => __('None'), @@ -565,14 +599,14 @@ $table->data[6][2] = html_print_select( false ); -// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive +// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive. if ($config['dbtype'] != 'oracle') { $table->data[3][3] = ''.__('Group by Enterprise String/IP').''; $table->data[3][4] = __('Yes').' '.html_print_radio_button('group_by', 1, '', $group_by, true).'  '; $table->data[3][4] .= __('No').' '.html_print_radio_button('group_by', 0, '', $group_by, true); } -$filter = '
'; +$filter = ''; $filter .= html_print_table($table, true); $filter .= '
'; $filter .= html_print_submit_button(__('Update'), 'search', false, 'class="sub upd"', true); @@ -595,9 +629,9 @@ $filter_resume['trap_type'] = $trap_types[$trap_type]; $traps = db_get_all_rows_sql($sql); $trapcount = (int) db_get_value_sql($sql_count); -// No traps +// No traps. if (empty($traps)) { - // Header + // Header. ui_print_page_header( __('SNMP Console'), 'images/op_snmp.png', @@ -638,24 +672,24 @@ if (empty($traps)) { echo '
"; - echo grafico_eventos_usuario(320, 296); + echo grafico_eventos_usuario(320, 280); echo '
"; - echo grafico_eventos_grupo(300, 200, $where); + echo grafico_eventos_grupo(300, 250, $where); echo '"; @@ -101,7 +101,7 @@ if (!users_is_admin()) { ]; } - echo graph_events_validated(320, 296, $extra_filter); + echo graph_events_validated(320, 250, $extra_filter); echo '
'.''; + $string .= ''; } if ($group_by) { @@ -1060,7 +1095,7 @@ if ($traps !== false) { } } -// No matching traps +// No matching traps. if ($idx == 0) { echo '
'.__('No matching traps found').'
'; } else { diff --git a/pandora_console/operation/visual_console/legacy_public_view.php b/pandora_console/operation/visual_console/legacy_public_view.php index 18d8e2ca55..ab6def4f70 100644 --- a/pandora_console/operation/visual_console/legacy_public_view.php +++ b/pandora_console/operation/visual_console/legacy_public_view.php @@ -40,6 +40,9 @@ ob_start('ui_process_page_head'); // Enterprise main enterprise_include('index.php'); +$url_css = ui_get_full_url('include/styles/visual_maps.css', false, false, false); +echo ''; + require_once 'include/functions_visual_map.php'; $hash = get_parameter('hash'); @@ -96,31 +99,41 @@ if ($layout) { echo '
'; } -// Floating menu - Start +// Floating menu - Start. echo '
'; echo ''; echo '
'; -// Floating menu - End -// QR code dialog + +// QR code dialog. echo ''; -ui_require_jquery_file('countdown'); -ui_require_javascript_file('wz_jsgraphics'); -ui_require_javascript_file('pandora_visual_console'); +ui_require_jquery_file('countdown', 'include/javascript/', true); +ui_require_javascript_file('wz_jsgraphics', 'include/javascript/', true); +ui_require_javascript_file('pandora_visual_console', 'include/javascript/', true); $ignored_params['refr'] = ''; ?> @@ -175,7 +188,7 @@ $ignored_params['refr'] = ''; var controls = document.getElementById('vc-controls'); autoHideElement(controls, 1000); - $('select#refr').change(function (event) { + $('#vc-controls').change(function (event) { refr = Number.parseInt(event.target.value, 10); startCountDown(refr, false); }); diff --git a/pandora_console/operation/visual_console/public_view.php b/pandora_console/operation/visual_console/public_view.php index 212387f8c0..7e899c3718 100644 --- a/pandora_console/operation/visual_console/public_view.php +++ b/pandora_console/operation/visual_console/public_view.php @@ -44,6 +44,9 @@ ob_start('ui_process_page_head'); // Enterprise main. enterprise_include('index.php'); +$url_css = ui_get_full_url('include/styles/visual_maps.css', false, false, false); +echo ''; + require_once 'include/functions_visual_map.php'; $hash = (string) get_parameter('hash'); @@ -136,7 +139,7 @@ if (!users_can_manage_group_all('AR')) { } $ignored_params['refr'] = ''; -ui_require_javascript_file('pandora_visual_console'); +ui_require_javascript_file('pandora_visual_console', 'include/javascript/', true); include_javascript_d3(); visual_map_load_client_resources(); @@ -159,6 +162,10 @@ $visualConsoleItems = VisualConsole::getItemsFromDB( var props = ; var items = ; var baseUrl = ""; + + var controls = document.getElementById('vc-controls'); + autoHideElement(controls, 1000); + var handleUpdate = function (prevProps, newProps) { if (!newProps) return; diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index d5fd693092..57c654851d 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.738 -%define release 190821 +%define release 190919 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index 076cf55a11..505c7f7640 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.738 -%define release 190821 +%define release 190919 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index 7f259bb853..8127bedc75 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.738 -%define release 190821 +%define release 190919 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index d1de66ab07..232b340b46 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1455,6 +1455,7 @@ CREATE TABLE IF NOT EXISTS `treport_content` ( `current_month` TINYINT(1) DEFAULT '1', `failover_mode` tinyint(1) DEFAULT '1', `failover_type` tinyint(1) DEFAULT '1', + `uncompressed_module` TINYINT DEFAULT '0', PRIMARY KEY(`id_rc`), FOREIGN KEY (`id_report`) REFERENCES treport(`id_report`) ON UPDATE CASCADE ON DELETE CASCADE @@ -2998,6 +2999,7 @@ CREATE TABLE IF NOT EXISTS `treport_content_template` ( `current_month` TINYINT(1) DEFAULT '1', `failover_mode` tinyint(1) DEFAULT '1', `failover_type` tinyint(1) DEFAULT '1', + `uncompressed_module` TINYINT DEFAULT '0', PRIMARY KEY(`id_rc`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index e36a1a6fbf..a02f88fe5f 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -109,7 +109,7 @@ INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_report_front_logo', 'images/pandora_logo_white.jpg'), ('custom_report_front_header', ''), ('custom_report_front_footer', ''), -('MR', 30), +('MR', 31), ('identification_reminder', 1), ('identification_reminder_timestamp', 0), ('current_package_enterprise', '738'), diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index 7a7ae4d5d6..ad82103ea8 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.738-190821 +Version: 7.0NG.738-190919 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 0f82ab810e..33b89f2f2e 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.738-190821" +pandora_version="7.0NG.738-190919" package_cpan=0 package_pandora=1 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 627d6f736e..7941e627b6 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -45,7 +45,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.738"; -my $pandora_build = "190821"; +my $pandora_build = "190919"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 3104345f5e..e1556d74b6 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -1205,13 +1205,13 @@ sub pandora_execute_action ($$$$$$$$$;$) { # Address - $field1 = subst_alert_macros ($field1, \%macros, $pa_config, $dbh, $agent, $module); + $field1 = subst_alert_macros ($field1, \%macros, $pa_config, $dbh, $agent, $module, $alert); # Subject - $field2 = subst_alert_macros ($field2, \%macros, $pa_config, $dbh, $agent, $module); + $field2 = subst_alert_macros ($field2, \%macros, $pa_config, $dbh, $agent, $module, $alert); # Message - $field3 = subst_alert_macros ($field3, \%macros, $pa_config, $dbh, $agent, $module); + $field3 = subst_alert_macros ($field3, \%macros, $pa_config, $dbh, $agent, $module, $alert); # Content - $field4 = subst_alert_macros ($field4, \%macros, $pa_config, $dbh, $agent, $module); + $field4 = subst_alert_macros ($field4, \%macros, $pa_config, $dbh, $agent, $module, $alert); if($field4 eq ""){ $field4 = "text/html"; @@ -3943,8 +3943,8 @@ sub pandora_evaluate_snmp_alerts ($$$$$$$$$) { ########################################################################## # Search string for macros and substitutes them with their values. ########################################################################## -sub subst_alert_macros ($$;$$$$) { - my ($string, $macros, $pa_config, $dbh, $agent, $module) = @_; +sub subst_alert_macros ($$;$$$$$) { + my ($string, $macros, $pa_config, $dbh, $agent, $module, $alert) = @_; my $macro_regexp = join('|', keys %{$macros}); @@ -3952,14 +3952,14 @@ sub subst_alert_macros ($$;$$$$) { if (defined($string) && $string =~ m/^(?:(")(?:.*)"|(')(?:.*)')$/) { my $quote = $1 ? $1 : $2; $subst_func = sub { - my $macro = on_demand_macro($pa_config, $dbh, shift, $macros, $agent, $module); + my $macro = on_demand_macro($pa_config, $dbh, shift, $macros, $agent, $module,$alert); $macro =~ s/'/'\\''/g; # close, escape, open return decode_entities($quote . "'" . $macro . "'" . $quote); # close, quote, open }; } else { $subst_func = sub { - my $macro = on_demand_macro($pa_config, $dbh, shift, $macros, $agent, $module); + my $macro = on_demand_macro($pa_config, $dbh, shift, $macros, $agent, $module, $alert); return decode_entities($macro); }; } @@ -3993,8 +3993,8 @@ sub subst_column_macros ($$;$$$$) { ########################################################################## # Load macros that access the database on demand. ########################################################################## -sub on_demand_macro($$$$$$) { - my ($pa_config, $dbh, $macro, $macros, $agent, $module) = @_; +sub on_demand_macro($$$$$$;$) { + my ($pa_config, $dbh, $macro, $macros, $agent, $module,$alert) = @_; # Static macro. return $macros->{$macro} if (defined($macros->{$macro})); @@ -4010,7 +4010,7 @@ sub on_demand_macro($$$$$$) { } elsif ($macro eq '_moduletags_') { return (defined ($module)) ? pandora_get_module_url_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : ''; } elsif ($macro eq '_policy_') { - return (defined ($module)) ? enterprise_hook('get_policy_name', [$dbh, $module->{'id_policy_module'}]) : ''; + return (defined ($alert)) ? enterprise_hook('get_policy_name_policy_alerts_id', [$dbh, $alert->{'id_policy_alerts'}]) : ''; } elsif ($macro eq '_email_tag_') { return (defined ($module)) ? pandora_get_module_email_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : ''; } elsif ($macro eq '_phone_tag_') { diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index f1d3dd3938..1fd4edcf4a 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -32,7 +32,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.738"; -my $pandora_build = "190821"; +my $pandora_build = "190919"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 4fe138ff1a..2376c07b2c 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.738 -%define release 190821 +%define release 190919 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index cf930a0ef9..58a9a051fc 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.738 -%define release 190821 +%define release 190919 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index fb7fb32dfe..40e9c53839 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.738" -PI_BUILD="190821" +PI_BUILD="190919" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index 7eee0698fa..e0ba24f054 100644 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -34,7 +34,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.738 PS190821"; +my $version = "7.0NG.738 PS190919"; # Pandora server configuration my %conf; @@ -136,7 +136,7 @@ sub pandora_purgedb ($$) { pandora_delete_old_export_data ($dbh, $ulimit_timestamp); # Delete sessions data - pandora_delete_old_session_data ($dbh, $ulimit_timestamp); + pandora_delete_old_session_data (\%conf, $dbh, $ulimit_timestamp); # Delete old inventory data @@ -678,6 +678,7 @@ sub pandora_load_config_pdb ($) { $conf->{'_netflow_nfexpire'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'netflow_nfexpire'"); $conf->{'_netflow_path'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'netflow_path'"); $conf->{'_delete_notinit'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'delete_notinit'"); + $conf->{'_session_timeout'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'session_timeout'"); $conf->{'_big_operation_step_datos_purge'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'big_operation_step_datos_purge'"); $conf->{'_small_operation_step_datos_purge'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'small_operation_step_datos_purge'"); @@ -990,12 +991,28 @@ sub pandora_delete_old_export_data { # Delete old session data. ############################################################################## sub pandora_delete_old_session_data { - my ($dbh, $ulimit_timestamp) = @_; + my ($conf, $dbh, $ulimit_timestamp) = @_; + + my $session_timeout = $conf->{'_session_timeout'}; + + if ($session_timeout ne '') { + if ($session_timeout == -1) { + # The session expires in 10 years + $session_timeout = 315576000; + } else { + $session_timeout *= 60; + } + + $ulimit_timestamp = time() - $session_timeout; + } log_message ('PURGE', "Deleting old session data from tsessions_php\n"); while(db_delete_limit ($dbh, 'tsessions_php', 'last_active < ?', $SMALL_OPERATION_STEP, $ulimit_timestamp) ne '0E0') { usleep (10000); }; + + db_do ($dbh, "DELETE FROM tsessions_php WHERE + data IS NULL OR id_session REGEXP '^cron-'"); } ############################################################################### diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 79ac99404b..ab951ab0f7 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.738 PS190821"; +my $version = "7.0NG.738 PS190919"; # save program name for logging my $progname = basename($0);
'.''.__('Variable bindings:').' '; if ($group_by) { - $new_url = 'index.php?sec=snmpconsole&sec2=operation/snmpconsole/snmp_view&'.'filter_severity='.$filter_severity.'&'.'filter_fired='.$filter_fired.'&'.'filter_status='.$filter_status.'&'.'refresh='.((int) get_parameter('refresh', 0)).'&'.'pure='.$config['pure'].'&'.'group_by=0&'.'free_search_string='.$free_search_string.'&'.'date_from_trap='.$date_from_trap.'&'.'date_to_trap='.$date_to_trap.'&'.'time_from_trap='.$time_from_trap.'&'.'time_to_trap='.$time_to_trap; + $new_url = 'index.php?sec=snmpconsole&sec2=operation/snmpconsole/snmp_view&filter_severity='.$filter_severity.'&filter_fired='.$filter_fired.'&filter_status='.$filter_status.'&refresh='.((int) get_parameter('refresh', 0)).'&pure='.$config['pure'].'&group_by=0&free_search_string='.$free_search_string.'&date_from_trap='.$date_from_trap.'&date_to_trap='.$date_to_trap.'&time_from_trap='.$time_from_trap.'&time_to_trap='.$time_to_trap; $string .= ''.__('See more details').''; } else { - // Print binding vars separately + // Print binding vars separately. $binding_vars = explode("\t", $trap['oid_custom']); foreach ($binding_vars as $var) { $string .= $var.'
'; @@ -1007,7 +1042,7 @@ if ($traps !== false) { break; } - $string .= '
'.''.__('Trap type:').''.''.$desc_trap_type.'
'.__('Trap type:').''.$desc_trap_type.'