<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

if (! isset($centreon)) {
    exit();
}

require_once './include/monitoring/common-Func.php';
require_once './class/centreonDB.class.php';
require_once './class/centreonGMT.class.php';
require_once realpath(__DIR__ . '/../../../../config/centreon.config.php');

function createArrayStats($arrayFromJson)
{
    $io = ['class' => 'stats_lv1'];

    if (isset($arrayFromJson['state'])) {
        $io[_('State')]['value'] = $arrayFromJson['state'];
        if ($arrayFromJson['state'] == 'disconnected') {
            $io[_('State')]['class'] = 'badge service_critical';
        } elseif (
            $arrayFromJson['state'] == 'listening'
            || $arrayFromJson['state'] == 'connected'
            || $arrayFromJson['state'] == 'connecting'
        ) {
            $io[_('State')]['class'] = 'badge service_ok';
        } elseif ($arrayFromJson['state'] == 'sleeping' || $arrayFromJson['state'] == 'blocked') {
            $io[_('State')]['class'] = 'badge service_warning';
        }
    }

    if (isset($arrayFromJson['status']) && $arrayFromJson['status']) {
        $io[_('Status')] = ['value' => $arrayFromJson['status'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['last_event_at']) && $arrayFromJson['last_event_at'] != -1) {
        $io[_('Last event at')] = ['value' => $arrayFromJson['last_event_at'], 'isTimestamp' => true];
    }

    if (isset($arrayFromJson['last_connection_attempt']) && $arrayFromJson['last_connection_attempt'] != -1) {
        $io[_('Last connection attempt')] = ['value' => $arrayFromJson['last_connection_attempt'], 'isTimestamp' => true];
    }

    if (isset($arrayFromJson['last_connection_success']) && $arrayFromJson['last_connection_success'] != -1) {
        $io[_('Last connection success')] = ['value' => $arrayFromJson['last_connection_success'], 'isTimestamp' => true];
    }

    if (isset($arrayFromJson['one_peer_retention_mode'])) {
        $io[_('One peer retention mode')] = ['value' => $arrayFromJson['one_peer_retention_mode'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['event_processing_speed'])) {
        $io[_('Event processing speed')] = ['value' => sprintf('%.2f events/s', $arrayFromJson['event_processing_speed']), 'isTimestamp' => false];
    }

    if (
        isset($arrayFromJson['queue file'], $arrayFromJson['queue file enabled'])

        && $arrayFromJson['queue file enabled'] != 'no'
    ) {
        $io[_('Queue file')] = ['value' => $arrayFromJson['queue file'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['queue file enabled'])) {
        $io[_('Queued file enabled')] = ['value' => $arrayFromJson['queue file enabled'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['queued_events'])) {
        $io[_('Queued events')] = ['value' => $arrayFromJson['queued_events'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['memory file'])) {
        $io[_('Memory file')] = ['value' => $arrayFromJson['memory file'], 'isTimestamp' => false];
    }

    if (isset($arrayFromJson['read_filters']) && $arrayFromJson['read_filters']) {
        if ($arrayFromJson['read_filters'] != 'all') {
            $io[_('Input accepted events type')] = ['value' => substr($arrayFromJson['read_filters'], 22), 'isTimestamp' => false];
        } else {
            $io[_('Input accepted events type')] = ['value' => $arrayFromJson['read_filters'], 'isTimestamp' => false];
        }
    }

    if (isset($arrayFromJson['write_filters']) && $arrayFromJson['write_filters']) {
        if ($arrayFromJson['write_filters'] != 'all') {
            $io[_('Output accepted events type')] = ['value' => substr($arrayFromJson['write_filters'], 2), 'isTimestamp' => false];
        } else {
            $io[_('Output accepted events type')] = ['value' => $arrayFromJson['write_filters'], 'isTimestamp' => false];
        }
    }

    return $io;
}

function parseStatsFile($statfile)
{
    // handle path traversal vulnerability
    if (str_contains($statfile, '..')) {
        throw new Exception('Path traversal found');
    }
    $jsonc_content = file_get_contents($statfile);
    $json_stats = json_decode($jsonc_content, true);

    $lastmodif = $json_stats['now'];

    $result = ['lastmodif' => $lastmodif, 'modules' => [], 'io' => []];

    foreach ($json_stats as $key => $value) {
        if (preg_match('/endpoint \(?(.*[^()])\)?/', $key, $matches)) {
            if (preg_match('/.*external commands.*/', $matches[1])) {
                $matches[1] = 'external-commands';
            }

            if (
                (preg_match('/.*external commands.*/', $key) && $json_stats[$key]['state'] != 'disconnected')
                || ! preg_match('/.*external commands.*/', $key)
            ) {
                $keySepByDash = explode('-', $key);
                $keySepBySpace = explode(' ', $key);
                $result['io'][$matches[1]] = createArrayStats($json_stats[$key]);
                $result['io'][$matches[1]]['type'] = end($keySepByDash);
                $result['io'][$matches[1]]['id'] = end($keySepBySpace);
                $result['io'][$matches[1]]['id'] = rtrim($result['io'][$matches[1]]['id'], ')');

                // force type of io
                if (preg_match('/.*external commands.*/', $key)) {
                    $result['io'][$matches[1]]['type'] = 'input';
                } elseif (
                    preg_match(
                        '/.*(central-broker-master-sql|centreon-broker-master-rrd'
                        . '|central-broker-master-perfdata|central-broker-master-unified-sql).*/',
                        $key
                    )
                ) {
                    $result['io'][$matches[1]]['type'] = 'output';
                } elseif (preg_match('/.*(centreon-bam-monitoring|centreon-bam-reporting).*/', $key)) {
                    $result['io'][$matches[1]]['type'] = 'output';
                }

                // manage failover output
                if (isset($json_stats[$key]['failover'])) {
                    $result['io'][$matches[1] . '-failover'] = createArrayStats($json_stats[$key]['failover']);
                    $result['io'][$matches[1] . '-failover']['type'] = 'output';
                    $result['io'][$matches[1] . '-failover']['class'] = 'stats_lv2';
                    $result['io'][$matches[1] . '-failover']['id'] = $matches[1] . '-failover';
                }

                // manage peers input
                if (isset($json_stats[$key]['peers'])) {
                    $arrayPeers = explode(',', $json_stats[$key]['peers']);
                    $counter = count($arrayPeers);
                    for ($i = 1; $i < $counter; $i++) {
                        $peerName = trim($arrayPeers[$i]);
                        $id = str_replace(':', '_', $peerName);
                        $id = str_replace('.', '_', $id);
                        $result['io'][$matches[1]]['peers'][$i] = $peerName;
                        $result['io'][$peerName] = createArrayStats($json_stats[$key][$matches[1] . '-' . $i]);
                        $result['io'][$peerName]['type'] = 'input';
                        $result['io'][$peerName]['class'] = 'stats_lv2';
                        $result['io'][$peerName]['id'] = $id . '-peers';
                    }
                }
            }
        }

        // Create list of loaded modules
        if (preg_match('/module\s*\/.*\/\d+\-(.*)\.so/', $key, $matches)) {
            $result['modules'][$matches[1]] = $json_stats[$key]['state'];
        }
    }

    return $result;
}

// Init GMT class
$centreonGMT = new CentreonGMT();
$centreonGMT->getMyGMTFromSession(session_id());

$form = new HTML_QuickFormCustom('form', 'post', '?p=' . $p);

// Get Poller List
$pollerList = [];
$DBRESULT = $pearDB->query('SELECT * FROM `nagios_server` WHERE `ns_activate` = 1 ORDER BY `name`');
while ($data = $DBRESULT->fetchRow()) {
    if ($data['localhost']) {
        $defaultPoller = $data['id'];
    }
    $pollerList[$data['id']] = HtmlSanitizer::createFromString($data['name'])->sanitize()->getString();
}
$DBRESULT->closeCursor();

// Get poller ID
$selectedPoller = isset($_POST['pollers']) && $_POST['pollers'] != ''
    ? $_POST['pollers']
    : $defaultPoller;
if (! isset($selectedPoller)) {
    $tmpKeys = array_keys($pollerList);
    $selectedPoller = $tmpKeys[0];
    unset($tmpKeys);
}

$form->addElement('select', 'pollers', _('Poller'), $pollerList, ['onChange' => 'this.form.submit();']);
$form->setDefaults(['pollers' => $selectedPoller]);
$pollerName = $pollerList[$selectedPoller];

$path = './include/Administration/brokerPerformance/';

// Smarty template initialization
$tpl = SmartyBC::createSmartyTemplate($path, './');

$renderer = new HTML_QuickForm_Renderer_ArraySmarty($tpl);
$form->accept($renderer);
$tpl->assign('form', $renderer->toArray());

// Message
$lang = [];
$lang['modules'] = _('Modules');
$lang['updated'] = _('Last update');
$lang['peers'] = _('Peers');
$lang['input'] = _('Input');
$lang['output'] = _('Output');
$tpl->assign('lang', $lang);
$tpl->assign('poller_name', $pollerName);

// Get the stats file name
$queryStatName = 'SELECT config_name, cache_directory '
    . 'FROM cfg_centreonbroker '
    . "WHERE stats_activate = '1' "
    . 'AND ns_nagios_server = :id';
try {
    $stmt = $pearDB->prepare($queryStatName);
    $stmt->bindParam(':id', $selectedPoller, PDO::PARAM_INT);
    $stmt->execute();
    if (! $stmt->rowCount()) {
        $tpl->assign('msg_err', _('No statistics file defined for this poller'));
    }
    $perf_info = [];
    $perf_err = [];
    while ($row = $stmt->fetch()) {
        $statsfile = $row['cache_directory'] . '/' . basename($row['config_name']) . '-stats.json';
        if ($defaultPoller != $selectedPoller) {
            $statsfile = _CENTREON_CACHEDIR_ . '/broker-stats/' . $selectedPoller . '/' . $row['config_name'] . '.json';
        }

        /**
         * check if file exists, is readable and inside proper folder
         */
        if (
            ! file_exists($statsfile)
            || ! is_readable($statsfile)
            || ((! str_starts_with(realpath($statsfile), _CENTREON_VARLIB_))
            && (! str_starts_with(realpath($statsfile), _CENTREON_CACHEDIR_)))
        ) {
            $perf_err[$row['config_name']] = _('Cannot open statistics file');
        } else {
            $perf_info[$row['config_name']] = parseStatsFile($statsfile);
        }
    }
    $tpl->assign('perf_err', $perf_err);
    $tpl->assign('perf_info_array', $perf_info);
} catch (PDOException $e) {
    $tpl->assign('msg_err', _('Error in getting stats filename'));
}

$tpl->display('brokerPerformance.ihtml');
