<?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
 *
 */

ini_set('display_errors', 'Off');

use App\Kernel;
use Centreon\Domain\Contact\Interfaces\ContactServiceInterface;
use Centreon\Domain\Entity\Task;

require_once realpath(__DIR__ . '/../../../../../config/centreon.config.php');
require_once realpath(__DIR__ . '/../../../../../config/bootstrap.php');
require_once realpath(__DIR__ . '/../../../../../bootstrap.php');
require_once _CENTREON_PATH_ . 'www/include/configuration/configGenerate/DB-Func.php';
require_once _CENTREON_PATH_ . 'www/class/centreonDB.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonSession.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreon.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonXML.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonACL.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonUser.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonConfigCentreonBroker.php';

if (! defined('STATUS_OK')) {
    define('STATUS_OK', 0);
}
if (! defined('STATUS_NOK')) {
    define('STATUS_NOK', 1);
}

$pearDB = new CentreonDB();

$xml = new CentreonXML();
$okMsg = "<b><font color='green'>OK</font></b>";
$nokMsg = "<b><font color='red'>NOK</font></b>";

if (isset($_SERVER['HTTP_X_AUTH_TOKEN'])) {
    $kernel = new Kernel('prod', false);
    $kernel->boot();

    $container = $kernel->getContainer();
    if ($container == null) {
        throw new Exception(_('Unable to load the Symfony container'));
    }
    $contactService = $container->get(ContactServiceInterface::class);
    $contact = $contactService->findByAuthenticationToken($_SERVER['HTTP_X_AUTH_TOKEN']);
    if ($contact === null) {
        $xml->startElement('response');
        $xml->writeElement('status', $nokMsg);
        $xml->writeElement('statuscode', STATUS_NOK);
        $xml->writeElement('error', 'Contact not found');
        $xml->endElement();

        if (! headers_sent()) {
            header('Content-Type: application/xml');
            header('Cache-Control: no-cache');
            header('Expires: 0');
            header('Cache-Control: no-cache, must-revalidate');
        }

        $xml->output();

        exit();
    }
    $centreon = new Centreon([
        'contact_id' => $contact->getId(),
        'contact_name' => $contact->getName(),
        'contact_alias' => $contact->getAlias(),
        'contact_email' => $contact->getEmail(),
        'contact_admin' => $contact->isAdmin(),
        'contact_lang' => null,
        'contact_passwd' => null,
        'contact_autologin_key' => null,
        'contact_location' => null,
        'reach_api' => $contact->hasAccessToApiConfiguration(),
        'reach_api_rt' => $contact->hasAccessToApiRealTime(),
        'show_deprecated_pages' => false,
        'show_deprecated_custom_views' => false,
    ]);
} else {
    // Check Session
    CentreonSession::start(1);
    if (! CentreonSession::checkSession(session_id(), $pearDB)) {
        echo 'Bad Session';

        exit();
    }
    $centreon = $_SESSION['centreon'];
}

if (! isset($_POST['poller']) || ! $centreon->user->access->checkAction('generate_cfg')) {
    exit;
}

/**
 * List of error from php
 */
global $generatePhpErrors;
global $dependencyInjector;

$generatePhpErrors = [];
$pollers = explode(',', $_POST['poller']);

// Add task to export files if there is a remote
$pollerParams = [];
foreach ($pollers as $index => $pollerId) {
    if (is_numeric($pollerId)) {
        $pollerParams[':poller_' . $index] = $pollerId;
    }
}

// SELECT Remote Servers from selected pollers
// Then add all simple pollers linked directly to those Remote Servers
// Then add all pollers which have an additional link to those Remote Servers
$statementRemotes = $pearDB->prepare(
    'SELECT ns.id
    FROM nagios_server AS ns
    JOIN platform_topology AS pt ON (ns.id = pt.server_id)
    WHERE ns.id IN (' . implode(',', array_keys($pollerParams)) . ')
    AND pt.type = "remote"
    UNION
    SELECT ns1.id
    FROM nagios_server AS ns1
    JOIN platform_topology AS pt ON (ns1.id = pt.server_id)
    JOIN nagios_server AS ns2 ON ns1.id = ns2.remote_id
    WHERE ns2.id IN (' . implode(',', array_keys($pollerParams)) . ')
    AND pt.type = "remote"
    UNION
    SELECT ns1.id
    FROM nagios_server AS ns1
    JOIN platform_topology AS pt ON (ns1.id = pt.server_id)
    JOIN rs_poller_relation AS rspr ON rspr.remote_server_id = ns1.id
    WHERE rspr.poller_server_id IN (' . implode(',', array_keys($pollerParams)) . ')
    AND pt.type = "remote"'
);
foreach ($pollerParams as $key => $value) {
    $statementRemotes->bindValue($key, $value, PDO::PARAM_INT);
}
$statementRemotes->execute();
$remotesResults = $statementRemotes->fetchAll(PDO::FETCH_ASSOC);

