<?php
/**
 * CodeIgniter library
 *
 * @category CodeIgniter
 * @license /_licenses/untermStrich/agb_normal.pdf
 * @author Christian Koller
 * @copyright 2009 untermStrich
 * @package libraries
 * @version $Id$
*/

if (!defined('BASEPATH')) { exit('No direct script access allowed'); }

/**
 * Shows infos about the system
 */
class US_Sysinfo
{
    const MIN_JAVA = 10;
    const MAX_JAVA = 21;
    const PADD_KEY = 35;
    protected $version_apache = false;
    protected $is_windows = false;
    protected $use_html = true;
    protected $all_ok = true;
    protected $reply = '';
    protected $cli_mode = false;
    protected $fpm_mode = false;
    private $_sysmod_log_values = null;
    
    /**
     * Constructor
     */
    public function __construct()
    {
        if (strtoupper(substr(PHP_OS, 0, 3))==='WIN') {
            $this->is_windows = true;
        }

        $sapi_type = substr( php_sapi_name(), 0, 3);
        $this->cli_mode = (strtolower($sapi_type)==='cli');
        $this->fpm_mode = (strtolower($sapi_type)==='fpm');
        
        $this->version_apache = false;
        
        if  ($this->fpm_mode) {
            $this->version_apache = 2;
        }
        
        if (array_key_exists('SERVER_SOFTWARE', $_SERVER)) {
            $this->_set_apache_version($_SERVER['SERVER_SOFTWARE']);
        }
        
        if ($this->version_apache === false && function_exists('apache_get_version')) {
            $server_software = apache_get_version();
            $this->_set_apache_version($server_software);
            
            if ($this->version_apache === false) {
                $this->version_apache = 2;
            }
        }
        
        if ( strtoupper(getenv('APACHE2_ACTIVE'))=='ON' ) {
            $this->version_apache = 2;
        }
    }
    
    /**
     * Get value from system_modification_log
     * 
     * @param string    $key    The key to set
     */
    private function _get_system_modifications_log_value($key)
    {
        $CI = CI_Controller::get_instance();

        if ($this->_sysmod_log_values === null) {
            $CI->load->us_library('value_objects/system_modifications_log_values');
            $this->_sysmod_log_values = System_modifications_log_values::init();
        }
        
        $method = "get_".$key;
        return $this->_sysmod_log_values->$method();
    }
    
    /**
     * Update the system_modifications_log when values have changed
     */
    public function update_system_modifications_log()
    {
        $CI = CI_Controller::get_instance();
        
        $CI->load->model('System_modifications_log_model', 'system_modifications_log', true);
        
        if ($this->_sysmod_log_values === null) {
            $CI->load->us_library('value_objects/system_modifications_log_values');
            $this->_sysmod_log_values = System_modifications_log_values::init();
        }
        
        $stat = $CI->system_modifications_log->update($this->_sysmod_log_values);
        if ($stat === true) {
        } elseif ($stat !== false)  {
            log_message('error', $stat);
        }
    }
    
    /**
     * Get the latest us update time
     * 
     * @return boolean
     */
    public function get_us_last_update() 
    {
        $files = @scandir(WRITEABLEPATH . 'updates/');
        if (!is_array($files) || count($files) === 0) {
            return false;
        }

        $files = array_filter($files, function($file) {
            return preg_match('/^saved_\d{10}.zip$/', $file, $matches);
        });

        if (!is_array($files) || count($files) === 0) {
            return false;
        }

        rsort($files);
        $datetime = new UsDateTime();
        $datetime->setTimestamp(substr($files[0],6, 10));
        return $datetime->mysql();
    }
    
    public function get_mysql_version() 
    {
        $CI = CI_Controller::get_instance();
        
        try {
            $result = $CI->db->query('SELECT @@version AS version');
            $sql_reply_info = $result->row();
            return $sql_reply_info->version;
        } catch (Exception $exc) {
            return null;
        }
    }
    
    public function get_mysql_sql_mode() 
    {
        $CI = CI_Controller::get_instance();
        
        try {
            $result = $CI->db->query('SELECT @@sql_mode AS sql_mode');
            $sql_reply_info = $result->row();
            return $sql_reply_info->sql_mode;
        } catch (Exception $exc) {
            return null;
        }
    }    
    
    /**
     * Create the body of the support email button
     * 
     * @return  string
     */
    public function create_supportmail_to()
    {
        return 'support@untermstrich.com';
    }
    
    /**
     * Create the body of the support email button
     * 
     * @return  string
     */
    public function create_supportmail_body()
    {
        $CI = CI_Controller::get_instance();

        $data = new stdClass();
        $data->us_version = $this->_get_system_modifications_log_value('us_version');
        $data->last_update = $this->_get_system_modifications_log_value('us_last_update');
        $data->us_serial = $this->_get_system_modifications_log_value('us_serial');
        $data->server_name = $this->_get_system_modifications_log_value('apache_on_host');
        $data->os_php = $this->_get_system_modifications_log_value('apache_os');
        $data->apache_user = $this->_get_system_modifications_log_value('apache_user');
        $data->version_apache = $this->_get_system_modifications_log_value('apache_version');
        $data->version_php = $this->_get_system_modifications_log_value('php_version');
        $data->version_mysql = $this->_get_system_modifications_log_value('mysql_version');
        $data->java_path =  $this->_get_system_modifications_log_value('java_path');
        $data->java_ok =  $this->_get_system_modifications_log_value('java_executable');
        $data->version_java =  $this->_get_system_modifications_log_value('java_version');
        $data->datapath = $this->_get_system_modifications_log_value('us_datapath');
        $data->datapath_ok = $this->_get_system_modifications_log_value('us_datapath_writeable');
        $data->enough_diskspace = $this->_get_system_modifications_log_value('enough_diskspace');
        
        $ret = "WICHTIGE Systeminfos\n";
        $ret.= $data->us_version." (".$data->last_update.")\n";
        $ret.= $data->us_serial."\n";

        if ($CI->config->item('us_rights_mode') >= 2) {
            $ret .= "SaaS (v".$CI->config->item('us_rights_mode').')';
            return rawurlencode(htmlspecialchars_decode($ret));
        }

        $ret.= "ON ".$data->server_name."\n";
        $ret.= substr($data->version_apache, 0, 25)."(".$data->apache_user.")"."\n";
        $ret.= "OS ".$data->os_php."\n";
        $ret.= "PHP ".substr($data->version_php, 0, 25)."\n";
        $ret.= "MySQL ".substr($data->version_mysql,0, 25)."\n";
        if ($data->datapath_ok) {
            $ret.= "DATAP OK\n";
        } else {
            $ret.= "DATAP(".$data->datapath.") FAIL\n";
        }
        $ret.= "Diskspace: ".(($data->enough_diskspace) ? 'OK' : 'FAIL')."\n";
        if ($data->java_ok) {
            $ret.= "JAVA(".$data->version_java.") OK\n";
        } else {
            $ret.= "JAVA(".$data->version_java.") FAIL: ".$data->java_path."\n";
        }
        
        return rawurlencode(htmlspecialchars_decode($ret));
        
    }
    
