<?php
///////////////////////////////////////////////////////////////////////////////
//
// NagiosQL
//
///////////////////////////////////////////////////////////////////////////////
//
// (c) 2005-2018 by Martin Willisegger
//
// Project   : NagiosQL
// Component : Configuration Class
// Website   : https://sourceforge.net/projects/nagiosql/
// Version   : 3.4.0
// GIT Repo  : https://gitlab.com/wizonet/NagiosQL
//
///////////////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////////////
//
// Class: Configuration class
//
///////////////////////////////////////////////////////////////////////////////////////////////
//
// Includes all functions used for handling configuration files with NagiosQL
//
// Name: NagConfigClass
//
///////////////////////////////////////////////////////////////////////////////////////////////
namespace functions;

class NagConfigClass
{
    // Define class variables
    /** @var resource $resConnectId */
    public $resConnectId;                       // Connection id for FTP and SSH connections
    public $resSFTP;                            // SFTP ressource id

    public $arrSession           = array();     // Session content
    public $strRelTable          = '';          // Relation table name
    public $strErrorMessage      = '';          // String including error messages
    public $strInfoMessage       = '';          // String including information messages
    public $strPicPath           = 'none';      // Picture path string
    public $intNagVersion        = 0;           // Nagios version id
    public $intDomainId          = 0;           // Configuration domain ID
    // PRIVATE
    private $arrSettings         = array();     // Array includes all global settings
    private $resConnectServer    = '';          // Connection server name for FTP and SSH connections
    private $resConnectType      = 'none';      // Connection type for FTP and SSH connections
    private $arrRelData          = '';          // Relation data
    // Class includes
    /** @var MysqliDbClass */
    public $myDBClass;                          // Database class reference
    /** @var NagDataClass */
    public $myDataClass;                        // Data processing class reference

    /**
     * NagConfigClass constructor.
     * @param array $arrSession                 PHP Session array
     */
    public function __construct($arrSession)
    {
        if (isset($arrSession['SETS'])) {
            // Read global settings
            $this->arrSettings = $arrSession['SETS'];
        }
        if (isset($arrSession['domain'])) {
            $this->intDomainId = $arrSession['domain'];
        }
        $this->arrSession = $arrSession;
    }

    /**
     * Get domain configuration parameters.
     * @param string $strConfigItem             Configuration key
     * @param string $strValue                  Configuration value (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getDomainData($strConfigItem, &$strValue)
    {
        // Variable definition
        $intReturn = 0;
        // Request domain data from database
        $strSQL   = 'SELECT `' .$strConfigItem. '` FROM `tbl_datadomain` WHERE `id` = ' .$this->intDomainId;
        $strValue = $this->myDBClass->getFieldData($strSQL);
        if ($strValue == '') {
            $intReturn = 1;
        }
        return $intReturn;
    }

    /**
     * Get last modification date of a database table and any configuration files inside a directory.
     * @param string $strTableName              Name of the database table
     * @param string $strConfigName             Name of the configuration file
     * @param int $intDataId                    ID of the dataset for service table
     * @param array $arrTimeData                Array with the timestamps of the files and the DB table (by reference)
     * @param int $intTimeInfo                  Time status value (by reference)
     *                                          0 = all files are newer than the database item
     *                                          1 = some file are older than the database item
     *                                          2 = one file is missing
     *                                          3 = any files are missing
     *                                          4 = no configuration targets defined
     * @return int                              0 = successful / 1 = error
     *                                          Status messages are stored in class variables
     */
    public function lastModifiedDir($strTableName, $strConfigName, $intDataId, &$arrTimeData, &$intTimeInfo)
    {
        // Variable definitions
        $intReturn       = 0;
        // Create file name
        $strFileName  = $strConfigName. '.cfg';
        // Get table times
        $strActive            = 0;
        $arrTimeData          = array();
        $arrTimeData['table'] = 'unknown';
        // Clear status cache
        clearstatcache();
        // Get last change on dataset
        if ($strTableName == 'tbl_host') {
            $strSQL1 = "SELECT DATE_FORMAT(`last_modified`,'%Y-%m-%d %H:%i:%s') FROM `tbl_host` ".
                "WHERE `host_name`='$strConfigName' AND `config_id`=".$this->intDomainId;
            $strSQL2 = "SELECT `active` FROM `tbl_host`  WHERE `host_name`='$strConfigName' ".
                'AND `config_id`=' .$this->intDomainId;
            $arrTimeData['table'] = $this->myDBClass->getFieldData($strSQL1);
            $strActive            = $this->myDBClass->getFieldData($strSQL2);
        } elseif ($strTableName == 'tbl_service') {
            $strSQL1 = "SELECT DATE_FORMAT(`last_modified`,'%Y-%m-%d %H:%i:%s') FROM `tbl_service` ".
                "WHERE `id`='$intDataId' AND `config_id`=".$this->intDomainId;
            $strSQL2 = "SELECT * FROM `$strTableName` WHERE `config_name`='$strConfigName' ".
                'AND `config_id`=' .$this->intDomainId." AND `active`='1'";
            $arrTimeData['table'] = $this->myDBClass->getFieldData($strSQL1);
            $intServiceCount      = $this->myDBClass->countRows($strSQL2);
            if ($intServiceCount != 0) {
                $strActive = 1;
            }
        } else {
            $intReturn = 1;
        }
        // Get config sets
        $arrConfigId      = array();
        $strTarget        = '';
        $strBaseDir       = '';
        $intTimeInfo      = -1;
        $intRetVal2  = $this->getConfigTargets($arrConfigId);
        if ($intRetVal2 == 0) {
            foreach ($arrConfigId as $intConfigId) {
                // Get configuration file data
                $this->getConfigValues($intConfigId, 'target', $strTarget);
                // Get last change on dataset
                if ($strTableName == 'tbl_host') {
                    $this->getConfigValues($intConfigId, 'hostconfig', $strBaseDir);
                } elseif ($strTableName == 'tbl_service') {
                    $this->getConfigValues($intConfigId, 'serviceconfig', $strBaseDir);
                }
                $arrTimeData[$strTarget] = 'unknown';
                $intFileStampTemp        = -1;
                // Get time data
                $intReturn = $this->getFileDate(
                    $intConfigId,
                    $strFileName,
                    $strBaseDir,
                    $intFileStampTemp,
                    $arrTimeData[$strTarget]
                );
                if (($intFileStampTemp == 0) && ($strActive == '1')) {
                    $intTimeInfo = 2;
                }
                if (($strActive == '1') && (strtotime($arrTimeData['table']) > $intFileStampTemp)) {
                    $intTimeInfo = 1;
                }
            }
            $intItems    = \count($arrTimeData) - 1;
            $intUnknown  = 0;
            $intUpToDate = 0;
            foreach ($arrTimeData as $key) {
                if ($key == 'unknown') {
                    $intUnknown++;
                }
                if (strtotime($arrTimeData['table']) < strtotime($key)) {
                    $intUpToDate++;
                }
            }
            if ($intUnknown  == $intItems) {
                $intTimeInfo = 3;
            }
            if ($intUpToDate == $intItems) {
                $intTimeInfo = 0;
            }
        } else {
            $intTimeInfo = 4;
        }
        return $intReturn;
    }

    /**
     * Get configuration target IDs
     * @param array $arrConfigId                Configuration target IDs (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getConfigTargets(&$arrConfigId)
    {
        // Variable definition
        $arrData      = array();
        $arrConfigId  = array();
        $intDataCount = 0;
        $intReturn    = 1;
        // Request target ID
        $strSQL    = 'SELECT `targets` FROM `tbl_datadomain` WHERE `id`=' .$this->intDomainId;
        $booReturn = $this->myDBClass->hasDataArray($strSQL, $arrData, $intDataCount);
        if ($booReturn && ($intDataCount != 0)) {
            foreach ($arrData as $elem) {
                $arrConfigId[] = $elem['targets'];
            }
            $intReturn = 0;
        }
        return $intReturn;
    }

    /**
     * Get configuration domain values
     * @param int $intConfigId                  Configuration ID
     * @param string $strConfigKey              Configuration key
     * @param string $strValue                  Configuration value (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getConfigValues($intConfigId, $strConfigKey, &$strValue)
    {
        // Define variables
        $intReturn = 1;
        // Read database
        $strSQL    = 'SELECT `' .$strConfigKey. '` FROM `tbl_configtarget` WHERE `id`=' .$intConfigId;
        $strValue  = $this->myDBClass->getFieldData($strSQL);
        if ($strValue != '') {
            $intReturn = 0;
        }
        return $intReturn;
    }

    /**
     * Get last modification date of a configuration file.
     * @param int $intConfigId                  Configuration ID
     * @param string $strFile                   Configuration file name
     * @param string $strBaseDir                Base directory with configuration file
     * @param int|bool $intFileStamp            File timestamp (by reference)
     * @param string $strTimeData               Human readable string of file time stamp (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getFileDate($intConfigId, $strFile, $strBaseDir, &$intFileStamp, &$strTimeData)
    {
        $strMethod  = 1;
        $intReturn  = 0;
        // Get configuration file data
        $this->getConfigValues($intConfigId, 'method', $strMethod);
        $strTimeData  = 'unknown';
        $intFileStamp = -1;
        // Lokal file system
        if (($strMethod == 1) && file_exists($strBaseDir. '/' .$strFile)) {
            $intFileStamp = filemtime($strBaseDir. '/' .$strFile);
            $strTimeData = date('Y-m-d H:i:s', $intFileStamp);
        } elseif ($strMethod == 2) { // FTP file system
            // Check connection
            $intReturn = $this->getFTPConnection($intConfigId);
            if ($intReturn == 0) {
                $intFileStamp = ftp_mdtm($this->resConnectId, $strBaseDir . '/' . $strFile);
                if ($intFileStamp != -1) {
                    $strTimeData = date('Y-m-d H:i:s', $intFileStamp);
                }
            }
        } elseif ($strMethod == 3) { // SSH file system
            // Check connection
            $intReturn = $this->getSSHConnection($intConfigId);
            // Check file date
            $strFilePath = str_replace('//', '/', $strBaseDir.'/'.$strFile);
            $strCommand  = 'ls '.$strFilePath;
            $arrResult   =  array();
            if (($intReturn == 0) && ($this->sendSSHCommand($strCommand, $arrResult) == 0) &&
                isset($arrResult[0]) && ($arrResult[0] == $strFilePath)) {
                $arrInfo      = ssh2_sftp_stat($this->resSFTP, $strFilePath);
                $intFileStamp = $arrInfo['mtime'];
                if ($intFileStamp != -1) {
                    $strTimeData = date('Y-m-d H:i:s', $intFileStamp);
                }
            }
        }
        return $intReturn;
    }

    /**
     * Open an FTP connection
     * @param int $intConfigID                  Configuration ID
     * @return int                              0 = successful / 1 = error
     *                                          Status messages are stored in class variables
     */
    public function getFTPConnection($intConfigID)
    {
        // Define variables
        $intReturn = 0;
        $arrError  = array();
        // Already connected?
        if (empty($this->resConnectId) || !\is_resource($this->resConnectId) || ($this->resConnectType != 'FTP')) {
            // Define variables
            $booLogin = false;
            $this->getConfigValues($intConfigID, 'server', $strServer);
            $this->getConfigValues($intConfigID, 'ftp_secure', $intFtpSecure);
            // Set up basic connection
            $this->resConnectServer = $strServer;
            $this->resConnectType = 'FTP';
            // Secure FTP?
            if ($intFtpSecure == 1) {
                $this->resConnectId = ftp_ssl_connect($strServer);
            } else {
                $this->resConnectId = ftp_connect($strServer);
            }
            // Login with username and password
            if ($this->resConnectId) {
                $this->getConfigValues($intConfigID, 'user', $strUser);
                $this->getConfigValues($intConfigID, 'password', $strPasswd);
                $intErrorReporting = error_reporting();
                error_reporting('0');
                $booLogin = ftp_login($this->resConnectId, $strUser, $strPasswd);
                $arrError = error_get_last();
                error_reporting($intErrorReporting);
                if ($booLogin == false) {
                    ftp_close($this->resConnectId);
                    $this->resConnectServer = '';
                    $this->resConnectType   = 'none';
                    $this->resConnectId     = null;
                    $intReturn = 1;
                } else {
                    // Change to PASV mode
                    ftp_pasv($this->resConnectId, true);
                }
            }
            // Check connection
            if ((!$this->resConnectId) || (!$booLogin)) {
                $this->myDataClass->writeLog(translate('Connection to remote system failed (FTP connection):') .
                    ' ' . $strServer);
                $this->processClassMessage(translate('Connection to remote system failed (FTP connection):') .
                    ' <b>' . $strServer . '</b>::', $this->strErrorMessage);
                if ($arrError !== null && ($arrError['message'] != '')) {
                    $this->processClassMessage($arrError['message'] . '::', $this->strErrorMessage);
                }
            }
        }
        return $intReturn;
    }