if (! empty($remotesResults)) {
    foreach ($remotesResults as $remote) {
        $linkedStatement = $pearDB->prepare(
            'SELECT id
            FROM nagios_server
            WHERE remote_id = :remote_id
            UNION
            SELECT poller_server_id AS id
            FROM rs_poller_relation
            WHERE remote_server_id = :remote_id'
        );
        $linkedStatement->bindValue(':remote_id', $remote['id'], PDO::PARAM_INT);
        $linkedStatement->execute();
        $linkedResults = $linkedStatement->fetchAll(PDO::FETCH_ASSOC);

        $exportParams = [
            'server' => $remote['id'],
            'pollers' => [],
        ];

        $exportParams['pollers'] = ! empty($linkedResults) ? array_column($linkedResults, 'id') : [$remote['id']];

        $dependencyInjector['centreon.taskservice']->addTask(Task::TYPE_EXPORT, ['params' => $exportParams]);
    }
}

/**
 * The error handler for get error from PHP
 *
 * @see set_error_handler
 */
$log_error = function ($errno, $errstr, $errfile, $errline) {
    global $generatePhpErrors;
    if (! (error_reporting() && $errno)) {
        return;
    }

    switch ($errno) {
        case E_ERROR:
        case E_USER_ERROR:
        case E_CORE_ERROR:
            $generatePhpErrors[] = ['error', $errstr];
            break;
        case E_WARNING:
        case E_USER_WARNING:
        case E_CORE_WARNING:
            $generatePhpErrors[] = ['warning', $errstr];
            break;
    }

    return true;
};