    /**
     * Get apache info
     *
     * @param   string  $server_software    Server software string
     * @return  void
     */
    private function _set_apache_version($server_software)
    {
        if( strpos($server_software, 'Win32') !== false ) {
            $this->is_windows = true;
        }
        
        $serverinfos = explode(' ', $server_software, 15);
        foreach ( $serverinfos as $serverinfo ) {
            if( strpos($serverinfo, '/') !== false ) {
                $serverinfoparts = explode('/', $serverinfo, 15);
                if( $serverinfoparts[0]==='Apache' && isset($serverinfoparts[1]) ) {
                    $version = substr(trim($serverinfoparts[1]), 0, 1);
                    if (is_numeric($version)) {
                        $this->version_apache = $version;
                    }
                }
            }
        }
    }

    /**
     * Shall we use HTML
     *
     * @param   boolean $to Activate HTML
     * @return  void
     */
    public function set_use_html($to)
    {
        $this->use_html = $to;
    }

    /**
     * Runs a test pre installation
     *
     * @return  mixed   Returns true on success, else an error message
     */
    public function test_pre_install()
    {
        $this->set_use_html(false);
        $msg = $this->create_version_to_do();
        $msg .= $this->create_apache_to_do();
        $msg .= $this->create_php_to_do();
        $msg .= $this->create_mysql_to_do();

        if ($this->all_ok) {
            return true;
        } else {
            return $msg;
        }
    }
    
    /**
     * Create the windows inof
     *
     * @return  string
     */
    public function windows_info()
    {
        $this->reply = '';
        
        try {
            $this->return_p('Server: '.php_uname('s').' '.php_uname('r').' '.php_uname('m').' on '.' '.php_uname('n'));
        } catch (Exception $exc) {
            $this->return_p('Server: '.PHP_OS);
            $this->return_note($exc->getMessage());
        }
        try {
            $this->return_p('PHP '.PHP_VERSION.' as '.php_sapi_name().' run by '.get_current_user());
        } catch (Exception $exc) {
            $this->return_note($exc->getMessage());
        }

        
        if (UTF8_ENABLED) {
            $utf8_mode = 'Full UTF-8 support';
        } else {
            $utf8_mode = 'Limited UTF-8 support';
        }
        
        if ( !( preg_match('/./u', 'é') === 1 ) ) {
            $this->return_note('PCRE must support UTF-8');
        }
        if ( !( function_exists('iconv') ) ) {
            $this->return_note('iconv must be installed');
        }
        if ( !( ini_get('mbstring.func_overload') != 1 ) ) {
            $this->return_note('Multibyte string function overloading cannot be enabled');
        }
        
        return $this->reply;
    }
    
    /**
     * Create the java to do
     *
     * @param   string  $us_java_path   The us_java_path
     * @param   boolean $view_non_error Optional View non error messages
     * @return  string  message
     */
    public function create_java_do($us_java_path=false, $view_non_error=true)
    {
        $CI = CI_Controller::get_instance();
        if ($this->_sysmod_log_values === null) {
            $CI->load->us_library('value_objects/system_modifications_log_values');
            $this->_sysmod_log_values = System_modifications_log_values::init();
        }

        $this->reply = '';
        
        if ($us_java_path===false) {
            $us_java_path = $this->_get_system_modifications_log_value('java_path');
        } else {
            $this->_sysmod_log_values->set_java_path($us_java_path);
        }
        
        if ($view_non_error) {
            $this->return_p('Java: <kbd style="border:1px dashed #DDDDDD;">'.$us_java_path.'</kbd>');
        }
        
        $what_does_java = 'create or open any XLSX, PDF, PNG or ZIP files';
        
        $java_version = 0;
        
        $java_executable = $this->_get_system_modifications_log_value('java_executable');
        $exec_java = $this->_sysmod_log_values->get_java_executable_response();
        if (!$java_executable) {
            $this->return_c('Cannot call java. Please change the system config. ', true);
            $this->return_c('Error message: '.$exec_java);
            $this->return_note('   You will not be able to '.$what_does_java.' !');
            $this->all_ok = false;
        } else {
            $java_parts = explode(' ', $exec_java);
            if (count($java_parts)<3) {
                $this->return_c('Error calling java. Please change the system config. ', true);
                $this->return_c('Error message: '.$exec_java);
                $this->return_note('   Maybe you cannot '.$what_does_java.' !');
                $this->all_ok = false;
            } else {
                $java_version = $this->_get_system_modifications_log_value('java_version');
                $version_parts = explode('.', $java_version);
                if ($version_parts[0]<self::MIN_JAVA) {
                    $this->return_c('Invalid java version. Please update java to "'.self::MIN_JAVA.'" or newer. ', true);
                    $this->return_c('Error message: '.$exec_java);
                    $this->return_note('   Maybe you cannot '.$what_does_java.' !');
                    $this->all_ok = false;
                } elseif ($version_parts[0]>self::MAX_JAVA) {
                    $this->return_c('Invalid java version. Java '.(self::MAX_JAVA+1).' or newer are not tested. ', true);
                    $this->return_c('Error message: '.$exec_java);
                    $this->return_note('   Maybe you cannot '.$what_does_java.' !');
                } else {
                    $this->return_p('Version: <kbd style="border:1px dashed #DDDDDD;">'.$java_version.'</kbd>');
                }
            }
        }
        
        try {
            $CI = CI_Controller::get_instance();
            $now = new UsDateTime('now');
            
            if ($CI->login->is_logged_in()) {
                $CI->load->model('System_settings_model', 'system_settings', true);
                $CI->system_settings->set('u10_check_java_version', $java_version);
                $CI->system_settings->set('u10_check_java_version_date', $now->mysql());
            } else {
                $CI->load->model('System_settings_model_readonly', 'system_settings_readonly', true);
                $CI->system_settings_readonly->set('u10_check_java_version', $java_version);
                $CI->system_settings_readonly->set('u10_check_java_version_date', $now->mysql());
            }
            
        } catch (Exception $exc) {
            $this->return_c($exc->getTraceAsString(), true);
        }

        return $this->reply;
    }