    /**
     * Open an SSH connection
     * @param int $intConfigID                  Configuration ID
     * @return int                              0 = successful / 1 = error
     *                                          Status messages are stored in class variables
     */
    public function getSSHConnection($intConfigID)
    {
        // Define variables
        $intReturn       = 0;
        $strPasswordNote = '';
        // Already connected?
        if (empty($this->resConnectId) || !\is_resource($this->resConnectId) || ($this->resConnectType != 'SSH')) {
            // SSH Possible
            if (!\function_exists('ssh2_connect')) {
                $this->processClassMessage(translate('SSH module not loaded!'). '::', $this->strErrorMessage);
                return 1;
            }
            // Define variables
            $booLogin = false;
            $this->getConfigValues($intConfigID, 'server', $strServer);
            $this->resConnectServer = $strServer;
            $this->resConnectType   = 'SSH';
            $intErrorReporting  = error_reporting();
            error_reporting(0);
            $this->resConnectId = ssh2_connect($strServer);
            $arrError = error_get_last();
            error_reporting($intErrorReporting);
            // Check connection
            if ($this->resConnectId) {
                // Login with username and password
                $this->getConfigValues($intConfigID, 'user', $strUser);
                $this->getConfigValues($intConfigID, 'password', $strPasswd);
                $this->getConfigValues($intConfigID, 'ssh_key_path', $strSSHKeyPath);
                if ($strSSHKeyPath != '') {
                    $strPublicKey = str_replace('//', '/', $strSSHKeyPath.'/id_rsa.pub');
                    $strPrivatKey = str_replace('//', '/', $strSSHKeyPath.'/id_rsa');
                    // Check if ssh key file are readable
                    if (!file_exists($strPublicKey) || !is_readable($strPublicKey)) {
                        $this->myDataClass->writeLog(translate('SSH public key does not exist or is not readable')
                            . ' ' . $strSSHKeyPath.$strPublicKey);
                        $this->processClassMessage(translate('SSH public key does not exist or is not readable')
                            . ' <b>' . $strSSHKeyPath.$strPublicKey. '</b>::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                    if (!file_exists($strPrivatKey) || !is_readable($strPrivatKey)) {
                        $this->myDataClass->writeLog(translate('SSH private key does not exist or is not readable')
                            . ' ' . $strPrivatKey);
                        $this->processClassMessage(translate('SSH private key does not exist or is not readable'). ' ' .
                            $strPrivatKey. '::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                    $intErrorReporting  = error_reporting();
                    error_reporting(0);
                    if ($strPasswd == '') {
                        $booLogin = ssh2_auth_pubkey_file(
                            $this->resConnectId,
                            $strUser,
                            $strSSHKeyPath. '/id_rsa.pub',
                            $strSSHKeyPath. '/id_rsa'
                        );
                    } else {
                        $booLogin = ssh2_auth_pubkey_file(
                            $this->resConnectId,
                            $strUser,
                            $strSSHKeyPath. '/id_rsa.pub',
                            $strSSHKeyPath. '/id_rsa',
                            $strPasswd
                        );
                    }
                    $arrError = error_get_last();
                    error_reporting($intErrorReporting);
                } else {
                    $intErrorReporting  = error_reporting();
                    error_reporting(0);
                    $booLogin        = ssh2_auth_password($this->resConnectId, $strUser, $strPasswd);
                    $arrError        = error_get_last();
                    $strPasswordNote = 'If you are using ssh2 with user/password - you have to enable ' .
                        'PasswordAuthentication in your sshd_config';
                    error_reporting($intErrorReporting);
                }
            } else {
                $this->myDataClass->writeLog(translate('Connection to remote system failed (SSH2 connection):').
                    ' ' .$strServer);
                $this->processClassMessage(translate('Connection to remote system failed (SSH2 connection):').
                    ' <b>' .$strServer. '</b>::', $this->strErrorMessage);
                if ($arrError['message'] != '') {
                    $this->processClassMessage($arrError['message']. '::', $this->strErrorMessage);
                }
                $intReturn = 1;
            }
            // Check connection
            if ((!$this->resConnectId) || (!$booLogin)) {
                $this->myDataClass->writeLog(translate('Connection to remote system failed (SSH2 connection):').
                    ' ' .$strServer);
                $this->processClassMessage(translate('Connection to remote system failed (SSH2 connection):')
                    . ' ' .$strServer. '::', $this->strErrorMessage);
                if ($arrError['message'] != '') {
                    $this->processClassMessage($arrError['message']. '::', $this->strErrorMessage);
                }
                if ($strPasswordNote !== null) {
                    $this->processClassMessage($strPasswordNote. '::', $this->strErrorMessage);
                }
                $this->resConnectServer = '';
                $this->resConnectType   = 'none';
                $this->resConnectId     = null;
                $intReturn = 1;
            } else {
                // Etablish an SFTP connection ressource
                $this->resSFTP = ssh2_sftp($this->resConnectId);
            }
        }
        return $intReturn;
    }

    /**
     * Sends a command via SSH and stores the result in an array
     * @param string $strCommand                Command string
     * @param array $arrResult                  Output as array (by reference)
     * @param int $intLines                     Maximal length of output to read
     * @return int                              0 = successful / 1 = error
     */
    public function sendSSHCommand($strCommand, &$arrResult, $intLines = 100)
    {
        // Define variables
        $intCount1 = 0; // empty lines
        $intCount2 = 0; // data lines
        $booBreak = false;
        $this->getConfigTargets($arrConfigSet);
        // Check connection
        $intReturn = $this->getSSHConnection($arrConfigSet[0]);
        if (\is_resource($this->resConnectId)) {
            // Send command
            $resStream = ssh2_exec($this->resConnectId, $strCommand.'; echo __END__');
            if ($resStream) {
                // read result
                stream_set_blocking($resStream, true);
                stream_set_timeout($resStream, 2);
                do {
                    $strLine = stream_get_line($resStream, 1024, "\n");
                    if ($strLine == '') {
                        $intCount1++;
                    } elseif (substr_count($strLine, '__END__') != 1) {
                        $arrResult[] = $strLine;
                        $intReturn   = 0;
                    } elseif (substr_count($strLine, '__END__') == 1) {
                        $booBreak = true;
                    }
                    $intCount2++;
                    $arrStatus = stream_get_meta_data($resStream);
                } while ($resStream && !feof($resStream) && ($intCount1 <= 10) && ($intCount2 <= $intLines) &&
                ($arrStatus['timed_out'] != true) && $booBreak == false);
                fclose($resStream);
                // Close SSH connection because of timing problems
                unset($this->resConnectId);
                //sleep(1);
            }
        }
        return $intReturn;
    }

    /**
     * Merge message strings and check for duplicate messages
     * @param string $strNewMessage             New message to add
     * @param string $strOldMessage             Modified message string (by reference)
     */
    public function processClassMessage($strNewMessage, &$strOldMessage)
    {
        $strNewMessage = str_replace('::::', '::', $strNewMessage);
        if (($strOldMessage != '') && ($strNewMessage != '') && (substr_count($strOldMessage, $strNewMessage) == 0)) {
            $strOldMessage .= $strNewMessage;
        } elseif ($strOldMessage == '') {
            $strOldMessage .= $strNewMessage;
        }
    }

    /**
     * Get configuration target IDs
     * @param array $arrConfigId                Configuration target IDs (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getConfigSets(&$arrConfigId)
    {
        // Variable definition
        $arrData      = array();
        $arrConfigId  = array();
        $intDataCount = 0;
        $intReturn    = 1;
        // Request target ID
        $strSQL    = 'SELECT `targets` FROM `tbl_datadomain` WHERE `id`=' .$this->intDomainId;
        $booReturn = $this->myDBClass->hasDataArray($strSQL, $arrData, $intDataCount);
        if ($booReturn && ($intDataCount != 0)) {
            foreach ($arrData as $elem) {
                $arrConfigId[] = $elem['targets'];
            }
            $intReturn = 0;
        }
        return $intReturn;
    }

    /**
     * Moves an existing configuration file to the backup directory and removes then the original file
     * @param string $strType                   Type of the configuration file
     * @param string $strName                   Name of the configuration file
     * @param int $intConfigID                  Configuration target ID
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function moveFile($strType, $strName, $intConfigID)
    {
        // Variable definitions
        $strConfigDir = '';
        $strBackupDir = '';
        $intReturn    = 0;
        // Get directories
        switch ($strType) {
            case 'host':
                $this->getConfigData($intConfigID, 'hostconfig', $strConfigDir);
                $this->getConfigData($intConfigID, 'hostbackup', $strBackupDir);
                break;
            case 'service':
                $this->getConfigData($intConfigID, 'serviceconfig', $strConfigDir);
                $this->getConfigData($intConfigID, 'servicebackup', $strBackupDir);
                break;
            case 'basic':
                $this->getConfigData($intConfigID, 'basedir', $strConfigDir);
                $this->getConfigData($intConfigID, 'backupdir', $strBackupDir);
                break;
            case 'nagiosbasic':
                $this->getConfigData($intConfigID, 'nagiosbasedir', $strConfigDir);
                $this->getConfigData($intConfigID, 'backupdir', $strBackupDir);
                break;
            default:
                $intReturn = 1;
        }
        if ($intReturn == 0) {
            // Variable definition
            $intMethod          = 1;
            $strDate            = date('YmdHis');
            $strSourceFile      = $strConfigDir. '/' .$strName;
            $strDestinationFile = $strBackupDir. '/' .$strName. '_old_' .$strDate;
            $booRetVal          = false;
            // Get connection method
            $this->getConfigData($intConfigID, 'method', $intMethod);
            // Local file system
            if ($intMethod == 1) {
                // Save configuration file
                if (file_exists($strSourceFile)) {
                    if (is_writable($strBackupDir) && is_writable($strConfigDir)) {
                        copy($strSourceFile, $strDestinationFile);
                        unlink($strSourceFile);
                    } else {
                        $this->processClassMessage(translate('Cannot backup the old file because the permissions are '
                                .'wrong - destination file: ').$strDestinationFile. '::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                } else {
                    $this->processClassMessage(translate('Cannot backup the old file because the source file is '
                            . 'missing - source file: ') . $strSourceFile . '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            } elseif ($intMethod == 2) { // Remote file (FTP)
                // Check connection
                $intReturn = $this->getFTPConnection($intConfigID);
                if ($intReturn == 0) {
                    $strSourceFile      = str_replace('//', '/', $strSourceFile);
                    $strDestinationFile = str_replace('//', '/', $strDestinationFile);
                    // Save configuration file
                    $intFileStamp = ftp_mdtm($this->resConnectId, $strSourceFile);
                    if ($intFileStamp > -1) {
                        $intErrorReporting = error_reporting();
                        error_reporting(0);
                        $booRetVal = ftp_rename($this->resConnectId, $strSourceFile, $strDestinationFile);
                        error_reporting($intErrorReporting);
                    } else {
                        $this->processClassMessage(translate('Cannot backup the old file because the source file is '
                                .'missing (remote FTP) - source file: '). $strSourceFile. '::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                }
                if (($booRetVal == false) && ($intReturn == 0)) {
                    $this->processClassMessage(translate('Cannot backup the old file because the permissions are '
                            .'wrong (remote FTP) - destination file: ').$strDestinationFile. '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            } elseif ($intMethod == 3) { // Remote file (SFTP)
                // Check connection
                $intReturn = $this->getSSHConnection($intConfigID);
                // Save configuration file
                $arrResult          = array();
                $strSourceFile      = str_replace('//', '/', $strSourceFile);
                $strDestinationFile = str_replace('//', '/', $strDestinationFile);
                $strCommand         = 'ls '.$strSourceFile;
                if (($intReturn == 0) && ($this->sendSSHCommand($strCommand, $arrResult) == 0)) {
                    if (isset($arrResult[0]) && $arrResult[0] == $strSourceFile) {
                        $arrInfo      = ssh2_sftp_stat($this->resSFTP, $strSourceFile);
                        if ($arrInfo['mtime'] > -1) {
                            $booRetVal = ssh2_sftp_rename($this->resSFTP, $strSourceFile, $strDestinationFile);
                        }
                    } else {
                        $this->processClassMessage(translate('Cannot backup the old file because the source file is '
                                .'missing (remote SFTP) - source file: '). $strSourceFile. '::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                }
                if (($booRetVal == false) && ($intReturn == 0)) {
                    $this->processClassMessage(translate('Cannot backup the old file because the permissions are '
                            .'wrong (remote SFTP) - destination file: ').$strDestinationFile. '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            }
        }
        return $intReturn;
    }

    /**
     * Remove a file
     * @param string $strFileName               Filename including path to remove
     * @param int $intConfigID                  Configuration target ID
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function removeFile($strFileName, $intConfigID)
    {
        // Variable definitions
        $intMethod = 1;
        $intReturn = 0;
        $booRetVal = false;
        // Get connection method
        $this->getConfigData($intConfigID, 'method', $intMethod);
        // Local file system
        if ($intMethod == 1) {
            // Save configuration file
            if (file_exists($strFileName)) {
                if (is_writable($strFileName)) {
                    unlink($strFileName);
                } else {
                    $this->processClassMessage(translate('Cannot delete the file (wrong permissions)!').'::'.
                        $strFileName. '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            } else {
                $this->processClassMessage(translate('Cannot delete the file (file does not exist)!').'::'.
                    $strFileName. '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        } elseif ($intMethod == 2) { // Remote file (FTP)
            // Check connection
            $intReturn = $this->getFTPConnection($intConfigID);
            if ($intReturn == 0) {
                // Save configuration file
                $intFileStamp = ftp_mdtm($this->resConnectId, $strFileName);
                if ($intFileStamp > -1) {
                    $intErrorReporting = error_reporting();
                    error_reporting(0);
                    $booRetVal = ftp_delete($this->resConnectId, $strFileName);
                    error_reporting($intErrorReporting);
                } else {
                    $this->processClassMessage(translate('Cannot delete file because it does not exists (remote '
                            . 'FTP)!'). '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            }
            if ($booRetVal == false) {
                $this->processClassMessage(translate('Cannot delete file because the permissions are incorrect '
                        . '(remote FTP)!'). '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        } elseif ($intMethod == 3) { // Remote file (SFTP)
            // Check connection
            $intReturn = $this->getSSHConnection($intConfigID);
            // Save configuration file
            if (($intReturn == 0) && ($this->sendSSHCommand('ls '.$strFileName, $arrResult) == 0)) {
                if (isset($arrResult[0])) {
                    $booRetVal = ssh2_sftp_unlink($this->resSFTP, $strFileName);
                } else {
                    $this->processClassMessage(translate('Cannot delete file because it does not exists (remote '
                            . 'SSH/SFTP)!'). '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            }
            if (($intReturn == 0) && ($booRetVal == false)) {
                $this->processClassMessage(translate('Cannot delete file because the permissions are incorrect '
                        . '(remote SSH/SFTP)!'). '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        }
        return $intReturn;
    }

    /**
     * Get configuration domain parameters
     * @param int $intConfigId                  Configuration ID
     * @param string $strConfigItem             Configuration key
     * @param string $strValue                  Configuration value (by reference)
     * @return int                              0 = successful / 1 = error
     */
    public function getConfigData($intConfigId, $strConfigItem, &$strValue)
    {
        $intReturn = 1;
        $strSQL   = 'SELECT `' .$strConfigItem. '` FROM `tbl_configtarget` WHERE `id` = ' .$intConfigId;
        $strValue = $this->myDBClass->getFieldData($strSQL);
        if ($strValue != '') {
            $intReturn = 0;
        }
        return $intReturn;
    }

    /**
     * Check a directory for write access
     * @param string $strPath                   Physical path
     * @return int                              0 = successful / 1 = error
     */
    public function isDirWriteable($strPath)
    {
        // Define variables
        $intReturnFile = 1;
        $intReturnDir  = 1;
        $intReturn     = 1;
        // Is input path a file?
        if (file_exists($strPath) && is_file($strPath)) {
            $resFile = fopen($strPath, 'ab');
            if ($resFile) {
                $intReturnFile = 0;
            }
        } else {
            $intReturnFile = 0;
        }
        if (is_file($strPath)) {
            $strDirectory = \dirname($strPath);
        } else {
            $strDirectory = $strPath;
        }
        $strFile = $strDirectory.'/'.uniqid(mt_rand(), true).'.tmp';
        // Check writing in directory directly
        if (is_dir($strDirectory) && is_writable($strDirectory)) {
            $resFile = fopen($strFile, 'wb');
            if ($resFile) {
                $intReturnDir = 0;
                unlink($strFile);
            }
        } else {
            $intReturnDir = 0;
        }
        if (($intReturnDir == 0) && ($intReturnFile == 0)) {
            $intReturn = 0;
        }
        return $intReturn;
    }

    /**
     * Copy a remote file
     * @param string $strFileRemote             Remote file name
     * @param int $intConfigID                  Configuration target id
     * @param string $strFileLocal              Local file name
     * @param int $intDirection                 0 = from remote to local / 1 = from local to remote
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function remoteFileCopy($strFileRemote, $intConfigID, $strFileLocal, $intDirection = 0)
    {
        // Variable definitions
        $intMethod = 3;
        $intReturn = 0;
        $arrTemp   = array();
        // Get method
        $this->getConfigData($intConfigID, 'method', $intMethod);
        if ($intMethod == 2) {
            // Check connection
            $intReturn = $this->getFTPConnection($intConfigID);
            if (($intReturn == 0) && ($intDirection == 0)) {
                $intErrorReporting = error_reporting();
                error_reporting(0);
                if (!ftp_get($this->resConnectId, $strFileLocal, $strFileRemote, FTP_ASCII)) {
                    $this->processClassMessage(translate('Cannot get the remote file (it does not exist or is not '
                            . 'readable) - remote file: '). $strFileRemote. '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
                error_reporting($intErrorReporting);
            } elseif (($intReturn == 0) && ($intDirection == 1)) {
                $intErrorReporting = error_reporting();
                error_reporting(0);
                if (!ftp_put($this->resConnectId, $strFileRemote, $strFileLocal, FTP_ASCII)) {
                    $this->processClassMessage(translate('Cannot write the remote file (remote file is not writeable)'
                            . '- remote file: ').$strFileRemote. '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
                error_reporting($intErrorReporting);
            }
            ftp_close($this->resConnectId);
        } elseif ($intMethod == 3) { // Remote file (SFTP)
            $intReturn = $this->getSSHConnection($intConfigID);
            if (($intReturn == 0) && ($intDirection == 0)) {
                // Copy file
                $intErrorReporting = error_reporting();
                error_reporting(0);
                if (!ssh2_scp_recv($this->resConnectId, $strFileRemote, $strFileLocal)) {
                    if ($this->sendSSHCommand('ls ' . $strFileRemote, $arrTemp) != 0) {
                        $this->processClassMessage(translate('Cannot get the remote file (it does not exist or is not '
                                . 'readable) - remote file: ') .$strFileRemote. '::', $this->strErrorMessage);
                    } else {
                        $this->processClassMessage(translate('Remote file is not readable - remote file: ')
                            . $strFileRemote. '::', $this->strErrorMessage);
                    }
                    $intReturn = 1;
                }
                error_reporting($intErrorReporting);
            } elseif (($intReturn == 0) && ($intDirection == 1)) {
                if (file_exists($strFileLocal) && is_readable($strFileLocal)) {
                    $intErrorReporting = error_reporting();
                    error_reporting(0);
                    if (!ssh2_scp_send($this->resConnectId, $strFileLocal, $strFileRemote, 0644)) {
                        $this->processClassMessage(translate('Cannot write a remote file (remote file is not writeable)'
                                .' - remote file: '). $strFileRemote . '::', $this->strErrorMessage);
                        $intReturn = 1;
                    }
                    error_reporting($intErrorReporting);
                } else {
                    $this->processClassMessage(translate('Cannot copy a local file to remote because the local file '.
                            'does not exist or is not readable - local file: ').
                        $strFileLocal . '::', $this->strErrorMessage);
                    $intReturn = 1;
                }
            }
        }
        return $intReturn;
    }

    /**
     * Add files of a given directory to an array
     * @param string $strSourceDir              Source directory
     * @param string $strIncPattern             Include file pattern
     * @param string $strExcPattern             Exclude file pattern
     * @param array $arrOutput                  Output array (by reference)
     * @param string $strErrorMessage           Error messages (by reference)
     */
    public function storeDirToArray($strSourceDir, $strIncPattern, $strExcPattern, &$arrOutput, &$strErrorMessage)
    {
        // Define variables
        $arrDir = array();
        while (substr($strSourceDir, -1) == '/' or substr($strSourceDir, -1) == "\\") {
            $strSourceDir = substr($strSourceDir, 0, -1);
        }
        $resHandle = opendir($strSourceDir);
        if ($resHandle === false) {
            if ($this->intDomainId != 0) {
                $strErrorMessage .= translate('Could not open directory'). ': ' .$strSourceDir;
            }
        } else {
            $booBreak = true;
            while ($booBreak) {
                if (!$arrDir[] = readdir($resHandle)) {
                    $booBreak = false;
                }
            }
            closedir($resHandle);
            sort($arrDir);
            /** @var string $file */
            foreach ($arrDir as $file) {
                /** @noinspection StrlenInEmptyStringCheckContextInspection */
                if (!preg_match("/^\.{1,2}/", $file) && \strlen($file)) {
                    if (is_dir($strSourceDir. '/' .$file)) {
                        $this->storeDirToArray(
                            $strSourceDir. '/' .$file,
                            $strIncPattern,
                            $strExcPattern,
                            $arrOutput,
                            $strErrorMessage
                        );
                    } else {
                        if (preg_match('/' .$strIncPattern. '/', $file) && (($strExcPattern == '') ||
                                !preg_match('/' .$strExcPattern. '/', $file))) {
                            if (0 === stripos(PHP_OS, 'WIN')) {
                                $strSourceDir=str_replace('/', "\\", $strSourceDir);
                                $arrOutput [] = $strSourceDir."\\".$file;
                            } else {
                                $arrOutput [] = $strSourceDir. '/' .$file;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Determines the dates of the last data table change and the last modification to the configuration files
     * @param string $strTableName              Name of the data table
     * @param array $arrTimeData                Array with time data of table and all config files
     * @param string $strCheckConfig            Information string (text message)
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function lastModifiedFile($strTableName, &$arrTimeData, &$strCheckConfig)
    {
        // Variable definitions
        $intEnableCommon = 0;
        $arrDataset      = array();
        $strFileName     = '';
        $strCheckConfig  = '';
        $intReturn       = 0;
        // Get configuration filename based on table name
        $arrConfigData = $this->getConfData();
        if (isset($arrConfigData[$strTableName])) {
            $strFileName   = $arrConfigData[$strTableName]['filename'];
        } else {
            $intReturn = 1;
        }
        // Get table times
        $arrTimeData          = array();
        $arrTimeData['table'] = 'unknown';
        // Clear status cache
        clearstatcache();
        $intRetVal1 = $this->getDomainData('enable_common', $intEnableCommon);
        // Get last change of date table
        if ($intRetVal1 == 0) {
            $strSQLAdd = '';
            if ($intEnableCommon == 1) {
                $strSQLAdd = 'OR `domainId`=0';
            }
            $strSQL = 'SELECT `updateTime` FROM `tbl_tablestatus` '
                . 'WHERE (`domainId`=' .$this->intDomainId." $strSQLAdd) AND `tableName`='".$strTableName."' "
                . 'ORDER BY `updateTime` DESC LIMIT 1';
            $booReturn = $this->myDBClass->hasSingleDataset($strSQL, $arrDataset);
            if ($booReturn && isset($arrDataset['updateTime'])) {
                $arrTimeData['table'] = $arrDataset['updateTime'];
            } else {
                $strSQL = 'SELECT `last_modified` FROM `' .$strTableName. '` '
                    . 'WHERE `config_id`=' .$this->intDomainId. ' ORDER BY `last_modified` DESC LIMIT 1';
                $booReturn = $this->myDBClass->hasSingleDataset($strSQL, $arrDataset);
                if (($booReturn == true) && isset($arrDataset['last_modified'])) {
                    $arrTimeData['table'] = $arrDataset['last_modified'];
                }
            }
        }
        // Get config sets
        $arrConfigId      = array();
        $strTarget        = '';
        $strBaseDir       = '';
        $intFileStampTemp = 0;
        $intRetVal2  = $this->getConfigSets($arrConfigId);
        if ($intRetVal2 == 0) {
            foreach ($arrConfigId as $intConfigId) {
                // Get configuration file data
                $this->getConfigData($intConfigId, 'target', $strTarget);
                $this->getConfigData($intConfigId, 'basedir', $strBaseDir);
                // Get time data
                $intReturn = $this->getFileDate(
                    $intConfigId,
                    $strFileName,
                    $strBaseDir,
                    $intFileStampTemp,
                    $arrTimeData[$strTarget]
                );
                if ($intFileStampTemp != 0 && strtotime($arrTimeData['table']) > $intFileStampTemp) {
                    $strCheckConfig = translate('Warning: configuration file is out of date!');
                }
                if ($arrTimeData[$strTarget] == 'unknown') {
                    $strCheckConfig = translate('Warning: configuration file is out of date!');
                }
            }
        } else {
            $strCheckConfig = translate('Warning: no configuration target defined!');
        }
        return $intReturn;
    }

    /**
     * Writes a configuration file including all datasets of a configuration table or returns the output as a text
     * file for download. (Public master function)
     * @param string $strTableName              Table name
     * @param int $intMode                      0 = Write file to filesystem
     *                                          1 = Return Textfile for download test
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function createConfig($strTableName, $intMode = 0)
    {
        // Define Variables
        $intReturn     = 0;
        // Do not create configs in common domain
        if ($this->intDomainId == 0) {
            $this->processClassMessage(translate('It is not possible to write config files directly from the common '
                    . 'domain!'). '::', $this->strErrorMessage);
            $intReturn = 1;
        }
        if ($intReturn == 0) {
            // Get configuration targets
            $this->getConfigSets($arrConfigID);
            if (($arrConfigID != 1) && \is_array($arrConfigID)) {
                foreach ($arrConfigID as $intConfigID) {
                    $intReturn = $this->writeConfTemplate($intConfigID, $strTableName, $intMode);
                }
            } else {
                $this->processClassMessage(translate('Warning: no configuration target defined!').
                    '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        }
        return $intReturn;
    }

    /**
     * Writes a configuration file including one single datasets of a configuration table or returns the output as
     * a text file for download.
     * @param string $strTableName              Table name
     * @param int $intDbId                      Data ID
     * @param int $intMode                      0 = Write file to filesystem
     *                                          1 = Return Textfile for download test
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    public function createConfigSingle($strTableName, $intDbId = 0, $intMode = 0)
    {
        // Define Variables
        $arrData            = array();
        $intDataCount       = 0;
        $setEnableCommon    = 0;
        $intReturn          = 0;
        $strDomainWhere     = ' (`config_id`=' .$this->intDomainId. ') ';
        // Read some settings and informations
        $this->getDomainData('enable_common', $setEnableCommon);
        // Variable rewritting
        if ($setEnableCommon != 0) {
            $strDomainWhere = str_replace(')', ' OR `config_id`=0)', $strDomainWhere);
        }
        // Do not create configs in common domain
        if ($this->intDomainId == 0) {
            $this->processClassMessage(translate('It is not possible to write config files directly from the common '
                    . 'domain!'). '::', $this->strErrorMessage);
            $intReturn = 1;
        }
        if ($intReturn == 0) {
            if ($intDbId == 0) {
                $strSQL = 'SELECT * FROM `' .$strTableName."` WHERE $strDomainWhere AND `active`='1' ORDER BY `id`";
            } else {
                $strSQL = 'SELECT * FROM `' .$strTableName."` WHERE $strDomainWhere AND `active`='1' AND `id`=$intDbId";
            }
            $booReturn = $this->myDBClass->hasDataArray($strSQL, $arrData, $intDataCount);
            if (($booReturn != false) && ($intDataCount != 0)) {
                /** @noinspection ForeachInvariantsInspection */
                for ($i = 0; $i < $intDataCount; $i++) {
                    // Process form POST variable
                    $strChbName = 'chbId_' .$arrData[$i]['id'];
                    // Check if this POST variable exists or the data ID parameter matches
                    if ((($intDbId != 0) && ($intDbId == $arrData[$i]['id'])) ||
                        (filter_input(INPUT_POST, $strChbName) !== null)) {
                        // Get configuration targets
                        $this->getConfigSets($arrConfigID);
                        if (($arrConfigID != 1) && \is_array($arrConfigID)) {
                            foreach ($arrConfigID as $intConfigID) {
                                $intReturn = $this->writeConfTemplate(
                                    $intConfigID,
                                    $strTableName,
                                    $intMode,
                                    $arrData,
                                    $i
                                );
                            }
                        } else {
                            $this->processClassMessage(translate('Warning: no configuration target defined!').
                                '::', $this->strErrorMessage);
                            $intReturn = 1;
                        }
                    }
                }
            } else {
                $this->myDataClass->writeLog(translate('Writing of the configuration failed - no dataset or not '
                    . 'activated dataset found'));
                $this->processClassMessage(translate('Writing of the configuration failed - no dataset or not '
                        . 'activated dataset found'). '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        }
        return $intReturn;
    }


    // PRIVATE functions

    /**
     * Determines the configuration data for each database table
     * @return array                            filename (configuration file name)
     *                                          order_field (database order field)
     */
    public function getConfData()
    {
        $arrConfData['tbl_timeperiod']        = array('filename' => 'timeperiods.cfg',
            'order_field' => 'timeperiod_name');
        $arrConfData['tbl_command']           = array('filename' => 'commands.cfg',
            'order_field' => 'command_name');
        $arrConfData['tbl_contact']           = array('filename' => 'contacts.cfg',
            'order_field' => 'contact_name');
        $arrConfData['tbl_contacttemplate']   = array('filename' => 'contacttemplates.cfg',
            'order_field' => 'template_name');
        $arrConfData['tbl_contactgroup']      = array('filename' => 'contactgroups.cfg',
            'order_field' => 'contactgroup_name');
        $arrConfData['tbl_hosttemplate']      = array('filename' => 'hosttemplates.cfg',
            'order_field' => 'template_name');
        $arrConfData['tbl_servicetemplate']   = array('filename' => 'servicetemplates.cfg',
            'order_field' => 'template_name');
        $arrConfData['tbl_hostgroup']         = array('filename' => 'hostgroups.cfg',
            'order_field' => 'hostgroup_name');
        $arrConfData['tbl_servicegroup']      = array('filename' => 'servicegroups.cfg',
            'order_field' => 'servicegroup_name');
        $arrConfData['tbl_hostdependency']    = array('filename' => 'hostdependencies.cfg',
            'order_field' => 'dependent_host_name');
        $arrConfData['tbl_servicedependency'] = array('filename' => 'servicedependencies.cfg',
            'order_field' => 'config_name');
        $arrConfData['tbl_hostescalation']    = array('filename' => 'hostescalations.cfg',
            'order_field' => 'host_name`,`hostgroup_name');
        $arrConfData['tbl_serviceescalation'] = array('filename' => 'serviceescalations.cfg',
            'order_field' => 'config_name');
        $arrConfData['tbl_hostextinfo']       = array('filename' => 'hostextinfo.cfg',
            'order_field' => 'host_name');
        $arrConfData['tbl_serviceextinfo']    = array('filename' => 'serviceextinfo.cfg',
            'order_field' => 'host_name');
        return $arrConfData;
    }

    /**
     * Writes a configuration file including all datasets of a configuration table or returns the output as a text
     * file for download. (Private worker function)
     * @param int $intConfigID                  Configuration target ID
     * @param string $strTableName              Table name
     * @param int $intMode                      0 = Write file to filesystem
     *                                          1 = Return Textfile for download test
     * @param array $arrTableData               Dataset array for host and services only
     * @param int $intID                        Key for dataset array
     * @return int                              0 = successful / 1 = error
     *                                          Status message is stored in message class variables
     */
    /** @noinspection ArrayTypeOfParameterByDefaultValueInspection */
    private function writeConfTemplate($intConfigID, $strTableName, $intMode, $arrTableData = array(), $intID = 0)
    {
        // Variable definitions
        $strSQL         = '';
        $strOrderField  = '';
        $strFileString  = '';
        $arrTplOptions  = array('use_preg' => false);
        $strDomainWhere = ' (`config_id`=' . $this->intDomainId . ') ';
        $intType        = 0;
        $intReturn      = 0;
        // Read some settings and informations
        $this->getConfigData($intConfigID, 'utf8_decode', $setUTF8Decode);
        $this->getDomainData('enable_common', $setEnableCommon);
        $this->getConfigData($intConfigID, 'version', $intNagiosVersion);
        $arrConfigData = $this->getConfData();
        if (isset($arrConfigData[$strTableName])) {
            $strFileString = str_replace('.cfg', '', $arrConfigData[$strTableName]['filename']);
            $strOrderField = $arrConfigData[$strTableName]['order_field'];
        }
        // Variable rewritting
        if ($setEnableCommon != 0) {
            $strDomainWhere = str_replace(')', ' OR `config_id`=0)', $strDomainWhere);
        }
        // Special processing for table host and service
        $setTemplate = $strFileString. '.tpl.dat';
        if (($strTableName == 'tbl_host') || ($strTableName == 'tbl_service')) {
            // Define variable names based on table name
            switch ($strTableName) {
                case 'tbl_host':
                    $strFileString = $arrTableData[$intID]['host_name'];
                    $intDomainId   = $arrTableData[$intID]['config_id'];
                    $setTemplate   = 'hosts.tpl.dat';
                    $intType       = 1;
                    $strSQL        = 'SELECT * FROM `' . $strTableName . "` WHERE `host_name`='$strFileString' "
                        . "AND `active`='1' AND `config_id`=$intDomainId";
                    break;
                case 'tbl_service':
                    $strFileString = $arrTableData[$intID]['config_name'];
                    $intDomainId   = $arrTableData[$intID]['config_id'];
                    $setTemplate   = 'services.tpl.dat';
                    $intType       = 2;
                    $strSQL        = 'SELECT * FROM `' . $strTableName . "` WHERE `config_name`='$strFileString' "
                        . "AND `active`='1' AND `config_id`=$intDomainId ORDER BY `service_description`";
                    break;
            }
        } else {
            $strSQL  = 'SELECT * FROM `' .$strTableName."` WHERE $strDomainWhere AND `active`='1' ".
                'ORDER BY `' .$strOrderField. '`';
        }
        $strFile     = $strFileString. '.cfg';
        // Load configuration template file
        $tplConf = new \HTML_Template_IT($this->arrSettings['path']['base_path']. '/templates/files/');
        $tplConf->loadTemplatefile($setTemplate, true, true);
        $tplConf->setOptions($arrTplOptions);
        $tplConf->setVariable('CREATE_DATE', date('Y-m-d H:i:s'));
        $tplConf->setVariable('NAGIOS_QL_VERSION', $this->arrSettings['db']['version']);
        $tplConf->setVariable('VERSION', $this->getVersionString($intConfigID));
        // Write data from configuration table
        $booReturn = $this->myDBClass->hasDataArray($strSQL, $arrData, $intDataCount);
        if ($booReturn && ($intDataCount != 0) && ($strFileString != '')) {
            // Process every data set
            /** @noinspection ForeachInvariantsInspection */
            for ($i = 0; $i < $intDataCount; $i++) {
                $intDataId = 0;
                /** @noinspection ForeachSourceInspection */
                foreach ($arrData[$i] as $key => $value) {
                    if ($key == 'id') {
                        $intDataId = $value;
                    }
                    if ($key == 'config_name') {
                        $key = '#NAGIOSQL_CONFIG_NAME';
                    }
                    // UTF8 decoded vaules
                    if ($setUTF8Decode == 1) {
                        $value = utf8_decode($value);
                    }
                    // Pass special fields (NagiosQL data fields not used by Nagios itselves)
                    if ($this->skipEntries($strTableName, $intNagiosVersion, $key, $value) == 1) {
                        continue;
                    }
                    // Get relation data
                    $intSkip = $this->getRelationData($strTableName, $tplConf, $arrData[$i], $key, $value);
                    // Rename field names
                    $this->renameFields($strTableName, $intConfigID, $intDataId, $key, $value, $intSkip);
                    // Inset data field
                    if ($intSkip != 1) {
                        // Insert fill spaces
                        $strFillLen = (30- \strlen($key));
                        $strSpace = ' ';
                        for ($f = 0; $f < $strFillLen; $f++) {
                            $strSpace .= ' ';
                        }
                        // Write key and value to template
                        $tplConf->setVariable('ITEM_TITLE', $key.$strSpace);
                        // Short values
                        if (($intNagiosVersion != 3) || (\strlen($value) < 800)) {
                            $tplConf->setVariable('ITEM_VALUE', $value);
                            $tplConf->parse('configline');
                        } else { // Long values
                            $arrValueTemp = explode(',', $value);
                            $strValueNew  = '';
                            $intArrCount  = \count($arrValueTemp);
                            $intCounter   = 0;
                            $strSpace     = ' ';
                            for ($f = 0; $f < 30; $f++) {
                                $strSpace .= ' ';
                            }
                            foreach ($arrValueTemp as $elem) {
                                if (\strlen($strValueNew) < 800) {
                                    $strValueNew .= $elem. ',';
                                } else {
                                    if (substr($strValueNew, -1) == ',') {
                                        $strValueNew = substr($strValueNew, 0, -1);
                                    }
                                    if ($intCounter < $intArrCount) {
                                        $strValueNew .= ",\\";
                                        $tplConf->setVariable('ITEM_VALUE', $strValueNew);
                                        $tplConf->parse('configline');
                                        $tplConf->setVariable('ITEM_TITLE', $strSpace);
                                    } else {
                                        $tplConf->setVariable('ITEM_VALUE', $strValueNew);
                                        $tplConf->parse('configline');
                                        $tplConf->setVariable('ITEM_TITLE', $strSpace);
                                    }
                                    $strValueNew = $elem. ',';
                                }
                                $intCounter++;
                            }
                            if ($strValueNew != '') {
                                if (substr($strValueNew, -1) == ',') {
                                    $strValueNew = substr($strValueNew, 0, -1);
                                }
                                $tplConf->setVariable('ITEM_VALUE', $strValueNew);
                                $tplConf->parse('configline');
                            }
                        }
                    }
                }
                // Special processing for time periods
                if ($strTableName == 'tbl_timeperiod') {
                    $arrDataTime = array();
                    $strSQLTime = 'SELECT `definition`, `range` '
                        . 'FROM `tbl_timedefinition` WHERE `tipId` = ' .$arrData[$i]['id'];
                    $booReturn  = $this->myDBClass->hasDataArray($strSQLTime, $arrDataTime, $intDataCountTime);
                    if ($booReturn && $intDataCountTime != 0) {
                        foreach ($arrDataTime as $data) {
                            // Skip other values than weekdays in nagios version below 3
                            if ($intNagiosVersion < 3) {
                                $arrWeekdays = array('monday','tuesday','wednesday','thursday','friday','saturday',
                                    'sunday');
                                if (!\in_array($data['definition'], $arrWeekdays, true)) {
                                    continue;
                                }
                            }
                            // Insert fill spaces
                            $strFillLen = (30- \strlen($data['definition']));
                            $strSpace = ' ';
                            for ($f = 0; $f < $strFillLen; $f++) {
                                $strSpace .= ' ';
                            }
                            // Write key and value
                            $tplConf->setVariable('ITEM_TITLE', $data['definition'].$strSpace);
                            $tplConf->setVariable('ITEM_VALUE', $data['range']);
                            $tplConf->parse('configline');
                        }
                    }
                }
                // Write configuration set
                $tplConf->parse('configset');
            }
        } elseif ($booReturn && ($intDataCount == 0) && ($strFileString != '')) {
            $this->processClassMessage(translate('Error while selecting data from database:')
                . '::', $this->strErrorMessage);
            $this->processClassMessage($this->myDBClass->strErrorMessage, $this->strErrorMessage);
            $intReturn = 1;
        } else {
            $this->myDataClass->writeLog(translate('Writing of the configuration failed - no dataset '
                . 'or not activated dataset found'));
            $this->processClassMessage(translate('Writing of the configuration failed - no dataset '
                    . 'or not activated dataset found'). '::', $this->strErrorMessage);
            $intReturn = 1;
        }
        if ($intMode == 0) {
            $intReturn = $this->getConfigFile($strFile, $intConfigID, $intType, $resCfgFile, $strCfgFile);
            if ($intReturn == 0) {
                $tplConf->parse();
                $strContent = $tplConf->get();
                $intReturn  = $this->writeConfigFile(
                    $strContent,
                    $strFile,
                    $intType,
                    $intConfigID,
                    $resCfgFile,
                    $strCfgFile
                );
            }
        } elseif ($intMode == 1) {
            $tplConf->show();
        }
        return $intReturn;
    }

    /**
     * Get Nagios version string
     * @param int $intConfigID                  Configuration target ID
     * @return string                           Version string
     */
    private function getVersionString($intConfigID)
    {
        $arrVersion = array(
            'Nagios 2.x config file',
            'Nagios 2.9 config file',
            'Nagios 3.x config file',
            'Nagios 4.x config file'
        );
        $this->getConfigData($intConfigID, 'version', $intVersion);
        if (($intVersion >= 1) && ($intVersion <= \count($arrVersion))) {
            $strVersion = $arrVersion[$intVersion - 1];
        } else {
            $strVersion = '';
        }
        return $strVersion;
    }

    /**
     * Skip database values based on Nagios version
     * @param string $strTableName              Table name
     * @param int $intVersionValue              Nagios version value
     * @param string $key                       Data key
     * @param string $value                     Data value
     * @return int
     */
    private function skipEntries($strTableName, $intVersionValue, $key, &$value)
    {
        // Define variables
        $arrOption = array();
        $intReturn = 0;
        // Skip common fields
        $strSpecial  = 'id,active,last_modified,access_rights,access_group,config_id,template,nodelete,command_type,';
        $strSpecial .= 'import_hash';

        // Skip fields of special tables
        if ($strTableName == 'tbl_hosttemplate') {
            $strSpecial .= ',parents_tploptions,hostgroups_tploptions,contacts_tploptions';
            $strSpecial .= ',contact_groups_tploptions,use_template_tploptions';
        }
        if ($strTableName == 'tbl_servicetemplate') {
            $strSpecial .= ',host_name_tploptions,hostgroup_name_tploptions,parents_tploptions,contacts_tploptions';
            $strSpecial .= ',servicegroups_tploptions,contact_groups_tploptions,use_template_tploptions';
        }
        if ($strTableName == 'tbl_contact') {
            $strSpecial .= ',use_template_tploptions,contactgroups_tploptions';
            $strSpecial .= ',host_notification_commands_tploptions,service_notification_commands_tploptions';
        }
        if ($strTableName == 'tbl_contacttemplate') {
            $strSpecial .= ',use_template_tploptions,contactgroups_tploptions';
            $strSpecial .= ',host_notification_commands_tploptions,service_notification_commands_tploptions';
        }
        if ($strTableName == 'tbl_host') {
            $strSpecial .= ',parents_tploptions,hostgroups_tploptions,contacts_tploptions';
            $strSpecial .= ',contact_groups_tploptions,use_template_tploptions';
        }
        if ($strTableName == 'tbl_service') {
            $strSpecial .= ',host_name_tploptions,hostgroup_name_tploptions,parents_tploptions';
            $strSpecial .= ',servicegroups_tploptions,contacts_tploptions,contact_groups_tploptions';
            $strSpecial .= ',use_template_tploptions';
        }

        // Pass fields based on nagios version lower than 3.x
        if ($intVersionValue < 3) {
            if ($strTableName == 'tbl_timeperiod') {
                $strSpecial .= ',use_template,exclude,name';
            }
            if (($strTableName == 'tbl_contact') || ($strTableName == 'tbl_contacttemplate')) {
                $strSpecial .= ',host_notifications_enabled,service_notifications_enabled,can_submit_commands';
                $strSpecial .= ',retain_status_information,retain_nonstatus_information';
                $arrOption['host_notification_options']    = ',s';
                $arrOption['service_notification_options'] = ',s';
            }
            if ($strTableName == 'tbl_contactgroup') {
                $strSpecial .= ',contactgroup_members';
            }
            if ($strTableName == 'tbl_hostgroup') {
                $strSpecial .= ',hostgroup_members,notes,notes_url,action_url';
            }
            if ($strTableName == 'tbl_servicegroup') {
                $strSpecial .= ',servicegroup_members,notes,notes_url,action_url';
            }
            if ($strTableName == 'tbl_hostdependency') {
                $strSpecial .= ',dependent_hostgroup_name,hostgroup_name,dependency_period';
            }
            if ($strTableName == 'tbl_hostescalation') {
                $strSpecial .= ',contacts';
            }
            if ($strTableName == 'tbl_servicedependency') {
                $strSpecial .= ',dependent_hostgroup_name,hostgroup_name,dependency_period,dependent_servicegroup_name';
                $strSpecial .= ',servicegroup_name';
            }
            if ($strTableName == 'tbl_serviceescalation') {
                $strSpecial .= ',hostgroup_name,contacts,servicegroup_name';
            }
            if (($strTableName == 'tbl_host') || ($strTableName == 'tbl_hosttemplate')) {
                $strSpecial .= ',initial_state,flap_detection_options,contacts,notes,notes_url,action_url';
                $strSpecial .= ',icon_image,icon_image_alt,vrml_image,statusmap_image,2d_coords,3d_coords';
                $arrOption['notification_options'] = ',s';
            }
            // Services
            if (($strTableName == 'tbl_service') || ($strTableName == 'tbl_servicetemplate')) {
                $strSpecial .= ',initial_state,flap_detection_options,contacts,notes,notes_url,action_url';
                $strSpecial .= ',icon_image,icon_image_alt';
                $arrOption['notification_options'] = ',s';
            }
        }
        // Pass fields based on nagios version higher than 2.x
        if ($intVersionValue > 2) {
            if ($strTableName == 'tbl_servicetemplate') {
                $strSpecial .= ',parallelize_check ';
            }
            if ($strTableName == 'tbl_service') {
                $strSpecial .= ',parallelize_check';
            }
        }
        // Pass fields based on nagios version lower than 4.x
        if ($intVersionValue < 4) {
            if (($strTableName == 'tbl_contact') || ($strTableName == 'tbl_contacttemplate')) {
                $strSpecial .= ',minimum_importance';
            }
            if ($strTableName == 'tbl_host') {
                $strSpecial .= ',importance';
            }
            if (($strTableName == 'tbl_service') || ($strTableName == 'tbl_servicetemplate')) {
                $strSpecial .= ',importance,parents';
            }
        }
        if ($intVersionValue == 1) {
            $strSpecial .= '';
        }
        // Reduce option values
        if (array_key_exists($key, $arrOption) && (\count($arrOption) != 0)) {
            $value = str_replace(array($arrOption[$key], str_replace(',', '', $arrOption[$key])), '', $value);
            if ($value == '') {
                $intReturn = 1;
            }
        }
        if ($intReturn == 0) {
            // Skip entries
            $arrSpecial = explode(',', $strSpecial);
            if (($value == '') || \in_array($key, $arrSpecial, true)) {
                $intReturn = 1;
            }
        }
        if ($intReturn == 0) {
            // Do not write config data (based on 'skip' option)
            $strNoTwo  = 'active_checks_enabled,passive_checks_enabled,obsess_over_host,check_freshness,';
            $strNoTwo .= 'event_handler_enabled,flap_detection_enabled,process_perf_data,retain_status_information,';
            $strNoTwo .= 'retain_nonstatus_information,notifications_enabled,parallelize_check,is_volatile,';
            $strNoTwo .= 'host_notifications_enabled,service_notifications_enabled,can_submit_commands,';
            $strNoTwo .= 'obsess_over_service';
            foreach (explode(',', $strNoTwo) as $elem) {
                if (($key == $elem) && ($value == '2')) {
                    $intReturn = 1;
                }
                if (($intVersionValue < 3) && ($key == $elem) && ($value == '3')) {
                    $intReturn = 1;
                }
            }
        }
        return $intReturn;
    }

    /**
     * Get related data
     * @param string $strTableName              Table name
     * @param \HTML_Template_IT $resTemplate    Template ressource
     * @param array $arrData                    Dataset array
     * @param string $strDataKey                Data key
     * @param string $strDataValue              Data value
     * @return int                              0 = use data / 1 = skip data
     *                                          Status message is stored in message class variables
     */
    private function getRelationData($strTableName, $resTemplate, $arrData, $strDataKey, &$strDataValue)
    {
        // Define Variables
        $intReturn    = 0;
        $intSkipProc  = 0;
        $arrRelations = array();
        // Pass function for tbl_command
        if ($strTableName == 'tbl_command') {
            $intSkipProc = 1;
        }
        // Get relation info and store the value in a class variable (speedup export)
        if (($intSkipProc == 0) && ($this->strRelTable != $strTableName)) {
            $intReturn = $this->myDataClass->tableRelations($strTableName, $arrRelations);
            $this->strRelTable = $strTableName;
            $this->arrRelData  = $arrRelations;
        } elseif ($intSkipProc == 0) {
            $arrRelations = $this->arrRelData;
            $intReturn   = 0;
        }
        if (($intSkipProc == 0) && (!\is_array($arrRelations)) && (\count($arrRelations) == 0)) {
            $intSkipProc = 1;
            $intReturn   = 1;
        }
        if ($intSkipProc == 0) {
            // Common domain is enabled?
            $this->getDomainData('enable_common', $intCommonEnable);
            if ($intCommonEnable == 1) {
                $strDomainWhere1 = ' (`config_id`=' . $this->intDomainId . ' OR `config_id`=0) ';
            } else {
                $strDomainWhere1 = ' `config_id`=' . $this->intDomainId . ' ';
            }
            // Process relations
            foreach ($arrRelations as $elem) {
                if ($elem['fieldName'] == $strDataKey) {
                    // Process normal 1:n relations (1 = only data / 2 = including a * value)
                    if (($elem['type'] == 2) && (($strDataValue == 1) || ($strDataValue == 2))) {
                        $intReturn = $this->processRelation1($arrData, $strDataValue, $elem, $strDomainWhere1);
                        // Process normal 1:1 relations
                    } elseif ($elem['type'] == 1) {
                        $intReturn = $this->processRelation2($arrData, $strDataValue, $elem, $strDomainWhere1);
                        // Process normal 1:n relations with special table and idSort (template tables)
                    } elseif (($elem['type'] == 3) && ($strDataValue == 1)) {
                        $intReturn = $this->processRelation3($arrData, $strDataValue, $elem, $strDomainWhere1);
                        // Process special 1:n:str relations with string values (servicedependencies)
                    } elseif (($elem['type'] == 6) && (($strDataValue == 1) || ($strDataValue == 2))) {
                        $intReturn = $this->processRelation4($arrData, $strDataValue, $elem, $strDomainWhere1);
                        // Process special relations for free variables
                    } elseif (($elem['type'] == 4) && ($strDataValue == 1) && ($this->intNagVersion >= 3)) {
                        $intReturn = $this->processRelation5($resTemplate, $arrData, $elem);
                        // Process special relations for service groups
                    } elseif (($elem['type'] == 5) && ($strDataValue == 1)) {
                        $intReturn = $this->processRelation6($arrData, $strDataValue, $elem, $strDomainWhere1);
                        // Process special relations for service parents
                    } elseif (($elem['type'] == 7) && ($strDataValue == 1)) {
                        $intReturn = $this->processRelation7($arrData, $strDataValue, $elem);
                        // Process "*"
                    } elseif ($strDataValue == 2) {
                        $strDataValue = '*';
                    } else {
                        $intReturn = 1;
                    }
                }
            }
        }
        return $intReturn;
    }

    /**
     * Rename field names
     * @param string $strTableName              Table name
     * @param int $intConfigID                  Configuration target ID
     * @param int $intDataId                    Data ID
     * @param string $key                       Data key (by reference)
     * @param string $value                     Data value (by reference)
     * @param int $intSkip                      Skip value (by reference) 1 = skip / 0 = pass
     */
    private function renameFields($strTableName, $intConfigID, $intDataId, &$key, &$value, &$intSkip)
    {
        if ($this->intNagVersion == 0) {
            $this->getConfigData($intConfigID, 'version', $this->intNagVersion);
        }
        // Picture path
        if ($this->strPicPath == 'none') {
            $this->getConfigData($intConfigID, 'picturedir', $this->strPicPath);
        }
        if ($key == 'icon_image') {
            $value = $this->strPicPath.$value;
        }
        if ($key == 'vrml_image') {
            $value = $this->strPicPath.$value;
        }
        if ($key == 'statusmap_image') {
            $value = $this->strPicPath.$value;
        }
        // Tables
        if ($strTableName == 'tbl_host') {
            if ($key == 'use_template') {
                $key = 'use';
            }
            $strVIValues  = 'active_checks_enabled,passive_checks_enabled,check_freshness,obsess_over_host,';
            $strVIValues .= 'event_handler_enabled,flap_detection_enabled,process_perf_data,retain_status_information,';
            $strVIValues .= 'retain_nonstatus_information,notifications_enabled';
            if (\in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'parents') {
                $value = $this->checkTpl($value, 'parents_tploptions', 'tbl_host', $intDataId, $intSkip);
            }
            if ($key == 'hostgroups') {
                $value = $this->checkTpl($value, 'hostgroups_tploptions', 'tbl_host', $intDataId, $intSkip);
            }
            if ($key == 'contacts') {
                $value = $this->checkTpl($value, 'contacts_tploptions', 'tbl_host', $intDataId, $intSkip);
            }
            if ($key == 'contact_groups') {
                $value = $this->checkTpl($value, 'contact_groups_tploptions', 'tbl_host', $intDataId, $intSkip);
            }
            if ($key == 'use') {
                $value = $this->checkTpl($value, 'use_template_tploptions', 'tbl_host', $intDataId, $intSkip);
            }
            if ($key == 'check_command') {
                $value = str_replace("\::bang::", "\!", $value);
            }
            if ($key == 'check_command') {
                $value = str_replace('::bang::', "\!", $value);
            }
        }
        if ($strTableName == 'tbl_service') {
            if ($key == 'use_template') {
                $key = 'use';
            }
            if ($this->intNagVersion < 2) {
                if ($key == 'check_interval') {
                    $key = 'normal_check_interval';
                }
                if ($key == 'retry_interval') {
                    $key = 'retry_check_interval';
                }
            }
            $strVIValues  = 'is_volatile,active_checks_enabled,passive_checks_enabled,parallelize_check,';
            $strVIValues .= 'obsess_over_service,check_freshness,event_handler_enabled,flap_detection_enabled,';
            $strVIValues .= 'process_perf_data,retain_status_information,retain_nonstatus_information,';
            $strVIValues .= 'notifications_enabled';
            if (\in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'host_name') {
                $value = $this->checkTpl($value, 'host_name_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'hostgroup_name') {
                $value = $this->checkTpl($value, 'hostgroup_name_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'parents') {
                $value = $this->checkTpl($value, 'parents_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'servicegroups') {
                $value = $this->checkTpl($value, 'servicegroups_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'contacts') {
                $value = $this->checkTpl($value, 'contacts_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'contact_groups') {
                $value = $this->checkTpl($value, 'contact_groups_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'use') {
                $value = $this->checkTpl($value, 'use_template_tploptions', 'tbl_service', $intDataId, $intSkip);
            }
            if ($key == 'check_command') {
                $value = str_replace("\::bang::", "\!", $value);
            }
            if ($key == 'check_command') {
                $value = str_replace('::bang::', "\!", $value);
            }
        }
        if ($strTableName == 'tbl_hosttemplate') {
            if ($key == 'template_name') {
                $key = 'name';
            }
            if ($key == 'use_template') {
                $key = 'use';
            }
            $strVIValues  = 'active_checks_enabled,passive_checks_enabled,check_freshness,obsess_over_host,';
            $strVIValues .= 'event_handler_enabled,flap_detection_enabled,process_perf_data,retain_status_information,';
            $strVIValues .= 'retain_nonstatus_information,notifications_enabled';
            if (\in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'parents') {
                $value = $this->checkTpl($value, 'parents_tploptions', 'tbl_hosttemplate', $intDataId, $intSkip);
            }
            if ($key == 'hostgroups') {
                $value = $this->checkTpl($value, 'hostgroups_tploptions', 'tbl_hosttemplate', $intDataId, $intSkip);
            }
            if ($key == 'contacts') {
                $value = $this->checkTpl($value, 'contacts_tploptions', 'tbl_hosttemplate', $intDataId, $intSkip);
            }
            if ($key == 'contact_groups') {
                $value = $this->checkTpl($value, 'contact_groups_tploptions', 'tbl_hosttemplate', $intDataId, $intSkip);
            }
            if ($key == 'use') {
                $value = $this->checkTpl($value, 'use_template_tploptions', 'tbl_hosttemplate', $intDataId, $intSkip);
            }
        }
        if ($strTableName == 'tbl_servicetemplate') {
            if ($key == 'template_name') {
                $key = 'name';
            }
            if ($key == 'use_template') {
                $key = 'use';
            }
            if ($this->intNagVersion < 2) {
                if ($key == 'check_interval') {
                    $key = 'normal_check_interval';
                }
                if ($key == 'retry_interval') {
                    $key = 'retry_check_interval';
                }
            }
            $strVIValues  = 'is_volatile,active_checks_enabled,passive_checks_enabled,parallelize_check,';
            $strVIValues .= 'obsess_over_service,check_freshness,event_handler_enabled,flap_detection_enabled,';
            $strVIValues .= 'process_perf_data,retain_status_information,retain_nonstatus_information,';
            $strVIValues .= 'notifications_enabled';
            if (\in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'host_name') {
                $value = $this->checkTpl($value, 'host_name_tploptions', 'tbl_servicetemplate', $intDataId, $intSkip);
            }
            if ($key == 'hostgroup_name') {
                $value = $this->checkTpl(
                    $value,
                    'hostgroup_name_tploptions',
                    'tbl_servicetemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'parents') {
                $value = $this->checkTpl($value, 'parents_tploptions', 'tbl_servicetemplate', $intDataId, $intSkip);
            }
            if ($key == 'servicegroups') {
                $value = $this->checkTpl(
                    $value,
                    'servicegroups_tploptions',
                    'tbl_servicetemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'contacts') {
                $value = $this->checkTpl($value, 'contacts_tploptions', 'tbl_servicetemplate', $intDataId, $intSkip);
            }
            if ($key == 'contact_groups') {
                $value = $this->checkTpl(
                    $value,
                    'contact_groups_tploptions',
                    'tbl_servicetemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'use') {
                $value = $this->checkTpl(
                    $value,
                    'use_template_tploptions',
                    'tbl_servicetemplate',
                    $intDataId,
                    $intSkip
                );
            }
        }
        if ($strTableName == 'tbl_contact') {
            if ($key == 'use_template') {
                $key = 'use';
            }
            $strVIValues  = 'host_notifications_enabled,service_notifications_enabled,can_submit_commands,';
            $strVIValues .= 'retain_status_information,retain_nonstatus_information';
            if (\in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'contactgroups') {
                $value = $this->checkTpl($value, 'contactgroups_tploptions', 'tbl_contact', $intDataId, $intSkip);
            }
            if ($key == 'host_notification_commands') {
                $value = $this->checkTpl(
                    $value,
                    'host_notification_commands_tploptions',
                    'tbl_contact',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'service_notification_commands') {
                $value = $this->checkTpl(
                    $value,
                    'service_notification_commands_tploptions',
                    'tbl_contact',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'use') {
                $value = $this->checkTpl($value, 'use_template_tploptions', 'tbl_contact', $intDataId, $intSkip);
            }
        }
        if ($strTableName == 'tbl_contacttemplate') {
            if ($key == 'template_name') {
                $key = 'name';
            }
            if ($key == 'use_template') {
                $key = 'use';
            }
            $strVIValues  = 'host_notifications_enabled,service_notifications_enabled,can_submit_commands,';
            $strVIValues .= 'retain_status_information,retain_nonstatus_information';
            if (in_array($key, explode(',', $strVIValues), true)) {
                if ($value == -1) {
                    $value = 'null';
                }
                if ($value == 3) {
                    $value = 'null';
                }
            }
            if ($key == 'contactgroups') {
                $value = $this->checkTpl(
                    $value,
                    'contactgroups_tploptions',
                    'tbl_contacttemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'host_notification_commands') {
                $value = $this->checkTpl(
                    $value,
                    'host_notification_commands_tploptions',
                    'tbl_contacttemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'service_notification_commands') {
                $value = $this->checkTpl(
                    $value,
                    'service_notification_commands_tploptions',
                    'tbl_contacttemplate',
                    $intDataId,
                    $intSkip
                );
            }
            if ($key == 'use') {
                $value = $this->checkTpl(
                    $value,
                    'use_template_tploptions',
                    'tbl_contacttemplate',
                    $intDataId,
                    $intSkip
                );
            }
        }
        if ((($strTableName == 'tbl_hosttemplate') || ($strTableName == 'tbl_servicetemplate') ||
                ($strTableName == 'tbl_contacttemplate')) && $key == 'register') {
            $value = '0';
        }
        if ($strTableName == 'tbl_timeperiod' && $key == 'use_template') {
            $key = 'use';
        }
    }

    /**
     * Open configuration file
     * @param string $strFile                   File name
     * @param int $intConfigID                  Configuration ID
     * @param int $intType                      Type ID
     * @param resource|bool $resConfigFile      Temporary or configuration file ressource (by reference)
     * @param string $strConfigFile             Configuration file name (by reference)
     * @return int                              0 = successful / 1 = error
     */
    private function getConfigFile($strFile, $intConfigID, $intType, &$resConfigFile, &$strConfigFile)
    {
        // Variable definitions
        $strBaseDir   = '';
        $intMethod    = 1;
        $intReturn    = 0;
        // Get config data
        if ($intType == 1) {
            $this->getConfigData($intConfigID, 'hostconfig', $strBaseDir);
            $strType = 'host';
        } elseif ($intType == 2) {
            $this->getConfigData($intConfigID, 'serviceconfig', $strBaseDir);
            $strType = 'service';
        } else {
            $this->getConfigData($intConfigID, 'basedir', $strBaseDir);
            $strType = 'basic';
        }
        $this->getConfigData($intConfigID, 'method', $intMethod);
        // Backup config file
        $this->moveFile($strType, $strFile, $intConfigID);
        // Variable definition
        $strConfigFile = $strBaseDir. '/' .$strFile;
        // Local file system
        if ($intMethod == 1) {
            // Save configuration file
            if (is_writable($strConfigFile) || (!file_exists($strConfigFile) && is_writable($strBaseDir))) {
                $resConfigFile = fopen($strConfigFile, 'wb');
                chmod($strConfigFile, 0644);
            } else {
                $this->myDataClass->writeLog(translate('Configuration write failed:'). ' ' .$strFile);
                $this->processClassMessage(translate('Cannot open/overwrite the configuration file (check the '
                        .'permissions)!'). '::', $this->strErrorMessage);
                $intReturn = 1;
            }
        } elseif ($intMethod == 2) { // Remote file (FTP)
            // Check connection
            if (empty($this->resConnectId) || !\is_resource($this->resConnectId) ||
                ($this->resConnectType != 'FTP')) {
                $intReturn = $this->getFTPConnection($intConfigID);
            }
            if ($intReturn == 0) {
                // Open the config file
                if (isset($this->arrSettings['path']) && isset($this->arrSettings['path']['tempdir'])) {
                    $strConfigFile = tempnam($this->arrSettings['path']['tempdir'], 'nagiosql');
                } else {
                    $strConfigFile = tempnam(sys_get_temp_dir(), 'nagiosql');
                }
                $resConfigFile = fopen($strConfigFile, 'wb');
            }
        } elseif ($intMethod == 3) { // Remote file (SFTP)
            // Check connection
            if (empty($this->resConnectId) || !\is_resource($this->resConnectId) ||
                ($this->resConnectType != 'SSH')) {
                $intReturn = $this->getSSHConnection($intConfigID);
            }
            if ($intReturn == 0) {
                if (isset($this->arrSettings['path']) && isset($this->arrSettings['path']['tempdir'])) {
                    $strConfigFile = tempnam($this->arrSettings['path']['tempdir'], 'nagiosql');
                } else {
                    $strConfigFile = tempnam(sys_get_temp_dir(), 'nagiosql');
                }
                $resConfigFile = fopen($strConfigFile, 'wb');
            }
        }
        return $intReturn;
    }

    /**
     * Write configuration file
     * @param string $strData               Data string
     * @param string $strFile               File name
     * @param int $intType                  Type ID
     * @param int $intConfigID              Configuration target ID
     * @param resource $resConfigFile       Temporary or configuration file ressource
     * @param string $strConfigFile         Configuration file name
     * @return int                          0 = successful / 1 = error
     */
    private function writeConfigFile($strData, $strFile, $intType, $intConfigID, $resConfigFile, $strConfigFile)
    {
        // Variable definitions
        $intReturn = 0;
        // Get config data
        if ($intType == 1) {
            $this->getConfigData($intConfigID, 'hostconfig', $strBaseDir);
        } elseif ($intType == 2) {
            $this->getConfigData($intConfigID, 'serviceconfig', $strBaseDir);
        } else {
            $this->getConfigData($intConfigID, 'basedir', $strBaseDir);
        }
        $this->getConfigData($intConfigID, 'method', $intMethod);
        $strData  = str_replace("\r\n", "\n", $strData);
        fwrite($resConfigFile, $strData);
        // Local filesystem
        if ($intMethod == 1) {
            fclose($resConfigFile);
        } elseif ($intMethod == 2) { // FTP access
            // SSH Possible
            if (!\function_exists('ftp_put')) {
                $this->processClassMessage(translate('FTP module not loaded!'). '::', $this->strErrorMessage);
                $intReturn = 1;
            } else {
                $intErrorReporting = error_reporting();
                error_reporting(0);
                if (!ftp_put($this->resConnectId, $strBaseDir . '/' . $strFile, $strConfigFile, FTP_ASCII)) {
                    $arrError = error_get_last();
                    error_reporting($intErrorReporting);
                    $this->processClassMessage(translate('Cannot open/overwrite the configuration file (FTP connection '
                            .'failed)!') . '::', $this->strErrorMessage);
                    if ($arrError['message'] != '') {
                        $this->processClassMessage($arrError['message'] . '::', $this->strErrorMessage);
                    }
                    $intReturn = 1;
                }
                error_reporting($intErrorReporting);
                ftp_close($this->resConnectId);
                fclose($resConfigFile);
            }
        } elseif ($intMethod == 3) { // SSH access
            // SSH Possible
            if (!\function_exists('ssh2_scp_send')) {
                $this->processClassMessage(translate('SSH module not loaded!'). '::', $this->strErrorMessage);
                $intReturn = 1;
            } else {
                $intErrorReporting = error_reporting();
                error_reporting(0);
                if (!ssh2_scp_send($this->resConnectId, $strConfigFile, $strBaseDir . '/' . $strFile, 0644)) {
                    $arrError = error_get_last();
                    error_reporting($intErrorReporting);
                    $this->processClassMessage(translate('Cannot open/overwrite the configuration file (remote SFTP)!').
                        '::', $this->strErrorMessage);
                    if ($arrError['message'] != '') {
                        $this->processClassMessage($arrError['message'] . '::', $this->strErrorMessage);
                    }
                    $this->resConnectId = null;
                    $intReturn = 1;
                }
                error_reporting($intErrorReporting);
                fclose($resConfigFile);
                unlink($strConfigFile);
                $this->resConnectId = null;
            }
        }
        if ($intReturn == 0) {
            $this->myDataClass->writeLog(translate('Configuration successfully written:') . ' ' . $strFile);
            $this->processClassMessage(translate('Configuration file successfully written!').
                '::', $this->strInfoMessage);
        }
        return $intReturn;
    }

    /**
     * Process special settings based on template option
     * @param string $strValue              Original data value
     * @param string $strKeyField           Template option field name
     * @param string $strTable              Table name
     * @param int $intId                    Dataset ID
     * @param int $intSkip                  Skip value (by reference)
     * @return string                       Manipulated data value
     */
    public function checkTpl($strValue, $strKeyField, $strTable, $intId, &$intSkip)
    {
        if ($this->intNagVersion < 3) {
            return $strValue;
        }
        $strSQL   = 'SELECT `' .$strKeyField. '` FROM `' .$strTable."` WHERE `id` = $intId";
        $intValue = $this->myDBClass->getFieldData($strSQL);
        if ($intValue == 0) {
            return('+' .$strValue);
        }
        if ($intValue == 1) {
            $intSkip = 0;
            return 'null';
        }
        return $strValue;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @param string $strDomainWhere1           SQL WHERE add-in
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation1($arrData, &$strDataValue, $elem, $strDomainWhere1)
    {
        // Define variables
        $arrDataRel      = array();
        $intDataCountRel = 0;
        $intReturn       = 0;
        // Get relation data
        $strSQLRel = 'SELECT `' . $elem['tableName1'] . '`.`' . $elem['target1'] . '`, `' . $elem['linkTable'] .
            '`.`exclude` FROM `' . $elem['linkTable'] . '` LEFT JOIN `' . $elem['tableName1'] .
            '` ON `' . $elem['linkTable'] . '`.`idSlave` = `' . $elem['tableName1'] . '`.`id`' .
            'WHERE `idMaster`=' . $arrData['id'] . " AND `active`='1' AND $strDomainWhere1" .
            'ORDER BY `' . $elem['tableName1'] . '`.`' . $elem['target1'] . '`';
        $booReturn = $this->myDBClass->hasDataArray($strSQLRel, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            if ($strDataValue == 2) {
                $strDataValue = '*,';
            } else {
                $strDataValue = '';
            }
            foreach ($arrDataRel as $data) {
                if ($data['exclude'] == 0) {
                    $strDataValue .= $data[$elem['target1']] . ',';
                } elseif ($this->intNagVersion >= 3) {
                    $strDataValue .= '!' . $data[$elem['target1']] . ',';
                }
            }
            $strDataValue = substr($strDataValue, 0, -1);
            if ($strDataValue == '') {
                $intReturn = 1;
            }
        } else {
            if ($strDataValue == 2) {
                $strDataValue = '*';
            } else {
                $intReturn = 1;
            }
        }
        return $intReturn;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @param string $strDomainWhere1           SQL WHERE add-in
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation2($arrData, &$strDataValue, $elem, $strDomainWhere1)
    {
        // Define variables
        $arrDataRel      = array();
        $arrField        = array();
        $intDataCountRel = 0;
        $intReturn       = 0;
        $strCommand      = '';
        // Get relation data
        if (($elem['tableName1'] == 'tbl_command') &&
            (substr_count($arrData[$elem['fieldName']], '!') != 0)) {
            $arrField = explode('!', $arrData[$elem['fieldName']]);
            $strCommand = strstr($arrData[$elem['fieldName']], '!');
            $strSQLRel = 'SELECT `' . $elem['target1'] . '` FROM `' . $elem['tableName1'] . '`' .
                'WHERE `id`=' . $arrField[0] . "  AND `active`='1' AND $strDomainWhere1";
        } else {
            $strSQLRel = 'SELECT `' . $elem['target1'] . '` FROM `' . $elem['tableName1'] . '`' .
                'WHERE `id`=' . $arrData[$elem['fieldName']] . "  AND `active`='1' AND $strDomainWhere1";
        }
        $booReturn = $this->myDBClass->hasDataArray($strSQLRel, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            if (($elem['tableName1'] == 'tbl_command') && (substr_count($strDataValue, '!') != 0)) {
                $strDataValue = $arrDataRel[0][$elem['target1']] . $strCommand;
            } else {
                $strDataValue = $arrDataRel[0][$elem['target1']];
            }
        } else {
            if (($elem['tableName1'] == 'tbl_command') && (substr_count($strDataValue, '!') != 0) &&
                ($arrField[0] == -1)) {
                $strDataValue = 'null';
            } else {
                $intReturn = 1;
            }
        }
        return $intReturn;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @param string $strDomainWhere1           SQL WHERE add-in
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation3($arrData, &$strDataValue, $elem, $strDomainWhere1)
    {
        // Define variables
        $arrDataRel      = array();
        $intDataCountRel = 0;
        $intReturn       = 0;
        // Get relation data
        $strSQLRel = 'SELECT * FROM `' .$elem['linkTable']. '` WHERE `idMaster`=' .$arrData['id']. ' ORDER BY idSort';
        $booReturn = $this->myDBClass->hasDataArray($strSQLRel, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            $strDataValue = '';
            foreach ($arrDataRel as $data) {
                if ($data['idTable'] == 1) {
                    $strSQLName = 'SELECT `' .$elem['target1']. '` FROM `' .$elem['tableName1']. '`' .
                        "WHERE `active`='1' AND $strDomainWhere1 AND `id`=".$data['idSlave'];
                } else {
                    $strSQLName = 'SELECT `' .$elem['target2']. '` FROM `' .$elem['tableName2']. '`' .
                        "WHERE `active`='1' AND $strDomainWhere1 AND `id`=".$data['idSlave'];
                }
                $strDataValue .= $this->myDBClass->getFieldData($strSQLName) . ',';
            }
            $strDataValue = substr($strDataValue, 0, -1);
        } else {
            $intReturn = 1;
        }
        return $intReturn;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @param string $strDomainWhere1           SQL WHERE add-in
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation4($arrData, &$strDataValue, $elem, $strDomainWhere1)
    {
        // Define variables
        $arrDataRel      = array();
        $intDataCountRel = 0;
        $intReturn       = 0;
        // Get relation data
        $strSQLRel = 'SELECT `' .$elem['linkTable']. '`.`strSlave`, `' .$elem['linkTable']. '`.`exclude` ' .
            'FROM `' .$elem['linkTable']. '` ' .
            'LEFT JOIN `tbl_service` ON `' .$elem['linkTable']. '`.`idSlave`=`tbl_service`.`id` ' .
            'WHERE `' .$elem['linkTable']. '`.`idMaster`=' .$arrData['id']." AND `active`='1' AND ".
            $strDomainWhere1. ' ' .
            'ORDER BY `' .$elem['linkTable']. '`.`strSlave`';
        $booReturn = $this->myDBClass->hasDataArray($strSQLRel, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            if ($strDataValue == 2) {
                $strDataValue = '*,';
            } else {
                $strDataValue = '';
            }
            foreach ($arrDataRel as $data) {
                if ($data['exclude'] == 0) {
                    $strDataValue .= $data['strSlave'] . ',';
                } elseif ($this->intNagVersion >= 3) {
                    $strDataValue .= '!' . $data['strSlave'] . ',';
                }
            }
            $strDataValue = substr($strDataValue, 0, -1);
            if ($strDataValue == '') {
                $intReturn = 1;
            }
        } else {
            if ($strDataValue == 2) {
                $strDataValue = '*';
            } else {
                $intReturn = 1;
            }
        }
        return $intReturn;
    }

    /**
     * @param \HTML_Template_IT $resTemplate    Template object
     * @param array $arrData                    Dataset array
     * @param array $elem                       Relation data array
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation5($resTemplate, $arrData, $elem)
    {
        // Define variables
        $arrDataRel      = array();
        $intDataCountRel = 0;
        $strSQLRel = 'SELECT * FROM `tbl_variabledefinition` LEFT JOIN `' .$elem['linkTable']. '` ' .
            'ON `id`=`idSlave` WHERE `idMaster`=' .$arrData['id']. ' ORDER BY `name`';
        $booReturn = $this->myDBClass->hasDataArray($strSQLRel, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            foreach ($arrDataRel as $vardata) {
                // Insert fill spaces
                $strFillLen = (30 - \strlen($vardata['name']));
                $strSpace = ' ';
                for ($f = 0; $f < $strFillLen; $f++) {
                    $strSpace .= ' ';
                }
                $resTemplate->setVariable('ITEM_TITLE', $vardata['name'] . $strSpace);
                $resTemplate->setVariable('ITEM_VALUE', $vardata['value']);
                $resTemplate->parse('configline');
            }
        }
        return 1;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @param string $strDomainWhere1           SQL WHERE add-in
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation6($arrData, &$strDataValue, $elem, $strDomainWhere1)
    {
        // Define variables
        $arrDataRel = array();
        $arrHG1 = array();
        $arrHG2 = array();
        $intDataCountRel = 0;
        $intHG1 = 0;
        $intHG2 = 0;
        $intReturn = 0;
        // Get relation data
        $strSQLMaster = 'SELECT * FROM `' . $elem['linkTable'] . '` WHERE `idMaster`=' . $arrData['id'];
        $booReturn = $this->myDBClass->hasDataArray($strSQLMaster, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            $strDataValue = '';
            foreach ($arrDataRel as $data) {
                if ($data['idSlaveHG'] != 0) {
                    $strSQLSrv = 'SELECT `' . $elem['target2'] . '` FROM `' . $elem['tableName2'] .
                        '` WHERE `id`=' . $data['idSlaveS'];
                    $strService = $this->myDBClass->getFieldData($strSQLSrv);
                    $strSQLHG1 = 'SELECT `host_name` FROM `tbl_host` ' .
                        'LEFT JOIN `tbl_lnkHostgroupToHost` ON `id`=`idSlave` ' .
                        'WHERE `idMaster`=' . $data['idSlaveHG'] . "  AND `active`='1' AND $strDomainWhere1";
                    $booReturn = $this->myDBClass->hasDataArray($strSQLHG1, $arrHG1, $intHG1);
                    if ($booReturn && ($intHG1 != 0)) {
                        foreach ($arrHG1 as $elemHG1) {
                            if (substr_count($strDataValue, $elemHG1['host_name'] . ',' . $strService) == 0) {
                                $strDataValue .= $elemHG1['host_name'] . ',' . $strService . ',';
                            }
                        }
                    }
                    $strSQLHG2 = 'SELECT `host_name` FROM `tbl_host` ' .
                        'LEFT JOIN `tbl_lnkHostToHostgroup` ON `id`=`idMaster` ' .
                        'WHERE `idSlave`=' . $data['idSlaveHG'] . "  AND `active`='1' AND $strDomainWhere1";
                    $booReturn = $this->myDBClass->hasDataArray($strSQLHG2, $arrHG2, $intHG2);
                    if ($booReturn && ($intHG2 != 0)) {
                        foreach ($arrHG2 as $elemHG2) {
                            if (substr_count($strDataValue, $elemHG2['host_name'] . ',' . $strService) == 0) {
                                $strDataValue .= $elemHG2['host_name'] . ',' . $strService . ',';
                            }
                        }
                    }
                } else {
                    $strSQLHost = 'SELECT `' . $elem['target1'] . '` FROM `' . $elem['tableName1'] . '` ' .
                        'WHERE `id`=' . $data['idSlaveH'] . "  AND `active`='1' AND $strDomainWhere1";
                    $strHost = $this->myDBClass->getFieldData($strSQLHost);
                    $strSQLSrv = 'SELECT `' . $elem['target2'] . '` FROM `' . $elem['tableName2'] . '` ' .
                        'WHERE `id`=' . $data['idSlaveS'] . "  AND `active`='1' AND $strDomainWhere1";
                    $strService = $this->myDBClass->getFieldData($strSQLSrv);
                    if (($strHost != '') && ($strService != '') &&
                        substr_count($strDataValue, $strHost . ',' . $strService) == 0) {
                        $strDataValue .= $strHost . ',' . $strService . ',';
                    }
                }
            }
            $strDataValue = substr($strDataValue, 0, -1);
            if ($strDataValue == '') {
                $intReturn = 1;
            }
        } else {
            $intReturn = 1;
        }
        return $intReturn;
    }

    /**
     * @param array $arrData                    Dataset array
     * @param string $strDataValue              Data value
     * @param array $elem                       Relation data array
     * @return int                              0 = use data / 1 = skip data
     */
    private function processRelation7($arrData, &$strDataValue, $elem)
    {
        $intReturn = 1;
        // Get relation data
        $strSQLMaster = 'SELECT * FROM `' . $elem['linkTable'] . '` WHERE `idMaster`=' . $arrData['id'];
        $booReturn = $this->myDBClass->hasDataArray($strSQLMaster, $arrDataRel, $intDataCountRel);
        if ($booReturn && ($intDataCountRel != 0)) {
            // Rewrite $strDataValue with returned relation data
            $strDataValue = '';
            /** @var array $arrDataRel */
            foreach ($arrDataRel as $data) {
                $strSQL = 'SELECT host_name FROM tbl_host WHERE id=' .$data['idHost'];
                $strHost = $this->myDBClass->getFieldData($strSQL);
                $strSQL = 'SELECT service_description FROM tbl_service WHERE id=' .$data['idSlave'];
                $strService = $this->myDBClass->getFieldData($strSQL);
                $strDataValue .= $strHost . ',' . $strService . ',';
                $intReturn = 0;
            }
            $strDataValue = substr($strDataValue, 0, -1);
        }
        return $intReturn;
    }
}