try {
    $ret = [];
    $ret['host'] = $pollers;

    chdir(_CENTREON_PATH_ . 'www');
    $nagiosCFGPath = _CENTREON_CACHEDIR_ . '/config/engine/';
    $centreonBrokerPath = _CENTREON_CACHEDIR_ . '/config/broker/';
    $vmWareConfigPath = _CENTREON_CACHEDIR_ . '/config/vmware/';

    // Set new error handler
    set_error_handler($log_error);

    // Centcore pipe path
    $centcore_pipe = _CENTREON_VARLIB_ . '/centcore.cmd';

    $tab_server = [];
    $tabs = $centreon->user->access->getPollerAclConf(['fields' => ['name', 'id', 'localhost'], 'order' => ['name'], 'conditions' => ['ns_activate' => '1'], 'keys' => ['id']]);

    foreach ($tabs as $tab) {
        if (isset($ret['host']) && ($ret['host'] == 0 || in_array($tab['id'], $ret['host']))) {
            $tab_server[$tab['id']] = ['id' => $tab['id'], 'name' => $tab['name'], 'localhost' => $tab['localhost']];
        }
    }

    foreach ($tab_server as $host) {
        if (isset($pollers) && ($pollers == 0 || in_array($host['id'], $pollers))) {
            $listBrokerFile = glob($centreonBrokerPath . $host['id'] . '/*.{xml,json,cfg,sql}', GLOB_BRACE);
            $listVmWareFile = glob($vmWareConfigPath . $host['id'] . '/*.json', GLOB_BRACE);
            if (isset($host['localhost']) && $host['localhost'] == 1) {
                // Check if monitoring engine's configuration directory existss
                $dbResult = $pearDB->query("
                    SELECT cfg_dir FROM cfg_nagios, nagios_server
                    WHERE nagios_server.id = cfg_nagios.nagios_server_id
                    AND nagios_server.localhost = '1'
                    ORDER BY cfg_nagios.nagios_activate
                    DESC LIMIT 1");

                $nagiosCfg = $dbResult->fetch();

                if (! is_dir($nagiosCfg['cfg_dir'])) {
                    throw new Exception(
                        sprintf(
                            _(
                                "Could not find configuration directory '%s' for monitoring engine '%s'.
                                 Please check its path or create it"
                            ),
                            $nagiosCfg['cfg_dir'],
                            $host['name']
                        )
                    );
                }
                // Copy monitoring engine's configuration files
                foreach (glob($nagiosCFGPath . $host['id'] . '/*.{json,cfg}', GLOB_BRACE) as $filename) {
                    $targetFilePath = rtrim($nagiosCfg['cfg_dir'], '/') . '/' . basename($filename);
                    $succeded = @copy($filename, $targetFilePath);
                    if (! $succeded) {
                        throw new Exception(
                            sprintf(
                                _(
                                    "Could not write to file '%s' for monitoring engine '%s'. Please add writing
                                     permissions for the webserver's user"
                                ),
                                basename($filename),
                                $host['name']
                            )
                        );
                    }
                    if (posix_getuid() === fileowner($targetFilePath)) {
                        @chmod($targetFilePath, 0664);
                    }
                }
                // Centreon Broker configuration
                if (count($listBrokerFile) > 0) {
                    $centreonBrokerDirCfg = getCentreonBrokerDirCfg($host['id']);
                    if (! is_null($centreonBrokerDirCfg)) {
                        if (! is_dir($centreonBrokerDirCfg)) {
                            if (! mkdir($centreonBrokerDirCfg, 0755)) {
                                throw new Exception(
                                    sprintf(
                                        _(
                                            "Centreon Broker's configuration directory '%s' does not exist and could not
                                             be created for monitoring engine '%s'. Please check its path or create it"
                                        ),
                                        $centreonBrokerDirCfg,
                                        $host['name']
                                    )
                                );
                            }
                        }
                        foreach ($listBrokerFile as $fileCfg) {
                            $targetFilePath = rtrim($centreonBrokerDirCfg, '/') . '/' . basename($fileCfg);
                            $succeded = @copy($fileCfg, $targetFilePath);
                            if (! $succeded) {
                                throw new Exception(
                                    sprintf(
                                        _(
                                            "Could not write to Centreon Broker's configuration file '%s' for monitoring
                                             engine '%s'. Please add writing permissions for the webserver's user"
                                        ),
                                        basename($fileCfg),
                                        $host['name']
                                    )
                                );
                            }
                            if (posix_getuid() === fileowner($targetFilePath)) {
                                @chmod($targetFilePath, 0664);
                            }
                        }
                    }
                }
                /**
                 * VMWare configuration
                 */
                if (! is_array($listVmWareFile) || count($listVmWareFile) != 1) {
                    throw new Exception(
                        sprintf(
                            <<<'MSG'
                                There must be one and only one VMWare configuration file for monitoring engine '%s'.
                                Please check its path or create it
                                MSG,
                            $host['name']
                        )
                    );
                }
                if (! copy($listVmWareFile[0], _CENTREON_ETC_ . '/' . 'centreon_vmware.json')) {
                    throw new Exception(sprintf(
                        <<<'MSG'
                            Could not write to VMWare's configuration file '%s' for monitoring server '%s'.
                            Please add writing permissions for the webserver's user.
                            MSG,
                        basename($listVmWareFile[0] ?? ''),
                        $host['name']
                    ));
                }
            } else {
                passthru(
                    escapeshellcmd("echo 'SENDCFGFILE:{$host['id']}'") . ' >> ' . escapeshellcmd($centcore_pipe),
                    $return
                );
                if ($return) {
                    throw new Exception(_('Could not write into centcore.cmd. Please check file permissions.'));
                }
                if (! isset($msg_restart[$host['id']])) {
                    $msg_restart[$host['id']] = '';
                }
                $msg_restart[$host['id']] .= _('<br><b>Centreon : </b>All configuration will be send to '
                    . $host['name'] . ' by centcore in several minutes.');
            }
        }
    }
    $xml->startElement('response');
    $xml->writeElement('status', $okMsg);
    $xml->writeElement('statuscode', STATUS_OK);
} catch (Exception $e) {
    $xml->startElement('response');
    $xml->writeElement('status', $nokMsg);
    $xml->writeElement('statuscode', STATUS_NOK);
    $xml->writeElement('error', $e->getMessage());
}
// Restore default error handler
restore_error_handler();

// Add error form php
$xml->startElement('errorsPhp');
foreach ($generatePhpErrors as $error) {
    if ($error[0] == 'error') {
        $errmsg = '<span style="color: red;">Error</span><span style="margin-left: 5px;">' . $error[1] . '</span>';
    } else {
        $errmsg = '<span style="color: orange;">Warning</span><span style="margin-left: 5px;">' . $error[1] . '</span>';
    }
    $xml->writeElement('errorPhp', $errmsg);
}
$xml->endElement();
$xml->endElement();

if (! headers_sent()) {
    header('Content-Type: application/xml');
    header('Cache-Control: no-cache');
    header('Expires: 0');
    header('Cache-Control: no-cache, must-revalidate');
}

$xml->output();