    /**
     * Create the directory info
     *
     * @param   mixed   $config         Optional Config array or NONE
     * @param   boolean $view_non_error Optional View non error messages
     * @return  string  message
     */
    public function create_dir_do($config=false, $view_non_error=true)
    {
        $dirs_ok = true;
        $this->reply = '';
        if ($config) {
            $log_path = $config['log_path'];
            $cache_path = $config['cache_path'];
            $smarty_template_dir = $config['smarty_template_dir'];
            $smarty_compile_dir = $config['smarty_compile_dir'];
            $smarty_cache_dir = $config['smarty_cache_dir'];
            $us_tempdir = $config['us_tempdir'];
            $us_reportsconfig = $config['us_reportsconfig'];
            $us_datapath = $config['us_datapath'];
            $min_free_diskpace = 3;
        } else {
            $CI = CI_Controller::get_instance();
            $CI->load->helper('number');
            $CI->load->library('US_Files', '', 'files');

            $log_path = $CI->config->item('log_path');
            $cache_path = $CI->config->item('cache_path');
            $smarty_template_dir = $CI->config->item('smarty_template_dir');
            $smarty_compile_dir = $CI->config->item('smarty_compile_dir');
            $smarty_cache_dir = $CI->config->item('smarty_cache_dir');
            $us_tempdir = $CI->config->item('us_tempdir');
            $us_reportsconfig = $CI->config->item('us_reportsconfig');
            $us_datapath = $this->_get_system_modifications_log_value('us_datapath');
            $min_free_diskpace = intval($CI->config->item('min_free_diskpace'));
            
            if (!$CI->files->is_path_allowed($us_datapath)) {
                $this->return_c('The data path is <span style="color:#DD0000;">not allowed</span> by us_block_paths', true);
                $dirs_ok = false;
            }
        }
        if ($min_free_diskpace<0 || $min_free_diskpace>100) {
            $min_free_diskpace = 5;
        }
        
        if (strtoupper(substr(PHP_OS, 0, 3))!=='WIN') {
            if (preg_match('/^[a-zA-Z]:[\/\\\\].+/', $us_datapath)) {
                $this->return_c('Data path on '.PHP_OS.' cannot start with a <span style="color:#DD0000;">Windows drive letter</span>: '.$us_datapath, true);
                $dirs_ok = false;
            }
        }
        
        if ($view_non_error) {
            $this->return_p('<span style="color:#CCCC00; font-weight:bold;">Your directories:</span>');
            $this->return_p('<strong>Data path</strong>: <kbd style="border:1px dashed #DDDDDD;">'.$us_datapath.'</kbd>');
            $this->return_p('file write mode: <kbd style="border:1px dashed #DDDDDD;">'.decoct(FILE_WRITE_MODE).'</kbd>');
            $this->return_p('dir write mode: <kbd style="border:1px dashed #DDDDDD;">'.decoct(DIR_WRITE_MODE).'</kbd>');
        }
        
        $ok = $this->_check_for_read_write($log_path);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read_write($cache_path);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read($smarty_template_dir);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read_write($smarty_compile_dir);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read_write($smarty_cache_dir);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read_write($us_tempdir);
        if (!$ok) $dirs_ok = false;
        $ok = $this->_check_for_read($us_reportsconfig);
        if (!$ok) $dirs_ok = false;
        
        $disk_free_cache = @disk_free_space($cache_path);
        $disk_total_cache = @disk_total_space($cache_path);
        if ($disk_free_cache!==false && $disk_free_cache!==null && $disk_total_cache!==false && $disk_total_cache!==null) {
            $avail_cache = ($disk_free_cache/$disk_total_cache)*100;
            if ($config===false && $view_non_error) {
                $this->return_p('Cache path free space: <kbd style="border:1px dashed #DDDDDD;">'.byte_format($disk_free_cache).'</kbd>');
                $this->return_p('Cache path total space: <kbd style="border:1px dashed #DDDDDD;">'.byte_format($disk_total_cache).'</kbd>');
                $this->return_p('Cache path available: <kbd style="border:1px dashed #DDDDDD;">'.(intval($avail_cache*10)/10).'%</kbd>');
            }
            
            if ($min_free_diskpace>0 && $avail_cache<$min_free_diskpace) {
                $this->return_c('<span style="color:#DD0000;">Diskpace warning:</span> Only <kbd style="color:#EE0000;">'.(intval($avail_cache*10)/10).'%</kbd> of the drive space of '.$cache_path.' is available.');
                $this->return_c('Please make sure that <em>more disk storage space</em> is available as <em>soon</em> as possible!');
                $dirs_ok = false;
            }
        }
        
        if ($dirs_ok) {
            if ($view_non_error) {
                $this->return_p('<span style="color:#00FF00;">All paths seem to be set up correctly</span>');
            } else {
                $this->return_p('Ok');
            }
        } else {
            $this->all_ok = false;
        }
        
        return $this->reply;
    }

    /**
     * Create an info regarding read/write of a path
     *
     * @param   string  $path   The path to test
     * @return  string  message
     */
    public function create_dir_check_write($path)
    {
        $this->reply = '';
        if (!$this->_check_for_read_write($path)) {
            $this->all_ok = false;
            return $this->reply;
        } else {
            return '';
        }
    }

    /**
     * Create an info regarding read of a path
     *
     * @param   string  $path   The path to test
     * @return  string  message
     */
    public function create_dir_check_read($path)
    {
        $this->reply = '';
        if (!$this->_check_for_read($path)) {
            $this->all_ok = false;
            return $this->reply;
        } else {
            return '';
        }
    }

    /**
     * Test the path if it is readable
     *
     * @param   string  $path   The path to test
     * @return  boolean Readable?
     */
    private function _check_for_read($path)
    {
        $realpath = realpath($path);
        if (empty($realpath)) {
            $this->return_c('The path "'.$path.'" does not exist', true);
            return false;
        } elseif (!us_is_readable($realpath)) {
            $this->return_c('Cannot read path "'.$path.'"', true);
            return false;
        } else {
            return true;
        }
    }

    /**
     * Test the path if it is readable and writeable
     *
     * @param   string  $path   The path to test
     * @return  boolean Read and write?
     */
    private function _check_for_read_write($path)
    {
        $realpath = realpath($path);
        if (empty($realpath)) {
            $this->return_c('The path "'.$path.'" does not exist', true);
            return false;
        } elseif (!us_is_readable($realpath)) {
            $this->return_c('Cannot read (write) path "'.$path.'"', true);
            return false;
        } elseif (!is_really_writable($realpath)) {
            $this->return_c('Cannot write path "'.$path.'"', true);
            return false;
        } else {
            return true;
        }
    }

    /**
     * Test the path if it is readable and executable
     *
     * @param   string  $path   The path to test
     * @return  boolean Read and exec?
     */
    private function _check_for_read_exec($path)
    {
        $realpath = realpath($path);
        if (empty($realpath)) {
            $this->return_c('The path "'.$path.'" does not exist', true);
            return false;
        } elseif (!us_is_readable($realpath)) {
            $this->return_c('Cannot read (exec) path "'.$path.'"', true);
            return false;
        } elseif (!is_executable($realpath)) {
            $this->return_c('Cannot execute path "'.$path.'"', true);
            return false;
        } else {
            return true;
        }
    }

    /**
     * Test the version of the applications in use
     * 
     * @see US_Sysinfo::test_pre_install
     * @category Called pre install
     *
     * @return  string  message
     */
    public function create_version_to_do()
    {
        $this->reply = '';
        $version_ok = true;
        
        if ( !$this->cli_mode && $this->version_apache===false ) {
            $this->return_p('Your version of Apache is out of date. Version: '.php_sapi_name(), true);
            $this->return_note('Please use Apache 2 or newer.');
            $version_ok = false;
        }

        if( !$this->cli_mode && intval($this->version_apache)<2 ) {
            $this->return_p('Your version of Apache is out of date. Version: '.$this->version_apache, true);
            $this->return_note('Please use Apache 2 or newer.');
            $version_ok = false;
        }
        
        $php_version_3 = floatval(substr(phpversion(),0,3));
        $now = new DateTime();
        $now_year = $now->format('Y');
        $now_month = $now->format('m');
        
        if ( $php_version_3 < 8.1 ) {
            $version_ok = false;

            $this->return_c('Ihre PHP Version wird nicht mehr unterstützt. / Your PHP version is no longer supported. Version: '.phpversion(), true);
            $this->return_note('Aktualisieren Sie auf eine neuere Version. / Update to a newer version.');
            if (strtoupper(substr(PHP_OS, 0, 3))==='WIN') {
                $this->return_note('Die Anleitung zum Update für Ihre SystembetreuerIn: / The Update Guide for your System Administrator: <a href="https://webservices.untermstrich.com/h5/de:installation:apache_update">HTTP Server, PHP, ionCube Bundle Update</a>');
            } else {
                $this->return_note('Bitte kontaktieren Sie für weitere Fragen Ihre SystembetreuerIn. / Please contact your system administrator for further questions.');
            }
        }
        
        if ($version_ok) {
            $this->return_p('<span style="color:#00FF00;">No version problems found</span>');
        } else {
            $this->all_ok = false;
        }
        return $this->reply;
    }

    /**
     * Create the to do list for Apache
     * 
     * @see US_Sysinfo::test_pre_install
     * @category Called pre install
     *
     * @return  string  message
     */
    public function create_apache_to_do()
    {
        if ($this->cli_mode) {
            return '';
        }
        if ($this->fpm_mode) {
            return '';
        }

        $this->reply = '';
        $apache_ok = true;
        
        $have_mod_env = false;
        $have_mod_rewrite = false;
        $have_mod_expires = false;
        
        if (function_exists('apache_get_modules')) {
            $modules = apache_get_modules();
            $have_mod_env = (in_array('mod_end', $modules));
            $have_mod_rewrite = (in_array('mod_rewrite', $modules));
            $have_mod_expires = (in_array('mod_expires', $modules));
        }
        
        $have_mod_env = ($have_mod_env) ? true :  ( strtoupper(getenv('HTTP_MOD_ENV'))=='ON' );
        $have_mod_rewrite = ($have_mod_rewrite) ? true :  ( strtoupper(getenv('HTTP_MOD_REWRITE'))=='ON' );
        $have_mod_expires = ($have_mod_expires) ? true :  ( strtoupper(getenv('HTTP_MOD_EXPIRES'))=='ON' );
        
        $have_mod_rewrite = ($have_mod_rewrite) ? true :  ( strtoupper(getenv('REDIRECT_HTTP_MOD_REWRITE'))=='ON' );
        $have_mod_expires = ($have_mod_expires) ? true :  ( strtoupper(getenv('REDIRECT_HTTP_MOD_EXPIRES'))=='ON' );
        
        if ($have_mod_rewrite && $have_mod_expires) {
            $have_mod_env = true;
        }
        
        if (!$have_mod_env) {
            $this->return_c('LoadModule env_module modules/mod_env.so', true);
            $this->return_note('   Activate the env_module, Some Linux: <code style="display:inline;">a2enmod env_module</code>');
            $apache_ok = false;
        }
        if (!$have_mod_rewrite) {
            $this->return_c('LoadModule rewrite_module modules/mod_rewrite.so', true);
            $this->return_note('   Activate the rewrite_module, Ubuntu: <code style="display:inline;">a2enmod rewrite</code>');
            $apache_ok = false;
        }
        if (!$have_mod_expires) {
            $this->return_c('LoadModule expires_module modules/mod_expires.so', true);
            $this->return_note('   Activate the expires_module, Ubuntu: <code style="display:inline;">a2enmod expires</code>');
            $apache_ok = false;
        }

        if ($apache_ok) {
            $this->return_p('<span style="color:#00FF00;">Your Apache config seems alright</span>');
        } else {
            $this->all_ok = false;
        }
        return $this->reply;
    }

    /**
     * Create the to do list for PHP
     * 
     * @see US_Sysinfo::test_pre_install
     * @category Called pre install
     *
     * @return  string  message
     */
    public function create_php_to_do()
    {
        if ($this->cli_mode) {
            return '';
        }
        
        $this->reply = '';
        if ($this->is_windows) {
            $php_ending = 'dll';
        } else {
            $php_ending = 'so';
        }

        $php_ok = true;
        if(!defined('US_TENANTPATH')) { //Check ioncube in non Saas mode only
            if (!extension_loaded('ionCube Loader')) {
                $this->return_c('zend_extension="...ioncube_loader_....'.$php_ending.'"', true);
                $this->return_note('   Instructions: <a href="'.base_url().'loader-wizard.php" onclick="window.open(this.href); return false;">ionCube Loader Wizard</a>');
                $php_ok = false;
            }
            if (function_exists('ioncube_loader_version')) {
                $ion_version = @ioncube_loader_version();
            } else {
                $ion_version = '0.0';
            }
            if (floatval($ion_version)<8.0) {
                $this->return_c('ioncube Loader is older than 8.0. Installed:'.$ion_version, true);
                $this->return_note('   Instructions: <a href="https://webservices.untermstrich.com/h5/de:ioncube:start" onclick="window.open(this.href); return false;">ioncube Update</a>');
                $php_ok = false;
            }
        }
        if (!extension_loaded('xsl')) {
            $this->return_c('extension=php_xsl.'.$php_ending, true);
            $this->return_note('   Please activate PHP XSL. Ubuntu: <code style="display:inline;">apt-get install php-xml</code>');
            $php_ok = false;
        }
        if (!extension_loaded('mysqli')) {
            $this->return_c('extension=php_mysqli.'.$php_ending, true);
            $this->return_note('   Please activate PHP MySQLI. Ubuntu: <code style="display:inline;">apt-get install php-xml</code>');
            $php_ok = false;
        }
        if (!extension_loaded('mbstring')) {
            $this->return_c('extension=php_mbstring.'.$php_ending, true);
            $this->return_note('   Please activate PHP MBString. Ubuntu: <code style="display:inline;">apt-get install php-mbstring</code>');
            $php_ok = false;
        }
        if (function_exists('json_encode') === false) {
            $this->return_c('Missing: json_encode', true);
            $this->return_note('   Instructions: It seems like json encode is missing. This might happen with some faulty upgrades. Please try to install php-json or remove and install PHP again.');
            $php_ok = false;
        }
        $have_mod_zip_igore = ( strtoupper(getenv('PHP_IGNORE_ZIP_EXTENSION'))=='ON' );
        if (!extension_loaded('zip') && !$have_mod_zip_igore) {
            $this->return_c('Missing: zip', true);
            $this->return_note('   <a href="http://www.php.net/manual/en/zip.setup.php" onclick="window.open(this.href); return false;">Zip Installing</a>');
            $php_ok = false;
        }
        $exec_test = @shell_exec('echo "TEST"');
        if (stripos($exec_test, 'TEST')===false) {
            $this->return_c('Cannot shell_exec any commands. '.$exec_test);
            $this->return_note('   You will not be able to create any PDF or PNG file!');
        }
        
        if (!extension_loaded('openssl')) {
            $this->return_c('Missing: openssl');
            $this->return_note('   <a href="http://www.php.net/manual/en/openssl.setup.php" onclick="window.open(this.href); return false;">OpenSSL Installing</a>');
        }
        if (!extension_loaded('ldap')) {
            $this->return_c('Missing: ldap - You cannot publish addresses from untermStrich using LDAP (Lightweight Directory Access Protocol)');
            $this->return_note('   It is recommended to install PHP with ldap support - <a href="http://www.php.net/manual/en/ldap.setup.php" onclick="window.open(this.href); return false;">LDAP Installing</a>');
            $this->return_note('   Ubuntu: <code style="display:inline;">sudo apt-get install php5-ldap</code>');
        }
        if (!extension_loaded('tidy')) {
            $this->return_c('Missing: tidy - We cannot clean HTML code for you without tidy.');
            $this->return_c('You have to ensure on your own, that the HTML code entered is valid.');
            $this->return_note('   It is recommended to install PHP with tidy support - <a href="http://www.php.net/manual/en/tidy.setup.php" onclick="window.open(this.href); return false;">Tidy Installing</a>');
            $this->return_note('   Ubuntu: <code style="display:inline;">sudo apt-get install php5-tidy</code>');
        }
        if (!function_exists('finfo_open')) {
            if (!function_exists('mime_content_type')) {
                $this->return_c('Missing: Fileinfo & mime_content_type - Cannot validate mime on the server');
                $this->return_note('   Mime type validation will be done via browser only.');
            } else {
                $this->return_c('Missing: Fileinfo - Using mime_content_type instead');
                $this->return_note('   Using deprecated function mime_content_type.');
            }
        }
        if (ini_get('register_globals')) {
            $this->return_c('register_globals = Off', true);
            $php_ok = false;
        }
        if (ini_get('safe_mode')) {
            $this->return_c('safe_mode = Off', true);
            $php_ok = false;
        }
        if (ini_get('magic_quotes_gpc')) {
            $this->return_c('magic_quotes_gpc = Off', true);
            $php_ok = false;
        }
        if (ini_get('magic_quotes_runtime')) {
            $this->return_c('magic_quotes_runtime = Off', true);
            $php_ok = false;
        }
        if (ini_get('max_execution_time')<30) {
            $this->return_c('max_execution_time = 30', true);
            $php_ok = false;
        }
        $memory_limit = $this->unformat_byte(ini_get('memory_limit'));
        if ($memory_limit<128*1024*1024) {
            $this->return_c('memory_limit = 128M', true);
            $this->return_note('   Current setting: '.ini_get('memory_limit'));
            $php_ok = false;
        }
        if (!ini_get('file_uploads')) {
            $this->return_c('file_uploads = On', true);
            $php_ok = false;
        }
        $upload_max_filesize = $this->unformat_byte(ini_get('upload_max_filesize'));
        if ($upload_max_filesize<20*1024*1024) {
            $this->return_c('upload_max_filesize = 20M', true);
            $this->return_note('   Current setting: '.ini_get('upload_max_filesize'));
            $php_ok = false;
        }
        $post_max_size = $this->unformat_byte(ini_get('post_max_size'));
        if ($post_max_size<30*1024*1024) {
            $this->return_c('post_max_size = 30M', true);
            $this->return_note('   Current setting: '.ini_get('post_max_size'));
            $php_ok = false;
        }
        $max_input_time = ini_get('max_input_time');
        if ($max_input_time!=-1 && $max_input_time<60) { //-1 for FCGI
            $this->return_c('max_input_time = 60', true);
            $this->return_note('   Current setting: '.ini_get('max_input_time'));
            $php_ok = false;
        }

        if ($php_ok) {
            $this->return_p('<span style="color:#00FF00;">Your PHP config seems alright</span>');
        } else {
            $this->all_ok = false;
        }
        return $this->reply;
    }
    
    /**
     * Get max file upload size in bytes
     * 
     * @return  integer
     */
    public function max_file_upload_in_bytes()
    {
        $memory_limit = $this->unformat_byte(ini_get('memory_limit'));
        $upload_max_filesize = $this->unformat_byte(ini_get('upload_max_filesize'));
        $post_max_size = $this->unformat_byte(ini_get('post_max_size'));
        
        return min($memory_limit, $upload_max_filesize, $post_max_size);
    }
    
    /**
     * Test node.js - DISABLED
     *
     * @return  string  message
     */
    public function create_node_to_do()
    {
        return '';
    }

    /**
     * Byte string to integer
     *
     * Takes a byte string according to http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes and returns the bytes as integer
     *
     * @param   string  $string     The byte string
     * @return  integer
     */
    protected function unformat_byte($string)
    {
        $str_int = intval($string);
        $last = substr(trim($string), -1);
        switch ($last) {
            case 'k':
            case 'K':
                return $str_int*1024;
            case 'm':
            case 'M':
                return $str_int*1024*1024;
            case 'g':
            case 'G':
                return $str_int*1024*1024*1024;
            default:
                return $str_int;
        }
    }
    
    /**
     * Do mysql connect
     *
     * @param   string  $hostname   Host name
     * @param   string  $port       Server port
     * @param   string  $username   User name
     * @param   string  $password   Password
     * @return  mixed   Either an US_sql object or false on fail
     */
    public function create_mysql_connect_to_do($hostname, $port, $username, $password)
    {
        require_once APPPATHLIVE.'us_libraries/US_sql.php';

        $main_db = new US_sql();
        
        $ok = $main_db->mysql_connect(
                $hostname,
                $username,
                $password,
                $port
        );
        if (!$ok) {
            $this->all_ok = false;
            return false;
        }
        
        return $main_db;
    }

    /**
     * Test the mysql settings and the database
     * 
     * @see US_Sysinfo::test_pre_install
     * @category Called pre install
     *
     * @param   mixed   $db             Optional DB array or NONE
     * @param   boolean $web_active     Optional Should the web related tables exist?
     * @return  string  message
     */
    public function create_mysql_to_do($db=false, $web_active=true)
    {
        $get_info = 'SELECT @@sql_mode AS sql_mode, @@version AS version, @@basedir AS basedir, @@datadir AS datadir, CURRENT_TIMESTAMP AS time_stamp';
        $get_engines = 'SHOW ENGINES';

        $this->reply = '';
        $warn_check_config = false;
        if ($db) {
            global $config;
            
            $config_db = $db['default'];

            $main_db = $this->create_mysql_connect_to_do(
                    $config_db['hostname'],
                    $config_db['port'],
                    $config_db['username'],
                    $config_db['password']
            );
            if ($main_db===false) {
                return $this->return_c('Failed to connect to the server. Check "hostname", "username", "password"', true);
            }

            $db_selected = $main_db->select_db($config_db['database']);
            if (isset($config_db['existing']) && $config_db['existing']) {
                if (!$db_selected) {
                    $this->all_ok = false;
                    return $this->return_c('Failed to connect to database. Check "database"', true);
                }
            } else {
                if ($db_selected) {
                    $this->all_ok = false;
                    return $this->return_c('Database already exists. Please enter an available database name.', true);
                }
                
                $this->return_p('<span style="color:#00FF00;">The entered database details seem to be alright</span>');
                return $this->reply;
            }

            #//Removed to allow adding user without tables.
            #
            #$result = $main_db->query('SELECT * FROM installation');
            #//Installation fail?
            #if (!$result) {
            #    $this->all_ok = false;
            #    return $this->return_c('Failed to get installation table. <br />'.$this->create_howto_migrate(), true);
            #}

            $result = $main_db->query($get_info);
            if (!$result) {
                return $this->return_c('Failed to get SQL mode and version.', true);
            }
            $sql_reply_info = $main_db->fetch_object($result);
            if (!$sql_reply_info) {
                $this->all_ok = false;
                return $this->return_c('Failed to get SQL mode and version.', true);
            }

            $result = $main_db->query($get_engines);
            if (!$result) {
                return $this->return_c('Failed to get SQL engines.', true);
            }
            $sql_reply_engines = array();
            while ($row = $main_db->fetch_object($result)) {
                $sql_reply_engines[] = $row;
            }
            if (empty($sql_reply_engines)) {
                $this->all_ok = false;
                return $this->return_c('Failed to get SQL engines.', true);
            }
            $sql_active_engines = $this->_prepare_engines($sql_reply_engines);
            
            if (isset($config_db['check_language']) && !empty($config_db['check_language'])) {
                $check_language = $config_db['check_language'];
                $get_language_count = 'SELECT ';
                $get_language_count .= '(SELECT count(*) FROM langs_work_packages_main WHERE language=\''.$check_language.'\') AS cnt_wp, ';
                $get_language_count .= '(SELECT count(*) FROM langs_cost_centres WHERE language=\''.$check_language.'\') AS cnt_cs, ';
                $get_language_count .= '(SELECT count(*) FROM langs_travels_types WHERE language=\''.$check_language.'\') AS cnt_tt';
                $result_language = $main_db->query($get_language_count);
                if (!$result_language) {
                    return $this->return_c('Failed to get language check.', true);
                }
                $language_count = $main_db->fetch_object($result_language);
                if (!$language_count) {
                    $this->all_ok = false;
                    return $this->return_c('Failed to get language check.', true);
                }
                
                $msg_language1 = 'Language mismatch. Please select the same main language, you had used before.';
                $msg_language2 = 'You cannot use '.$check_language.' since we found ';
                if ($language_count->cnt_wp>0) {
                    $this->all_ok = false;
                    return $this->return_c($msg_language1.'<br>'.$msg_language2.$language_count->cnt_wp.' entries within langs_work_packages_main.', true);
                }
                if ($language_count->cnt_cs>0) {
                    $this->all_ok = false;
                    return $this->return_c($msg_language1.'<br>'.$msg_language2.$language_count->cnt_cs.' entries within langs_cost_centres.', true);
                }
                if ($language_count->cnt_tt>0) {
                    $this->all_ok = false;
                    return $this->return_c($msg_language1.'<br>'.$msg_language2.$language_count->cnt_tt.' entries within langs_travels_types.', true);
                }
            }

            $config_db = $db['temp'];
            
            $temp_db = $this->create_mysql_connect_to_do(
                    $config_db['hostname'],
                    $config_db['port'],
                    $config_db['username'],
                    $config_db['password']
            );
            if ($temp_db===false) {
                return $this->return_c('Failed to connect to the temporary DB server. Check "hostname", "username", "password"', true);
            }

            $db_selected = $temp_db->select_db($config_db['database']);
            if (!$db_selected) {
                $this->all_ok = false;
                return $this->return_c('Failed to connect to temporary DB database. Check "database"', true);
            }
            

            $result = $main_db->query('SELECT * FROM sys_installation');
            if ($web_active) {
                if (!$result) {
                    $this->all_ok = false;
                    return $this->return_c('Failed to get sys_installation view. untermStrich Web views setup missing.', true);
                }
            }

            $result = $main_db->query('SELECT * FROM u10_ci_sessions');
            if ($web_active) {
                if (!$result) {
                    $this->all_ok = false;
                    return $this->return_c('Failed to get u10_ci_sessions table. untermStrich Web table setup missing.', true);
                }
            }
            
            $test_ustrich = isset($config['test_ustrich']) ? $config['test_ustrich'] : false;
            
        } else {
            $CI = CI_Controller::get_instance();
            
            $result = $CI->db->query($get_info);
            $sql_reply_info = $result->row();
            if (!$sql_reply_info) {
                $this->all_ok = false;
                return $this->return_c('Failed to get SQL mode and version.', true);
            }

            $get_variables = "SHOW VARIABLES WHERE Variable_name IN('max_connections', 'max_heap_table_size', 'max_allowed_packet', 'table_open_cache', 'sort_buffer_size', 'innodb_buffer_pool_size', 'log_bin', 'log_bin_trust_function_creators')";
            $result = $CI->db->query($get_variables);
            $sql_reply_variables = $result->result_array();
            if (!$sql_reply_variables) {
                $this->all_ok = false;
                return $this->return_c('Failed to get SQL variables.', true);
            }

            $result = $CI->db->query($get_engines);
            $sql_reply_engines = $result->result_object();
            if (!$sql_reply_engines) {
                $this->all_ok = false;
                return $this->return_c('Failed to get engines.', true);
            }
            $sql_active_engines = $this->_prepare_engines($sql_reply_engines);

            $CI->load->library('US_TempDB', '', 'tempdb');
            $CI->load->helper('number');
            
            $this->return_p('<span style="color:#CCCC00; font-weight:bold;">Your database config:</span>');
            $this->return_p('Hostname: <kbd style="border:1px dashed #DDDDDD;">'.$CI->db->hostname.'</kbd> Port: <kbd style="border:1px dashed #DDDDDD;">'.$CI->db->port.'</kbd>');
            $this->return_p('<strong>Database</strong>: <kbd style="border:1px dashed #DDDDDD;">'.$CI->db->database.'</kbd>');
            $this->return_p('<strong>MySQL version</strong>: <kbd style="border:1px dashed #DDDDDD;">'.$sql_reply_info->version.'</kbd>');
            $this->return_p('Base dir: <kbd style="border:1px dashed #DDDDDD;">'.$sql_reply_info->basedir.'</kbd>');
            $this->return_p('Data dir: <kbd style="border:1px dashed #DDDDDD;">'.$sql_reply_info->datadir.'</kbd>');
            $this->return_p('SQL mode: <kbd style="border:1px dashed #DDDDDD;">'.$sql_reply_info->sql_mode.'</kbd>');
            $this->return_p('Timestamp: <kbd style="border:1px dashed #DDDDDD;">'.$sql_reply_info->time_stamp.'</kbd>');
            $this->return_p('ENGINES: <kbd style="border:1px dashed #DDDDDD;">'.implode(', ', $sql_active_engines).'</kbd>');
            $variables_info = '';
            $variable_prefix = '<kbd style="border:1px dashed #DDDDDD; display:inline-block; margin: 0 15px 0 15px;">';
            $variable_suffix = '</kbd></kbd>';
            $variable_value_prefix_warn = '<kbd style="color:#993300;">';
            $variable_value_prefix_bad = '<kbd style="color:#CC0000;">';
            $variable_log_bin = null; $variable_log_bin_trust_function_creators = null;
            foreach($sql_reply_variables as $sql_reply_variable) {
                if (!isset($sql_reply_variable['Variable_name']) && !isset($sql_reply_variable['Value'])) {
                    continue;
                }
                $variable_name = $sql_reply_variable['Variable_name'];
                $variable_name_title = str_replace('_', ' ', $variable_name);
                $variable_value = intval($sql_reply_variable['Value']);
                $variable_value_orig = $sql_reply_variable['Value'];
                $variable_value_prefix = '<kbd>';
                switch ($variable_name) {
                    case 'max_connections':
                        if ($variable_value<50) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.$variable_value.$variable_suffix;
                        break;
                    case 'max_heap_table_size':
                        if ($variable_value<60000000) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        } elseif ($variable_value<100000000) {
                            $variable_value_prefix = $variable_value_prefix_warn;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.byte_format($variable_value, 1).$variable_suffix;
                        break;
                    case 'max_allowed_packet':
                        if ($variable_value<500000) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        } elseif ($variable_value<5000000) {
                            $variable_value_prefix = $variable_value_prefix_warn;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.byte_format($variable_value, 1).$variable_suffix;
                        break;
                    case 'table_open_cache':
                        if ($variable_value<300) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.$variable_value.$variable_suffix;
                        break;
                    case 'sort_buffer_size':
                        if ($variable_value<1000000) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.byte_format($variable_value, 0).$variable_suffix;
                        break;
                    case 'query_cache_size':
                        if ($variable_value<5000000) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        } elseif ($variable_value<10000000) {
                            $variable_value_prefix = $variable_value_prefix_warn;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.byte_format($variable_value, 0).$variable_suffix;
                        break;
                    case 'innodb_buffer_pool_size':
                        if ($variable_value<100000000) {
                            $warn_check_config = true;
                            $variable_value_prefix = $variable_value_prefix_bad;
                        }
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.byte_format($variable_value, 0).$variable_suffix;
                        break;
                    case 'log_bin':
                        $variable_log_bin = ($variable_value_orig==='1' || $variable_value_orig===1 || $variable_value_orig==='ON') ? true : false;
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.$variable_value_orig.$variable_suffix;
                        break;
                    case 'log_bin_trust_function_creators':
                        $variable_log_bin_trust_function_creators = ($variable_value_orig==='1' || $variable_value_orig===1 || $variable_value_orig==='ON') ? true : false;
                        $variables_info .= $variable_prefix.$variable_name_title.': '.$variable_value_prefix.$variable_value_orig.$variable_suffix;
                        break;
                }
            }
            $this->return_p('VARIABLES: '.$variables_info);
            if ($variable_log_bin!==null && $variable_log_bin_trust_function_creators!==null) {
                if ($variable_log_bin && !$variable_log_bin_trust_function_creators) {
                    $this->all_ok = false;
                    return $this->return_c('Log bin is active without trust function creators set to on. Updates will fail!', true);
                }
            }
            
            $test_ustrich = $CI->config->item('test_ustrich');
        }
        
        $version_elems = explode('.', $sql_reply_info->version);
        if (count($version_elems)<3) {
            $this->all_ok = false;
            return $this->return_c('Failed to get SQL version.', true);
        }
        $version = (intval($version_elems[0])*10000)+(intval($version_elems[1])*100)+intval($version_elems[2]);
        
        if ($version<50711) {
            if ($version<50605) {
                $this->all_ok = false;
            }
            if ($version<50605) {
                return $this->return_c('Your MySQL version is out of date. untermStrich X4 requires MySQL 5.7.11 or newer.', true);
            } else {
                $this->return_c('Your MySQL version 5.6 is out of date but you can use it for untermStrich X4. We still recommend to update soon.', true);
            }
        }
        
        if (($version<100000 && $version > 80100) || ($version>100000 && $version > 101100)) {
            $this->all_ok = false;
            return $this->return_c('Your MySQL version is too new. untermStrich X4 requires MySQL versions up to 5.7 or 8.0.', true);
        }
        
        if ($version>=50706 && $version<50711) {
            $this->all_ok = false;
            return $this->return_c('Your MySQL version has a well known bug. Please update to MySQL 5.7.11 or newer.', true);
        }
        
        $sql_active_engines_str = strtolower(implode('|', $sql_active_engines));
        if (strpos($sql_active_engines_str, 'myisam')===false) {
            $this->all_ok = false;
            return $this->return_c('Your MySQL version does not support MyISAM. Supported engines of your server: '.implode(', ', $sql_active_engines), true);
        }
        if (strpos($sql_active_engines_str, 'innodb')===false) {
            $this->all_ok = false;
            return $this->return_c('Your MySQL version does not support InnoDB. Supported engines of your server: '.implode(', ', $sql_active_engines), true);
        }
        if (strpos($sql_active_engines_str, 'archive')===false) {
            $this->return_c('Your MySQL version does not support ARCHIVE. Supported engines of your server: '.implode(', ', $sql_active_engines), true);
            $this->return_note('   untermStrich will use MyISAM as a fallback');
        }
        if (strpos($sql_active_engines_str, 'memory')===false) {
            $this->all_ok = false;
            return $this->return_c('Your MySQL version does not support MEMORY. Supported engines of your server: '.implode(', ', $sql_active_engines), true);
        }
        
        $time_stamp = new UsDateTime($sql_reply_info->time_stamp, null, false);
        $now_stamp = new UsDateTime('now', null, false);
        $stamp_diff = $time_stamp->format('U')-$now_stamp->format('U');
        if (abs($stamp_diff)>(2*60)) {
            $this->all_ok = false;
            if (abs($stamp_diff)>(2*60*60)) {
                return $this->return_c('Your MySQL server time(zone) is different from your webserver time: '.$time_stamp->format('H:m').' '.$time_stamp->us_date().' vs. '.$now_stamp->format('H:m').' '.$now_stamp->us_date().'. This causes problems with the session, update times, etc. pp. Please config date_default_timezone within application/config.php and installer/config.php.', true);
            } else {
                return $this->return_c('Your MySQL server time(zone) is different from your webserver time: '.$time_stamp->format('H:m').' vs. '.$now_stamp->format('H:m').'. This causes problems with the session, update times, etc. pp. Please config date_default_timezone within application/config.php and installer/config.php.', true);
            }
        }
        
        if ($warn_check_config) {
            $this->return_note('   Your configuration is not optimised! <a href="https://webservices.untermstrich.com/h5/de:faq:mysql_optimieren" onclick="window.open(this.href); return false;">MySQL Geschwindigkeit optimieren</a>');
        } else {
            $this->return_p('<span style="color:#00FF00;">Your database config seems alright</span>');
        }
        return $this->reply;
    }
    
    /**
     * Prepare active engines
     * 
     * @param   array   $sql_reply_engines      Active engines from DB
     * @return  array
     */
    private function _prepare_engines($sql_reply_engines)
    {
        $reply = array();
        foreach ($sql_reply_engines as $sql_reply_engine) {
            if (!isset($sql_reply_engine->Support)) {
                return array('This is a fallback due to an error in SHOW ENGINES', 'InnoDB', 'MyISAM', 'ARCHIVE', 'MEMORY');
            }
            
            $support = $sql_reply_engine->Support;
            if ($support=='YES' || $support=='DEFAULT') {
                $reply[] = $sql_reply_engine->Engine;
            }
        }
        
        return $reply;
    }

    /**
     * Create the message in how to migrate untermStrich to MySQL
     *
     * @return string
     */
    public function create_howto_migrate()
    {
        $msg = 'Please migrate your installation to MySQL using <kbd>db_migration.exe</kbd>.<br />' ;
        $msg .= '<a href="https://webservices.untermstrich.com/h1/de:faq:mysql_migration" onclick="window.open(this.href); return false;">Migration auf MySQL</a>';
        $msg .= 'Only after migrating to MySQL and Test using untermStrich X.1 upgrade to X2.';
        return $msg;
    }

    /**
     * Print a simple text message
     *
     * @param   string  $text   Message
     * @param   boolean $indent Indent the text
     * @return  string
     */
    protected function return_p($text, $indent=false)
    {
        if ($this->use_html) {
            if ($indent) {
                $this->reply .= '<p style="margin-left:20px;">'.$text.'</p>';
            } else {
                $this->reply .= '<p>'.$text.'</p>';
            }
        } else {
            if ($indent) $text = '    '.$text;
            $this->reply .= $text."\n";
        }
        return $this->reply;
    }

    /**
     * Print a code block
     *
     * @param   string  $text   Code
     * @param   boolean $fatal  Optional Fatal erro message
     * @return  string
     */
    protected function return_c($text, $fatal=false)
    {
        if ($this->use_html) {
            if ($fatal) {
                $this->reply .= '<code class="errorsmall">'.$text.'</code>';
            } else {
                $this->reply .= '<code>'.$text.'</code>';
            }
        } else {
            if ($fatal) {
                $this->reply .= '!! FATAL ERROR !! '.$text."\n";
            } else {
                $this->reply .= $text."\n";
            }
        }
        return $this->reply;
    }

    /**
     * Print a note block
     *
     * @param   string  $text       Note
     * @param   string  $id         Optional ID for html
     * @param   string  $style      Optional CSS style for html
     * @return  string
     */
    protected function return_note($text, $id='', $style='')
    {
        if ($this->use_html) {
            $id = ($id !== '') ? "id='$id'" : '';
            $style = ($style !== '') ? "style='$style'" : '';
            $this->reply .= '<p '.$id.' '.$style.'><span class="warningsmall ui-corner-all">'.$text.'</span></p>';
        } else {
            $this->reply .= 'i: '.$text."\n";
        }
        return $this->reply;
    }

    /**
     * Print an array
     * 
     * @param   array   $array  The assoc array to print
     * @return  void
     */
    protected function print_array(array $array)
    {
        foreach ($array as $key=>$item) {
            if (is_bool($item)) {
                if ($item) $item = "-TRUE-\n"; else $item="-FALSE-\n";
            } else if (is_array($item) || is_object($item)) {
                $item = '<small>'.print_r($item, true).'</small>';
            } else {
                $item .= "\n";
            }
            echo us_utf8_clean('    '.str_pad($key, self::PADD_KEY, ' ').' => '. $item);
        }
    }

    /**
     * Print infos about PHP
     *
     * @param   boolean $in_CI      Are we using CodeIgniter at all
     * @param   boolean $force_view Optional Force view in CI
     * @return  void
     *
     * @global  array   $config
     * @global  array   $db
     */
    public function print_php_info($in_CI, $force_view=false)
    {
        #=====================================================================================
        #=====================================================================================
        #=====================================================================================

        if ($in_CI) {
                $CI = CI_Controller::get_instance();
                $config = $CI->config->config;
                $config_db = array();
                $config_db['username'] = $CI->db->username;
                $config_db['dbdriver'] = $CI->db->dbdriver;
                $config_db['_escape_char'] = $CI->db->_escape_char;
                $config_db['hostname'] = $CI->db->hostname;
                $config_db['database'] = $CI->db->database;
                $config_db['dbprefix'] = $CI->db->dbprefix;
                $config_db['char_set'] = $CI->db->char_set;
                $config_db['dbcollat'] = $CI->db->dbcollat;
                $config_db['autoinit'] = $CI->db->autoinit;
                $config_db['swap_pre'] = $CI->db->swap_pre;
                $config_db['port'] = $CI->db->port;
                $config_db['pconnect'] = $CI->db->pconnect;
                $config_db['db_debug'] = $CI->db->db_debug;
                $config_db['trans_enabled'] = $CI->db->trans_enabled;
                $config_db['cache_on'] = $CI->db->cache_on;
                $config_db['cachedir'] = $CI->db->cachedir;
                
                if (!$force_view && !$CI->login->has_right(Login_model::R_MASTERDATAMANAGEMENT, Login_model::L_MEMBEROFSTAFF)) {
                    return;
                }
                
                $have_spellcheck = $CI->load->external_portlet_exists('com_untermstrich_spell');

        } else {
                global $config, $db;
                $config_db = $db['default'];
                
                $have_spellcheck = false;
        }

?>
untermStrich: Version <?php echo $config['us_version']; ?>

You are using: <?php echo getenv('SERVER_SOFTWARE'); ?>

<strong>PHP version</strong>: <?php echo phpversion(); ?>

Zend engine version: <?php echo zend_version(); ?>

IonCube version: <?php 
        if (function_exists('ioncube_loader_version')) {
            echo @ioncube_loader_version();
        } else {
            echo "Unknown";;
        }
?>

On server: <?php echo getenv('SERVER_NAME'); ?>

IP: <?php echo getenv('REMOTE_ADDR'); ?>

Port: <?php echo getenv('SERVER_PORT'); ?>

Basepath: <?php echo BASEPATH; if(!defined('EXT')) echo '  *This value might differ from the real one*'; ?>

php.ini path: <?php echo $this->ini_file(); ?>

Browser: <?php echo trim($_SERVER['HTTP_USER_AGENT']); ?>

<?php if ($have_spellcheck): ?>
Spell checker: <?php 
    $have_spell = false;
    if (function_exists('enchant_dict_check')) {
        $have_spell = true;
        echo 'Enchant - Provider: ';
        try {
            $enchant_r = enchant_broker_init();
            $bprovides = enchant_broker_describe($enchant_r);
            enchant_broker_free($enchant_r);
            print_r($bprovides);
        } catch (Exception $exc) {
            echo $exc->getMessage();
        }
        echo "\n";
    }
    if (function_exists('pspell_check')) {
        $have_spell = true;
        echo 'Pspell';
    }
    if ($have_spell===false) {
        echo '<kbd style="color:#CC0000;">Missing</kbd>';
    }
?>
<?php endif; ?>


USTRICH CONFIG
~~~~~~~~~~~~~~
<?php
if (isset($config)):
    ksort($config);
    $this->print_array($config);
    echo "\n";
else:
    echo 'NONE'."\n\n";
endif;

echo "DATABASE:\n";
if (isset($config_db)):
    if (isset($config_db['password'])) $config_db['password'] = '*****'; else $config_db['password'] = '-';
    $this->print_array($config_db);
else:
    echo 'NONE'."\n";
endif;

if (isset($in_CI)):
    echo "\nINSTALLATION:\n";
    $installation = $CI->installation->get_all();
    if (isset($installation['instinfo'])) $installation['instinfo'] = '*****'; else $installation['instinfo'] = '-';
    $this->print_array($installation);
endif;
?>



APACHE SERVER
~~~~~~~~~~~~~
<?php
        $var = $_SERVER;

        if (isset($var['HTTP_COOKIE'])) $var['HTTP_COOKIE'] = '*****'; else $var['HTTP_COOKIE'] = '-';
        if (isset($var['SSL_SESSION_ID'])) $var['SSL_SESSION_ID'] = '*****'; else $var['SSL_SESSION_ID'] = '-';

        ksort($var);
        $this->print_array($var);
?>


APACHE MODULES
~~~~~~~~~~~~~~
<?php
    if (function_exists('apache_get_modules')) {
        $modules = apache_get_modules();
        asort($modules);
        $this->print_array($modules);
    } else {
        echo "\nMode: ".php_sapi_name()."\n";
    }
?>


PHP EXTENSIONS
~~~~~~~~~~~~~~
<?php
    $extensions = get_loaded_extensions();
    asort($extensions);
    $this->print_array($extensions);
?>



PHP CONFIG
~~~~~~~~~~
<?php
    if (substr(phpversion(),0,3)<5.3) {
        $php_conf = ini_get_all();
    } else {
        $php_conf = ini_get_all(null, false);
    }
    ksort($php_conf);
    
    if (isset($php_conf['mysql.default_password'])) $php_conf['mysql.default_password'] = '*****'; else $php_conf['mysql.default_password'] = '-';
    
    $this->print_array($php_conf);
?>

PHP ERROR
~~~~~~~~~
<?php
    echo 'Error level: '.error_reporting()."\n";
?>

<?php
        if (function_exists('getrusage')) {
?>
CURRENT RESOURCE USAGES
~~~~~~~~~~~~~~~~~~~~~~~
<?php $this->print_array(getrusage()); ?>
<?php
        }

        #=====================================================================================
        #=====================================================================================
        #=====================================================================================
    }

    /**
     * Returns if everything went ok
     *
     * @param   boolean     $reset      Optional Set to true for a reset
     * @return  boolean     OK?
     */
    public function was_all_ok($reset=false)
    {
        $reply = $this->all_ok;
        if ($reset) {
            $this->all_ok = true;
        }
        return $reply;
    }

    /**
     * Get path to PHP ini file
     *
     * @return  string
     */
    public function ini_file()
    {
        $path = function_exists('php_ini_loaded_file') ? php_ini_loaded_file() : '';
        return $path!='' ? $path : 'php.ini';
    }
    
} // END class US_Sysinfo
