Till Brehm
2014-03-04 ccbf1497dde4aef031a39544235a284641e694de
- Added templating library to installer.
- Added function to detect the apache version to installer.
- Added support for apache 2.4 to vhots templates for ispconfig vhost and apps vhost in installer.
4 files added
11 files modified
2184 ■■■■■ changed files
install/dist/lib/fedora.lib.php 36 ●●●●● patch | view | raw | blame | history
install/dist/lib/gentoo.lib.php 30 ●●●●● patch | view | raw | blame | history
install/dist/lib/opensuse.lib.php 39 ●●●● patch | view | raw | blame | history
install/install.php 3 ●●●●● patch | view | raw | blame | history
install/lib/classes/tpl.inc.php 1431 ●●●●● patch | view | raw | blame | history
install/lib/classes/tpl_cache.inc.php 193 ●●●●● patch | view | raw | blame | history
install/lib/classes/tpl_error.inc.php 95 ●●●●● patch | view | raw | blame | history
install/lib/classes/tpl_ini.inc.php 119 ●●●●● patch | view | raw | blame | history
install/lib/install.lib.php 25 ●●●●● patch | view | raw | blame | history
install/lib/installer_base.lib.php 57 ●●●● patch | view | raw | blame | history
install/tpl/apache_apps.vhost.master 46 ●●●●● patch | view | raw | blame | history
install/tpl/apache_ispconfig.conf.master 76 ●●●● patch | view | raw | blame | history
install/tpl/apache_ispconfig.vhost.master 30 ●●●● patch | view | raw | blame | history
install/update.php 3 ●●●●● patch | view | raw | blame | history
interface/lib/config.inc.php 1 ●●●● patch | view | raw | blame | history
install/dist/lib/fedora.lib.php
@@ -645,10 +645,12 @@
        $vhost_conf_dir = $conf['apache']['vhost_conf_dir'];
        $vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir'];
        // copy('tpl/apache_ispconfig.conf.master',$vhost_conf_dir.'/ispconfig.conf');
        $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.conf.master', 'tpl/apache_ispconfig.conf.master');
        $tpl = new tpl('apache_ispconfig.conf.master');
        $tpl->setVar('apache_version',getapacheversion());
        $records = $this->db->queryAllRecords('SELECT * FROM '.$conf['mysql']['master_database'].'.server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
        $ip_addresses = array();
        if(is_array($records) && count($records) > 0) {
            foreach($records as $rec) {
                if($rec['ip_type'] == 'IPv6') {
@@ -661,15 +663,15 @@
                    foreach($ports as $port) {
                        $port = intval($port);
                        if($port > 0 && $port < 65536 && $ip_address != '') {
                            $content .= 'NameVirtualHost '.$ip_address.":".$port."\n";
                            $ip_addresses[] = array('ip_address' => $ip_address, 'port' => $port);
                        }
                    }
                }
            }
        }
        $content .= "\n";
        wf($vhost_conf_dir.'/ispconfig.conf', $content);
        wf($vhost_conf_dir.'/ispconfig.conf', $tpl->grab());
        unset($tpl);
        if(!@is_link($vhost_conf_enabled_dir."/000-ispconfig.conf")) {
            exec("ln -s ".$vhost_conf_dir."/ispconfig.conf ".$vhost_conf_enabled_dir."/000-ispconfig.conf");
@@ -1033,28 +1035,30 @@
            // Dont just copy over the virtualhost template but add some custom settings
            $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.vhost.master', "tpl/apache_ispconfig.vhost.master");
            $content = str_replace('{vhost_port}', $conf['apache']['vhost_port'], $content);
            $tpl = new tpl('apache_ispconfig.vhost.master');
            $tpl->setVar('vhost_port',$conf['apache']['vhost_port']);
            // comment out the listen directive if port is 80 or 443
            if($conf['apache']['vhost_port'] == 80 or $conf['apache']['vhost_port'] == 443) {
                $content = str_replace('{vhost_port_listen}', '#', $content);
                $tpl->setVar('vhost_port_listen','#');
            } else {
                $content = str_replace('{vhost_port_listen}', '', $content);
                $tpl->setVar('vhost_port_listen','');
            }
            if(is_file('/usr/local/ispconfig/interface/ssl/ispserver.crt') && is_file('/usr/local/ispconfig/interface/ssl/ispserver.key')) {
                $content = str_replace('{ssl_comment}', '', $content);
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key')) {
                $tpl->setVar('ssl_comment','');
            } else {
                $content = str_replace('{ssl_comment}', '#', $content);
                $tpl->setVar('ssl_comment','#');
            }
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key') && is_file($install_dir.'/interface/ssl/ispserver.bundle')) {
                $content = str_replace('{ssl_bundle_comment}', '', $content);
                $tpl->setVar('ssl_bundle_comment','');
            } else {
                $content = str_replace('{ssl_bundle_comment}', '#', $content);
                $tpl->setVar('ssl_bundle_comment','#');
            }
            $tpl->setVar('apache_version',getapacheversion());
            wf("$vhost_conf_dir/ispconfig.vhost", $content);
            wf($vhost_conf_dir.'/ispconfig.vhost', $tpl->grab());
            //copy('tpl/apache_ispconfig.vhost.master', "$vhost_conf_dir/ispconfig.vhost");
            //* and create the symlink
install/dist/lib/gentoo.lib.php
@@ -495,6 +495,7 @@
        //* Copy the ISPConfig configuration include
        /*
        $content = $this->get_template_file('apache_ispconfig.conf', true);
        $records = $this->db->queryAllRecords("SELECT * FROM server_ip WHERE server_id = ".$conf["server_id"]." AND virtualhost = 'y'");
@@ -507,6 +508,35 @@
        }
        $this->write_config_file($conf['apache']['vhost_conf_dir'].'/000-ispconfig.conf', $content);
        */
        $tpl = new tpl('apache_ispconfig.conf.master');
        $tpl->setVar('apache_version',getapacheversion());
        $records = $this->db->queryAllRecords('SELECT * FROM '.$conf['mysql']['master_database'].'.server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
        $ip_addresses = array();
        if(is_array($records) && count($records) > 0) {
            foreach($records as $rec) {
                if($rec['ip_type'] == 'IPv6') {
                    $ip_address = '['.$rec['ip_address'].']';
                } else {
                    $ip_address = $rec['ip_address'];
                }
                $ports = explode(',', $rec['virtualhost_port']);
                if(is_array($ports)) {
                    foreach($ports as $port) {
                        $port = intval($port);
                        if($port > 0 && $port < 65536 && $ip_address != '') {
                            $ip_addresses[] = array('ip_address' => $ip_address, 'port' => $port);
                        }
                    }
                }
            }
        }
        wf($conf['apache']['vhost_conf_dir'].'/000-ispconfig.conf', $tpl->grab());
        unset($tpl);
        //* Gentoo by default does not include .vhost files. Add include line to config file.
        $content = rf($conf['apache']['config_file']);
install/dist/lib/opensuse.lib.php
@@ -660,10 +660,12 @@
        $vhost_conf_dir = $conf['apache']['vhost_conf_dir'];
        $vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir'];
        //copy('tpl/apache_ispconfig.conf.master',$vhost_conf_dir.'/ispconfig.conf');
        $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.conf.master', 'tpl/apache_ispconfig.conf.master');
        $tpl = new tpl('apache_ispconfig.conf.master');
        $tpl->setVar('apache_version',getapacheversion());
        $records = $this->db->queryAllRecords('SELECT * FROM '.$conf['mysql']['master_database'].'.server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
        $ip_addresses = array();
        if(is_array($records) && count($records) > 0) {
            foreach($records as $rec) {
                if($rec['ip_type'] == 'IPv6') {
@@ -676,15 +678,15 @@
                    foreach($ports as $port) {
                        $port = intval($port);
                        if($port > 0 && $port < 65536 && $ip_address != '') {
                            $content .= 'NameVirtualHost '.$ip_address.":".$port."\n";
                            $ip_addresses[] = array('ip_address' => $ip_address, 'port' => $port);
                        }
                    }
                }
            }
        }
        $content .= "\n";
        wf($vhost_conf_dir.'/ispconfig.conf', $content);
        wf($vhost_conf_dir.'/ispconfig.conf', $tpl->grab());
        unset($tpl);
        if(!@is_link($vhost_conf_enabled_dir."/000-ispconfig.conf")) {
            exec("ln -s ".$vhost_conf_dir."/ispconfig.conf ".$vhost_conf_enabled_dir."/000-ispconfig.conf");
@@ -1089,31 +1091,30 @@
            // Dont just copy over the virtualhost template but add some custom settings
            $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.vhost.master', "tpl/apache_ispconfig.vhost.master");
            $content = str_replace('{vhost_port}', $conf['apache']['vhost_port'], $content);
            $tpl = new tpl('apache_ispconfig.vhost.master');
            $tpl->setVar('vhost_port',$conf['apache']['vhost_port']);
            // comment out the listen directive if port is 80 or 443
            if($conf['apache']['vhost_port'] == 80 or $conf['apache']['vhost_port'] == 443) {
                $content = str_replace('{vhost_port_listen}', '#', $content);
                $tpl->setVar('vhost_port_listen','#');
            } else {
                $content = str_replace('{vhost_port_listen}', '', $content);
                $tpl->setVar('vhost_port_listen','');
            }
            if(is_file('/usr/local/ispconfig/interface/ssl/ispserver.crt') && is_file('/usr/local/ispconfig/interface/ssl/ispserver.key')) {
                $content = str_replace('{ssl_comment}', '', $content);
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key')) {
                $tpl->setVar('ssl_comment','');
            } else {
                $content = str_replace('{ssl_comment}', '#', $content);
                $tpl->setVar('ssl_comment','#');
            }
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key') && is_file($install_dir.'/interface/ssl/ispserver.bundle')) {
                $content = str_replace('{ssl_bundle_comment}', '', $content);
                $tpl->setVar('ssl_bundle_comment','');
            } else {
                $content = str_replace('{ssl_bundle_comment}', '#', $content);
                $tpl->setVar('ssl_bundle_comment','#');
            }
            $tpl->setVar('apache_version',getapacheversion());
            $content = str_replace('/var/www/', '/srv/www/', $content);
            wf("$vhost_conf_dir/ispconfig.vhost", $content);
            wf($vhost_conf_dir.'/ispconfig.vhost', $tpl->grab());
            //if(!is_file('/srv/www/php-fcgi-scripts/ispconfig/.php-fcgi-starter')) {
            $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig_fcgi_starter.master', 'tpl/apache_ispconfig_fcgi_starter.master');
install/install.php
@@ -65,6 +65,9 @@
define('ISPC_LOG_FILE', '/var/log/ispconfig_install.log');
define('ISPC_INSTALL_ROOT', realpath(dirname(__FILE__).'/../'));
//** Include the templating lib
require_once 'lib/classes/tpl.inc.php';
//** Check for existing installation
/*if(is_dir("/usr/local/ispconfig")) {
    die('We will stop here. There is already a ISPConfig installation, use the update script to update this installation.');
install/lib/classes/tpl.inc.php
New file
@@ -0,0 +1,1431 @@
<?php
/**
 * vlibTemplate is a class used to seperate PHP and HTML.
 * For instructions on how to use vlibTemplate, see the
 * vlibTemplate.html file, located in the 'docs' directory.
 *
 * @since 07/03/2002
 * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
 * @package vLIB
 * @access public
 * @see vlibTemplate.html
 */
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0                                                      |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002 Active Fish Group                                 |
// +----------------------------------------------------------------------+
// | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk>                     |
// +----------------------------------------------------------------------+
//
// $Id: class.tpl.inc.php,v 1.1 2003/07/08 12:31:10 platinum Exp $
//** check and avoid multiple loading of class
if (!defined('vlibTemplateClassLoaded')) {
    define('vlibTemplateClassLoaded', 1);
    include_once ISPC_INSTALL_ROOT.'/install/lib/classes/tpl_error.inc.php';
    include_once ISPC_INSTALL_ROOT.'/install/lib/classes/tpl_ini.inc.php';
    class tpl{
        /*-----------------------------------------------------------------------------\
        |                                 ATTENTION                                    |
        |  Do not touch the following variables. vlibTemplate will not work otherwise. |
        \-----------------------------------------------------------------------------*/
        private $OPTIONS = array(
            'MAX_INCLUDES'          =>   10,
            'TEMPLATE_DIR'          => null,
            'GLOBAL_VARS'           => null,
            'GLOBAL_CONTEXT_VARS'   => null,
            'LOOP_CONTEXT_VARS'     => null,
            'SET_LOOP_VAR'          => null,
            'DEFAULT_ESCAPE'        => null,
            'STRICT'                => null,
            'CASELESS'              => null,
            'UNKNOWNS'              => null,
            'TIME_PARSE'            => null,
            'ENABLE_PHPINCLUDE'     => null,
            'INCLUDE_PATHS'         => array(),
            'CACHE_DIRECTORY'       => null,
            'CACHE_LIFETIME'        => null,
            'CACHE_EXTENSION'       => null
        );
        /** open and close tags used for escaping */
        private $ESCAPE_TAGS = array(
            'html'      => array('open' => 'htmlspecialchars('    , 'close'=> ', ENT_QUOTES)'),
            'url'       => array('open' => 'urlencode('           , 'close'=> ')'),
            'rawurl'    => array('open' => 'rawurlencode('        , 'close'=> ')'),
            'sq'        => array('open' => 'addcslashes('         , 'close'=> ", \"'\")"),
            'dq'        => array('open' => 'addcslashes('         , 'close'=> ", '\"')"),
            '1'         => array('open' => 'htmlspecialchars('    , 'close'=> ', ENT_QUOTES)'),
            '0'         => array('open' => ''                     , 'close'=> ''),
            'none'      => array('open' => ''                     , 'close'=> ''),
            'hex'       => array('open' => '$this->_escape_hex('  , 'close'=> ', false)'),
            'hexentity' => array('open' => '$this->_escape_hex('  , 'close'=> ', true)')
        );
        /** open and close tags used for formatting */
        private $FORMAT_TAGS = array(
            'strtoupper' => array('open' => 'strtoupper(',          'close'=> ')'),
            'uc'         => array('open' => 'strtoupper(',          'close'=> ')'),
            'strtolower' => array('open' => 'strtolower(',          'close'=> ')'),
            'lc'         => array('open' => 'strtolower(',          'close'=> ')'),
            'ucfirst'    => array('open' => 'ucfirst(',             'close'=> ')'),
            'lcucfirst'  => array('open' => 'ucfirst(strtolower(',  'close'=> '))'),
            'ucwords'    => array('open' => 'ucwords(',             'close'=> ')'),
            'lcucwords'  => array('open' => 'ucwords(strtolower(',  'close'=> '))')
        );
        /** operators allowed when using extended TMPL_IF syntax */
        private $allowed_if_ops = array('==', '!=', '<>', '<', '>', '<=', '>=');
        /** dbs allowed by vlibTemplate::setDbLoop(). */
        private $allowed_loop_dbs = array('MYSQL', 'POSTGRESQL', 'INFORMIX', 'INTERBASE', 'INGRES',
            'MSSQL', 'MSQL', 'OCI8', 'ORACLE', 'OVRIMOS', 'SYBASE');
        /** root directory of vlibTemplate automagically filled in */
        private $VLIBTEMPLATE_ROOT = null;
        /** contains current directory used when doing recursive include */
        private $_currentincludedir = array();
        /** current depth of includes */
        private $_includedepth = 0;
        /** full path to tmpl file */
        private $_tmplfilename = null;
        /** file data before it's parsed */
        private $_tmplfile = null;
        /** parsed version of file, ready for eval()ing */
        private $_tmplfilep = null;
        /** eval()ed version ready for printing or whatever */
        private $_tmploutput = null;
        /** array for variables to be kept */
        private $_vars = array();
        /** array where loop variables are kept */
        private $_arrvars = array();
        /** array which holds the current namespace during parse */
        private $_namespace = array();
        /** variable is set to true once the template is parsed, to save re-parsing everything */
        private $_parsed = false;
        /** array holds all unknowns vars */
        private $_unknowns = array();
        /** microtime when template parsing began */
        private $_firstparsetime = null;
        /** total time taken to parse template */
        private $_totalparsetime = null;
        /** name of current loop being passed in */
        private $_currloopname = null;
        /** rows with the above loop */
        private $_currloop = array();
        /** define vars to avoid warnings */
        private $_debug = null;
        private $_cache = null;
        /** array which holds the dynamic Includes */
        private $_dyninclude = array();
        /*-----------------------------------------------------------------------------\
        |                           public functions                                   |
        \-----------------------------------------------------------------------------*/
        /**
         * Usually called by the class constructor.
         * Stores the filename in $this->_tmplfilename.
         * Raises an error if the template file is not found.
         * @param string $tmplfile full path to template file
         * @return boolean true
         * @access public
         */
        public function newTemplate($tmplfile)
        {
            if (!$tfile = $this->_fileSearch($tmplfile)){
                vlibTemplateError::raiseError('VT_ERROR_NOFILE', KILL, $tmplfile);
            }
            //* make sure that any parsing vars are cleared for the new template
            $this->_tmplfile = null;
            $this->_tmplfilep = null;
            $this->_tmploutput = null;
            $this->_parsed = false;
            $this->_unknowns = array();
            $this->_firstparsetime = null;
            $this->_totalparsetime = null;
            //* reset debug module
            if ($this->_debug){
                $this->_debugReset();
            }
            $this->_tmplfilename = $tfile;
            return true;
        }
        /**
         * Sets variables to be used by the template
         * If $k is an array, then it will treat it as an associative array
         * using the keys as variable names and the values as variable values.
         * @param mixed $k key to define variable name
         * @param mixed $v variable to assign to $k
         * @return boolean true/false
         * @access public
         */
        public function setVar($k, $v = null)
        {
            if (is_array($k)) {
                foreach($k as $key => $value){
                    $key = ($this->OPTIONS['CASELESS']) ? strtolower(trim($key)) : trim($key);
                    if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $key) && $value !== null ) {
                        $this->_vars[$key] = $value;
                    }
                }
            } else {
                if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k) && $v !== null) {
                    if ($this->OPTIONS['CASELESS']) $k = strtolower($k);
                    $this->_vars[trim($k)] = $v;
                } else {
                    return false;
                }
            }
            return true;
        }
        /**
         * Sets dynamic includes to be used by the template
         * If $k is an array, then it will treat it as an associative array
         * using the keys as variable names and the values as variable values.
         * @param mixed $k key to define variable name
         * @param mixed $v variable to assign to $k
         * @return boolean true/false
         * @access public
         */
        public function setInclude($k, $v = null)
        {
            if(is_array($k)) {
                foreach($k as $key => $val) {
                    $this->_dyninclude[$key] = $val;
                }
            } else {
                $this->_dyninclude[$k] = $v;
            }
            return true;
        }
        /**
         * Unsets a variable which has already been set
         * Parse in all vars wanted for deletion in seperate parametres
         * @param string var name to remove use: vlibTemplate::unsetVar(var[, var..])
         * @return boolean true/false returns true unless called with 0 params
         * @access public
         */
        public function unsetVar()
        {
            $num_args = func_num_args();
            if ($num_args < 1)  return false;
            for ($i = 0; $i < $num_args; $i++) {
                $var = func_get_arg($i);
                if ($this->OPTIONS['CASELESS']) $var = strtolower($var);
                if (!preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $var)) continue;
                unset($this->_vars[$var]);
            }
            return true;
        }
        /**
         * Gets all vars currently set in global namespace.
         * @return array
         * @access public
         */
        public function getVars()
        {
            return empty($this->_vars) ? false : $this->_vars;
        }
        /**
         * Gets a single var from the global namespace
         * @return var
         * @access public
         */
        public function getVar($var)
        {
            if ($this->OPTIONS['CASELESS']) $var = strtolower($var);
            return (empty($var) || !isset($this->_vars[$var])) ? false : $this->_vars[$var];
        }
        /**
         * sets the GLOBAL_CONTEXT_VARS
         * @return true
         * @access public
         */
        public function setContextVars()
        {
            $_phpself = @$GLOBALS['HTTP_SERVER_VARS']['PHP_SELF'];
            $_pathinfo = @$GLOBALS['HTTP_SERVER_VARS']['PATH_INFO'];
            $_request_uri = @$GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI'];
            $_qs   = @$GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
            //* the following fixes bug of $PHP_SELF on Win32 CGI and IIS.
            $_self = (!empty($_pathinfo)) ? $_pathinfo : $_phpself;
            $_uri  = (!empty($_request_uri)) ? $_request_uri : $_self.'?'.$_qs;
            $this->setvar('__SELF__', $_self);
            $this->setvar('__REQUEST_URI__', $_uri);
            return true;
        }
        /**
         * Builds the loop construct for use with <TMPL_LOOP>.
         * @param string $k string to define loop name
         * @param array $v array to assign to $k
         * @return boolean true/false
         * @access public
         */
        public function setLoop($k, $v)
        {
            if (is_array($v) && preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k)) {
                $k = ($this->OPTIONS['CASELESS']) ? strtolower(trim($k)) : trim($k);
                $this->_arrvars[$k] = array();
                if ($this->OPTIONS['SET_LOOP_VAR'] && !empty($v)) $this->setvar($k, 1);
                if (($this->_arrvars[$k] = $this->_arrayBuild($v)) == false) {
                    vlibTemplateError::raiseError('VT_WARNING_INVALID_ARR', WARNING, $k);
                } else {
                    $this->vars['_'.$k.'_num'] = count($v);
                }
            }
            return true;
        }
        /**
         * [** EXPERIMENTAL **]
         * Function to create a loop from a Db result resource link.
         * @param string $loopname to commit loop. If not set, will use last loopname set using newLoop()
         * @param string $result link to a Db result resource
         * @param string $db_type, type of db that the result resource belongs to.
         * @return boolean true/false
         * @access public
         */
        public function setDbLoop($loopname, $result, $db_type = 'MYSQL')
        {
            /*
            $db_type = strtoupper($db_type);
            if (!in_array($db_type, $this->allowed_loop_dbs)) {
                vlibTemplateError::raiseError('VT_WARNING_INVALID_LOOP_DB', WARNING, $db_type);
                return false;
            }
            $loop_arr = array();
            // TODO: Are all these necessary as were onyl using mysql and possible postgres ? - pedro
            switch ($db_type) {
                case 'MYSQL':
                    if (get_resource_type($result) != 'mysql result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = mysql_fetch_assoc($result)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'POSTGRESQL':
                    if (get_resource_type($result) != 'pgsql result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    $nr = (function_exists('pg_num_rows')) ? pg_num_rows($result) : pg_numrows($result);
                    for ($i=0; $i < $nr; $i++) {
                        $loop_arr[] = pg_fetch_array($result, $i, PGSQL_ASSOC);
                    }
                    break;
                case 'INFORMIX':
                    if (!$result) {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = ifx_fetch_row($result, 'NEXT')) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'INTERBASE':
                    if (get_resource_type($result) != 'interbase result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = ibase_fetch_row($result)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'INGRES':
                    if (!$result) {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = ingres_fetch_array(INGRES_ASSOC, $result)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'MSSQL':
                    if (get_resource_type($result) != 'mssql result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = mssql_fetch_array($result)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'MSQL':
                    if (get_resource_type($result) != 'msql result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = msql_fetch_array($result, MSQL_ASSOC)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'OCI8':
                    if (get_resource_type($result) != 'oci8 statement') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while(OCIFetchInto($result, &$r, OCI_ASSOC+OCI_RETURN_LOBS)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'ORACLE':
                    if (get_resource_type($result) != 'oracle Cursor') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while(ora_fetch_into($result, &$r, ORA_FETCHINTO_ASSOC)) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'OVRIMOS':
                    if (!$result) {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while(ovrimos_fetch_into($result, &$r, 'NEXT')) {
                        $loop_arr[] = $r;
                    }
                    break;
                case 'SYBASE':
                    if (get_resource_type($result) != 'sybase-db result') {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_RESOURCE', WARNING, $db_type);
                        return false;
                    }
                    while($r = sybase_fetch_array($result)) {
                        $loop_arr[] = $r;
                    }
                    break;
            }
            $this->setLoop($loopname, $loop_arr);
            return true;
            */
        }
        /**
         * Sets the name for the curent loop in the 3 step loop process.
         * @param string $name string to define loop name
         * @return boolean true/false
         * @access public
         */
        public function newLoop($loopname)
        {
            if (preg_match('/^[a-z_]+[a-z0-9_]*$/i', $loopname)) {
                $this->_currloopname[$loopname] = $loopname;
                $this->_currloop[$loopname] = array();
                return true;
            } else {
                return false;
            }
        }
        /**
         * Adds a row to the current loop in the 3 step loop process.
         * @param array $row loop row to add to current loop
         * @param string $loopname loop to which you want to add row, if not set will use last loop set using newLoop().
         * @return boolean true/false
         * @access public
         */
        public function addRow($row, $loopname = null)
        {
            if (!$loopname) $loopname = $this->_currloopname[(count($this->_currloopname)-1)];
            if (!isset($this->_currloop[$loopname]) || empty($this->_currloopname)) {
                vlibTemplateError::raiseError('VT_WARNING_LOOP_NOT_SET', WARNING);
                return false;
            }
            if (is_array($row)) {
                $this->_currloop[$loopname][] = $row;
                return true;
            } else {
                return false;
            }
        }
        /**
         * Completes the 3 step loop process. This assigns the rows and resets
         * the variables used.
         * @param string $loopname to commit loop. If not set, will use last loopname set using newLoop()
         * @return boolean true/false
         * @access public
         */
        public function addLoop($loopname = null)
        {
            if ($loopname == null) { // add last loop used
                if (!empty($this->_currloop)) {
                    foreach ($this->_currloop as $k => $v) {
                        $this->setLoop($k, $v);
                        unset($this->_currloop[$k]);
                    }
                    $this->_currloopname = array();
                    return true;
                } else {
                    return false;
                }
            } elseif (!isset($this->_currloop[$loopname]) || empty($this->_currloopname)) { // newLoop not yet envoked
                vlibTemplateError::raiseError('VT_WARNING_LOOP_NOT_SET', WARNING);
                return false;
            } else { // add a specific loop
                $this->setLoop($loopname, $this->_currloop[$loopname]);
                unset($this->_currloopname[$loopname], $this->_currloop[$loopname]);
            }
            return true;
        }
        /**
         * Unsets a loop which has already been set.
         * Can only unset top level loops.
         * @param string loop to remove use: vlibTemplate::unsetLoop(loop[, loop..])
         * @return boolean true/false returns true unless called with 0 params
         * @access public
         */
        public function unsetLoop()
        {
            $num_args = func_num_args();
            if ($num_args < 1) return false;
            for ($i = 0; $i < $num_args; $i++) {
                $var = func_get_arg($i);
                if ($this->OPTIONS['CASELESS']) $var = strtolower($var);
                if (!preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $var)) continue;
                unset($this->_arrvars[$var]);
            }
            return true;
        }
        /**
         * Resets the vlibTemplate object. After using vlibTemplate::reset() you must
         * use vlibTemplate::newTemplate(tmpl) to reuse, not passing in the options array.
         * @return boolean true
         * @access public
         */
        public function reset()
        {
            $this->clearVars();
            $this->clearLoops();
            $this->_tmplfilename = null;
            $this->_tmplfile = null;
            $this->_tmplfilep = null;
            $this->_tmploutput = null;
            $this->_parsed = false;
            $this->_unknowns = array();
            $this->_firstparsetime = null;
            $this->_totalparsetime = null;
            $this->_currloopname = null;
            $this->_currloop = array();
            return true;
        }
        /**
         * Unsets all variables in the template
         * @return boolean true
         * @access public
         */
        public function clearVars()
        {
            $this->_vars = array();
            return true;
        }
        /**
         * Unsets all loops in the template
         * @return boolean true
         * @access public
         */
        public function clearLoops()
        {
            $this->_arrvars = array();
            $this->_currloopname = null;
            $this->_currloop = array();
            return true;
        }
        /**
         * Unsets all variables and loops set using setVar/Loop()
         * @return boolean true
         * @access public
         */
        public function clearAll()
        {
            $this->clearVars();
            $this->clearLoops();
            return true;
        }
        /**
         * Returns true if unknowns were found after parsing.
         * Function MUST be called AFTER one of the parsing functions to have any relevance.
         * @return boolean true/false
         * @access public
         */
        public function unknownsExist()
        {
            return !empty($this->_unknowns);
        }
        /**
         * Alias for unknownsExist.
         * @access public
         */
        public function unknowns()
        {
            return $this->unknownsExist();
        }
        /**
         * Returns an array of all unknown vars found when parsing.
         * This function is only relevant after parsing a document.
         * @return array
         * @access public
         */
        public function getUnknowns()
        {
            return $this->_unknowns;
        }
        /**
         * Sets how you want to handle variables that were found in the
         * template but not set in vlibTemplate using vlibTemplate::setVar().
         * @param  string $arg ignore, remove, print, leave or comment
         * @return boolean
         * @access public
         */
        public function setUnknowns($arg)
        {
            $arg = strtolower(trim($arg));
            if (preg_match('/^ignore|remove|print|leave|comment$/', $arg)) {
                $this->OPTIONS['UNKNOWNS'] = $arg;
                return true;
            }
            return false;
        }
        /**
         * function sets the paths to use when including files.
         * Use of this function: vlibTemplate::setPath(string path [, string path, ..]);
         * i.e. if $tmpl is your template object do: $tmpl->setPath('/web/htdocs/templates','/web/htdocs/www');
         * with as many paths as you like.
         * if this function is called without any arguments, it will just delete any previously set paths.
         *
         * @param string path (mulitple)
         * @return bool success
         * @access public
         */
        public function setPath()
        {
            $num_args = func_num_args();
            if ($num_args < 1) {
                $this->OPTIONS['INCLUDE_PATHS'] = array();
                return true;
            }
            for ($i = 0; $i < $num_args; $i++) {
                $thispath = func_get_arg($i);
                array_push($this->OPTIONS['INCLUDE_PATHS'], realpath($thispath));
            }
            return true;
        }
        /**
         * After using one of the parse functions, this will allow you
         * access the time taken to parse the template.
         * see OPTION 'TIME_PARSE'.
         *
         * @return float time taken to parse template
         * @access public
         */
        public function getParseTime()
        {
            if ($this->OPTIONS['TIME_PARSE'] && $this->_parsed) {
                return $this->_totalparsetime;
            }
            return false;
        }
        /**
         * Identical to pparse() except that it uses output buffering w/ gz compression thus
         * printing the output directly and compressed if poss.
         * Will possibly if parsing a huge template.
         *
         * @access public
         * @return boolean true/false
         */
        public function fastPrint()
        {
            $ret = $this->_parse('ob_gzhandler');
            print($this->_tmploutput);
            return $ret;
        }
        /**
         * Calls parse, and then prints out $this->_tmploutput
         * @access public
         * @return boolean true/false
         */
        public function pparse()
        {
            if (!$this->_parsed) $this->_parse();
            print($this->_tmploutput);
            return true;
        }
        /**
         * Alias for pparse()
         * @access public
         */
        public function pprint()
        {
            return $this->pparse();
        }
        /**
         * Returns the parsed output, ready for printing, passing to mail() ...etc.
         * Invokes $this->_parse() if template has not yet been parsed.
         *
         * @access public
         * @return boolean true/false
         */
        public function grab()
        {
            if (!$this->_parsed) $this->_parse();
            return $this->_tmploutput;
        }
        /*-----------------------------------------------------------------------------\
        |                           private functions                                  |
        \-----------------------------------------------------------------------------*/
        /**
         * vlibTemplate constructor.
         * if $tmplfile has been passed to it, it will send to $this->newTemplate()
         * @param string $tmplfile full path to template file
         * @param array $options see above
         * @return boolean true/false
         * @access private
         */
        public function __construct($tmplfile = null, $options = null)
        {
            if (is_array($tmplfile) && $options == null) {
                $options = $tmplfile;
                unset($tmplfile);
            }
            $this->VLIBTEMPLATE_ROOT = dirname(realpath(__FILE__));
            if (is_array(vlibIni::vlibTemplate())) {
                foreach (vlibIni::vlibTemplate() as $name => $val) {
                    $this->OPTIONS[$name] = $val;
                }
            }
            if (is_array($options)) {
                foreach($options as $key => $val) {
                    $key = strtoupper($key);
                    if ($key == 'PATH') {
                        $this->setPath($val);
                    } else {
                        $this->_setOption($key, strtolower($val));
                    }
                }
            }
            if($tmplfile) $this->newTemplate($tmplfile);
            if ($this->OPTIONS['GLOBAL_CONTEXT_VARS']) $this->setContextVars();
            return true;
        }
        /**
         * function returns the text from the file, or if we're using cache, the text
         * from the cache file. MUST RETURN DATA.
         * @param string tmplfile contains path to template file
         * @param do_eval used for included files. If set then this function must do the eval()'ing.
         * @access private
         * @return mixed data/string or boolean
         */
        private function _getData ($tmplfile, $do_eval=false)
        {
            //* check the current file depth
            if ($this->_includedepth > $this->OPTIONS['MAX_INCLUDES'] || $tmplfile == false) {
                return;
            } else {
                if ($this->_debug){
                    array_push($this->_debugIncludedfiles, $tmplfile);
                }
                if ($do_eval) {
                    array_push($this->_currentincludedir, dirname($tmplfile));
                    $this->_includedepth++;
                }
            }
            if($this->_cache && $this->_checkCache($tmplfile)) { //* cache exists so lets use it
                $data = fread($fp = fopen($this->_cachefile, 'r'), filesize($this->_cachefile));
                fclose($fp);
            } else { //* no cache lets parse the file
                $data = fread($fp = fopen($tmplfile, 'r'), filesize($tmplfile));
                fclose($fp);
                $regex = '/(<|<\/|{|{\/|<!--|<!--\/){1}\s*';
                $regex.= 'tmpl_([\w]+)\s*';
                $regex.= '((?:(?:';
                $regex.=    '(?:';
                $regex.=        '(name|format|escape|op|value|file)';
                $regex.=        '\s*=\s*';
                $regex.=    ')?';
                $regex.=    '(?:[\"\'])?';
                $regex.=    '((?<=[\"\'])';
                $regex.=    '[^\"\']*|[a-z0-9_\.]*)';
                $regex.=    '[\"\']?';
                $regex.= ')?\s*)*?)';
                $regex.= '(?:>|\/>|}|-->){1}';
                $regex.= '/i';
                $data = preg_replace_callback($regex, array($this, '_parseTag'), $data);
                if ($this->_cache) { // add cache if need be
                    $this->_createCache($data);
                }
            }
            //* now we must parse the $data and check for any <tmpl_include>'s
            if ($this->_debug) $this->doDebugWarnings(file($tmplfile), $tmplfile);
            if ($do_eval) {
                $success = @eval('?>'.$data.'<?php return 1;');
                $this->_includedepth--;
                array_pop($this->_currentincludedir);
                return $success;
            } else {
                return $data;
            }
        }
        /**
         * Searches for all possible instances of file { $file }
         * @param string $file path of file we're looking for
         * @access private
         * @return mixed fullpath to file or boolean false
         */
        private function _fileSearch($file)
        {
            $filename = basename($file);
            $filepath = dirname($file);
            if(isset($_SESSION['s']['module']['name']) && isset($_SESSION['s']['theme'])) {
                if(is_file(ISPC_THEMES_PATH.'/'.$_SESSION['s']['theme'].'/templates/'.$_SESSION['s']['module']['name'].'/'.$filename)) {
                    return ISPC_THEMES_PATH.'/'.$_SESSION['s']['theme'].'/templates/'.$_SESSION['s']['module']['name'].'/'.$filename;
                }
            }
            //* check fullpath first..
            $fullpath = $filepath.'/'.$filename;
            if (is_file($fullpath)) return $fullpath;
            //* ..then check for relative path for current directory..
            if (!empty($this->_currentincludedir)) {
                $currdir = $this->_currentincludedir[(count($this->_currentincludedir) -1)];
                $relativepath = realpath($currdir.'/'.$filepath.'/'.$filename);
                if (is_file($relativepath)) {
                    array_push($this->_currentincludedir, dirname($relativepath));
                    return $relativepath;
                }
            }
            //* ..then check for relative path for all additional given paths..
            if (!empty($this->OPTIONS['INCLUDE_PATHS'])) {
                foreach ($this->OPTIONS['INCLUDE_PATHS'] as $currdir) {
                    $relativepath = realpath($currdir.'/'.$filepath.'/'.$filename);
                    if (is_file($relativepath)) {
                        return $relativepath;
                    }
                }
            }
            //* ..then check path from TEMPLATE_DIR..
            if (!empty($this->OPTIONS['TEMPLATE_DIR'])) {
                $fullpath = realpath($this->OPTIONS['TEMPLATE_DIR'].'/'.$filepath.'/'.$filename);
                if (is_file($fullpath)) return $fullpath;
            }
            //* ..then check relative path from executing php script..
            $fullpath = realpath($filepath.'/'.$filename);
            if (is_file($fullpath)) return $fullpath;
            //* ..then check path from template file.
            if (!empty($this->VLIBTEMPLATE_ROOT)) {
                $fullpath = realpath($this->VLIBTEMPLATE_ROOT.'/'.$filepath.'/'.$filename);
                if (is_file($fullpath)) return $fullpath;
            }
            return false; // uh oh, file not found
        }
        /**
         * Modifies the array $arr to add Template variables, __FIRST__, __LAST__ ..etc
         * if $this->OPTIONS['LOOP_CONTEXT_VARS'] is true.
         * Used by $this->setloop().
         * @param array $arr
         * @return array new look array
         * @access private
         */
        private function _arrayBuild($arr)
        {
            if (is_array($arr) && !empty($arr)) {
                $arr = array_values($arr); // to prevent problems w/ non sequential arrays
                for ($i = 0; $i < count($arr); $i++) {
                    if(!is_array($arr[$i]))  return false;
                    foreach ($arr[$i] as $k => $v) {
                        unset($arr[$i][$k]);
                        if ($this->OPTIONS['CASELESS']) $k = strtolower($k);
                        if (preg_match('/^[0-9]+$/', $k)) $k = '_'.$k;
                        if (is_array($v)) {
                            if (($arr[$i][$k] = $this->_arrayBuild($v)) == false) return false;
                        } else { // reinsert the var
                            $arr[$i][$k] = $v;
                        }
                    }
                    if ($this->OPTIONS['LOOP_CONTEXT_VARS']) {
                        if ($i == 0) $arr[$i]['__FIRST__'] = true;
                        if (($i + 1) == count($arr)) $arr[$i]['__LAST__'] = true;
                        if ($i != 0 && (($i + 1) < count($arr))) $arr[$i]['__INNER__'] = true;
                        if (is_int(($i+1) / 2))  $arr[$i]['__EVEN__'] = true;
                        if (!is_int(($i+1) / 2))  $arr[$i]['__ODD__'] = true;
                        $arr[$i]['__ROWNUM__'] = ($i + 1);
                    }
                }
                return $arr;
            } elseif (empty($arr)) {
                return true;
            }
        }
        /**
         * returns a string used for parsing in tmpl_if statements.
         * @param string $varname
         * @param string $value
         * @param string $op
         * @param string $namespace current namespace
         * @access private
         * @return string used for eval'ing
         */
        private function _parseIf($varname, $value = null, $op = null, $namespace = null, $format = null)
        {
            if (isset($namespace)) $namespace = substr($namespace, 0, -1);
            $comp_str = ''; // used for extended if statements
            // work out what to put on the end id value="whatever" is used
            if (isset($value)) {
                // add the correct operator depending on whether it's been specified or not
                if (!empty($op)) {
                    if (in_array($op, $this->allowed_if_ops)) {
                        $comp_str .= $op;
                    } else {
                        vlibTemplateError::raiseError('VT_WARNING_INVALID_IF_OP', WARNING, $op);
                    }
                } else {
                    $comp_str .= '==';
                }
                // now we add the value, if it's numeric, then we leave the quotes off
                if (is_numeric($value)) {
                    $comp_str .= $value;
                } else {
                    $comp_str .= '\''.$value.'\'';
                }
            }
            if (count($this->_namespace) == 0 || $namespace == 'global') return '$this->_vars[\''.$varname.'\']'.$comp_str;
            $retstr = '$this->_arrvars';
            $numnamespaces = count($this->_namespace);
            for ($i=0; $i < $numnamespaces; $i++) {
                if ($this->_namespace[$i] == $namespace || (($i + 1) == $numnamespaces && !empty($namespace))) {
                    $retstr .= "['".$namespace."'][\$_".$i."]";
                    break 1;
                } else {
                    $retstr .= "['".$this->_namespace[$i]."'][\$_".$i."]";
                }
            }
            if ($this->OPTIONS['GLOBAL_VARS'] && empty($namespace)) {
                $retstr = '(('.$retstr.'[\''.$varname.'\'] !== null) ? '.$retstr.'[\''.$varname.'\'] : $this->_vars[\''.$varname.'\'])';
                if(isset($format) && isset($value) && $format == 'version') {
                    return 'version_compare(' . $retstr . ', \'' . $value . '\', \'' . (!empty($op) ? $op : '==') . '\')';
                } else {
                    return $retstr.$comp_str;
                }
            }
            else {
                if(isset($format) && isset($value) && $format == 'version') {
                    return 'version_compare(' . $retstr."['".$varname."']" . ', \'' . $value . '\', \'' . (!empty($op) ? $op : '==') . '\')';
                } else {
                    return $retstr."['".$varname."']".$comp_str;
                }
            }
        }
        /**
         * returns a string used for parsing in tmpl_loop statements.
         * @param string $varname
         * @access private
         * @return string used for eval'ing
         */
        private function _parseLoop ($varname)
        {
            array_push($this->_namespace, $varname);
            $tempvar = count($this->_namespace) - 1;
            $retstr = "for (\$_".$tempvar."=0 ; \$_".$tempvar." < count(\$this->_arrvars";
            for ($i=0; $i < count($this->_namespace); $i++) {
                $retstr .= "['".$this->_namespace[$i]."']";
                if ($this->_namespace[$i] != $varname) $retstr .= "[\$_".$i."]";
            }
            return $retstr."); \$_".$tempvar."++) {";
        }
        /**
         * returns a string used for parsing in tmpl_var statements.
         * @param string $wholetag
         * @param string $tag
         * @param string $varname
         * @param string $escape
         * @param string $format
         * @param string $namespace
         * @access private
         * @return string used for eval'ing
         */
        private function _parseVar ($wholetag, $tag, $varname, $escape, $format, $namespace)
        {
            if (!empty($namespace)) $namespace = substr($namespace, 0, -1);
            $wholetag = stripslashes($wholetag);
            if (count($this->_namespace) == 0 || $namespace == 'global') {
                $var1 = '$this->_vars[\''.$varname.'\']';
            } else {
                $var1build = "\$this->_arrvars";
                $numnamespaces = count($this->_namespace);
                for ($i=0; $i < $numnamespaces; $i++) {
                    if ($this->_namespace[$i] == $namespace || (($i + 1) == $numnamespaces && !empty($namespace))) {
                        $var1build .= "['".$namespace."'][\$_".$i."]";
                        break 1;
                    } else {
                        $var1build .= "['".$this->_namespace[$i]."'][\$_".$i."]";
                    }
                }
                $var1 = $var1build . "['$varname']";
                if ($this->OPTIONS['GLOBAL_VARS'] && empty($namespace)) {
                    $var2 = '$this->_vars[\''.$varname.'\']';
                }
            }
            $beforevar = '';
            $aftervar  = '';
            if (!empty($escape)&& isset($this->ESCAPE_TAGS[$escape])) {
                $beforevar .= $this->ESCAPE_TAGS[$escape]['open'];
                $aftervar   = $this->ESCAPE_TAGS[$escape]['close'] . $aftervar;
            }
            if (!empty($format)&& isset($this->FORMAT_TAGS[$format])) {
                $beforevar .= $this->FORMAT_TAGS[$format]['open'];
                $aftervar   = $this->FORMAT_TAGS[$format]['close'] . $aftervar;
            }
            //* build return values
            $retstr  = 'if ('.$var1.' !== null) { ';
            $retstr .= 'print('.$beforevar.$var1.$aftervar.'); ';
            $retstr .= '}';
            if (@$var2) {
                $retstr .= ' elseif ('.$var2.' !== null) { ';
                $retstr .= 'print('.$beforevar.$var2.$aftervar.'); ';
                $retstr .= '}';
            }
            switch (strtolower($this->OPTIONS['UNKNOWNS'])) {
            case 'comment':
                $comment = addcslashes('<!-- unknown variable '.preg_replace('/<!--|-->/', '', $wholetag).'//-->', '"');
                $retstr .= ' else { print("'.$comment.'"); $this->_setUnknown("'.$varname.'"); }';
                return $retstr;
            case 'leave':
                $retstr .= ' else { print("'.addcslashes($wholetag, '"').'"); $this->_setUnknown("'.$varname.'"); }';
                return $retstr;
            case 'print':
                $retstr .= ' else { print("'.htmlspecialchars($wholetag, ENT_QUOTES).'"); $this->_setUnknown("'.$varname.'"); }';
                return $retstr;
            case 'ignore':
                return $retstr;
            case 'remove':
            default:
                $retstr .= ' else { $this->_setUnknown("'.$varname.'"); }';
                return $retstr;
            }
        }
        /**
         * takes values from preg_replace in $this->_intparse() and determines
         * the replace string.
         *
         * @param array $args array of all matches found by preg_replace
         * @access private
         * @return string replace values
         */
        private function _parseTag ($args)
        {
            $wholetag = $args[0];
            $openclose = $args[1];
            $tag = strtolower($args[2]);
            if ($tag == 'else') return '<?php } else { ?>';
            if ($tag == 'tmpl_include') return $wholetag; // ignore tmpl_include tags
            if (preg_match("/^<\/|{\/|<!--\/$/s", $openclose) || preg_match("/^end[if|loop|unless|comment]$/", $tag)) {
                if ($tag == 'loop' || $tag == 'endloop') array_pop($this->_namespace);
                if ($tag == 'comment' || $tag == 'endcomment') {
                    return '<?php */ ?>';
                } else {
                    return '<?php } ?>';
                }
            }
            // arrange attributes
            $tmp_atts = $args[3];
            $atts = preg_split('/\s+/', $tmp_atts);
            foreach($atts as $att) {
                $regex =    '/(?:';
                $regex.=        '(name|format|escape|op|value|file)';
                $regex.=        '\s*=\s*';
                $regex.=    ')?';
                $regex.=    '(?:[\"\'])?';
                $regex.=    '((?<=[\"\'])';
                $regex.=    '[^\"\']*|[a-z0-9_\.]*)';
                $regex.=    '[\"\']?/';
                if(preg_match($regex, $att, $match)) {
                    $key = (empty($match[1])) ? 'name' : strtolower($match[1]);
                    if ($key == 'name' && preg_match('/^(php)?include$/', $tag)) $key = 'file';
                    $$key = $match[2];
                }
            }
            $var = ($this->OPTIONS['CASELESS']) ? strtolower($name) : $name;
            if ($this->_debug && !empty($var)) {
                if (preg_match("/^global\.([A-Za-z_]+[_A-Za-z0-9]*)$/", $var, $matches)) $var2 = $matches[1];
                if (empty($this->_debugTemplatevars[$tag])) $this->_debugTemplatevars[$tag] = array();
                if (!isset($var2)) $var2 = $var;
                if (!in_array($var2, $this->_debugTemplatevars[$tag])) array_push($this->_debugTemplatevars[$tag], $var2);
            }
            if (preg_match("/^([A-Za-z_]+[_A-Za-z0-9]*(\.)+)?([A-Za-z_]+[_A-Za-z0-9]*)$/", $var, $matches)) {
                $var = $matches[3];
                $namespace = $matches[1];
            }
            //* return correct string (tag dependent)
            switch ($tag) {
            case 'var':
                if (empty($escape) && (!empty($this->OPTIONS['DEFAULT_ESCAPE']) && strtolower($this->OPTIONS['DEFAULT_ESCAPE']) != 'none')) {
                    $escape = strtolower($this->OPTIONS['DEFAULT_ESCAPE']);
                }
                return '<?php '.$this->_parseVar ($wholetag, $tag, $var, @$escape, @$format, @$namespace)." ?>\n";
            case 'if':
                return '<?php if ('. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
            case 'unless':
                return '<?php if (!'. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
            case 'elseif':
                return '<?php } elseif ('. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
            case 'loop':
                return '<?php '. $this->_parseLoop($var) .'?>';
            case 'comment':
                if (empty($var)) { // full open/close style comment
                    return '<?php /* ?>';
                } else { // just ignore tag if it was a one line comment
                    return;
                }
            case 'phpinclude':
                if ($this->OPTIONS['ENABLE_PHPINCLUDE']) {
                    return '<?php include(\''.$file.'\'); ?>';
                }
            case 'include':
                return '<?php $this->_getData($this->_fileSearch(\''.$file.'\'), 1); ?>';
            case 'dyninclude':
                return '<?php $this->_getData($this->_fileSearch($this->_dyninclude[\''.$name.'\']), 1); ?>';
            default:
                if ($this->OPTIONS['STRICT']) vlibTemplateError::raiseError('VT_ERROR_INVALID_TAG', KILL, htmlspecialchars($wholetag, ENT_QUOTES));
                break;
            }
        }
        /**
         * Parses $this->_tmplfile into correct format for eval() to work
         * Called by $this->_parse(), or $this->fastPrint, this replaces all <tmpl_*> references
         * with their correct php representation, i.e. <tmpl_var title> becomes $this->vars['title']
         * Sets final parsed file to $this->_tmplfilep.
         *
         * @access private
         * @return boolean true/false
         */
        private function _intParse ()
        {
            //$mqrt = get_magic_quotes_runtime();
            //set_magic_quotes_runtime(0);
            $this->_tmplfilep = '?>'.$this->_getData($this->_tmplfilename).'<?php return true;';
            //set_magic_quotes_runtime($mqrt);
            return true;
        }
        /**
         * Calls _intParse, and eval()s $this->tmplfilep
         * and outputs the results to $this->tmploutput
         *
         * @param bool compress whether to compress contents
         * @access private
         * @return boolean true/false
         */
        private function _parse ($compress = '')
        {
            if (!$this->_parsed) {
                if ($this->OPTIONS['TIME_PARSE']) $this->_firstparsetime = $this->_getMicroTime();
                $this->_intParse();
                $this->_parsed = true;
                if ($this->OPTIONS['TIME_PARSE']) $this->_totalparsetime = ($this->_getMicroTime() - $this->_firstparsetime);
                if ($this->OPTIONS['TIME_PARSE'] && $this->OPTIONS['GLOBAL_CONTEXT_VARS']) $this->setVar('__PARSE_TIME__', $this->getParseTime());
            }
            // ob_start($compress);
            ob_start();
            array_push($this->_currentincludedir, dirname($this->_tmplfilename));
            $this->_includedepth++;
            $success = @eval($this->_tmplfilep);
            $this->_includedepth--;
            array_pop($this->_currentincludedir);
            if ($this->_debug) $this->doDebug();
            if (!$success) vlibTemplateError::raiseError('VT_ERROR_PARSE', FATAL);
            $this->_tmploutput .= ob_get_contents();
            ob_end_clean();
            return true;
        }
        /**
         * Sets one or more of the boolean options 1/0, that control certain actions in the template.
         * Use of this function:
         * either: vlibTemplate::_setOptions(string option_name, bool option_val [, string option_name, bool option_val ..]);
         * or      vlibTemplate::_setOptions(array);
         *          with an associative array where the key is the option_name
         *          and the value is the option_value.
         *
         * @param mixed (mulitple)
         * @return bool true/false
         * @access private
         */
        private function _setOption()
        {
            $numargs = func_num_args();
            if ($numargs < 1) {
                vlibTemplateError::raiseError('VT_ERROR_WRONG_NO_PARAMS', null, '_setOption()');
                return false;
            }
            if ($numargs == 1) {
                $options = func_get_arg(1);
                if (is_array($options)) {
                    foreach ($options as $k => $v) {
                        if ($v != null) {
                            if(in_array($k, array_keys($this->OPTIONS))) $this->OPTIONS[$k] = $v;
                        } else {
                            continue;
                        }
                    }
                } else {
                    vlibTemplateError::raiseError('VT_ERROR_WRONG_NO_PARAMS', null, '_setOption()');
                    return false;
                }
            }elseif (is_int($numargs / 2)) {
                for ($i = 0; $i < $numargs; $i=($i+2)) {
                    $k  = func_get_arg($i);
                    $v = func_get_arg(($i+1));
                    if ($v != null) {
                        if(in_array($k, array_keys($this->OPTIONS))) $this->OPTIONS[$k] = $v;
                    }
                }
            } else {
                vlibTemplateError::raiseError('VT_ERROR_WRONG_NO_PARAMS', null, '_setOption()');
                return false;
            }
            return true;
        }
        /**
         * Used during parsing, this function sets an unknown var checking to see if it
         * has been previously set.
         * @param string var
         * @access private
         */
        private function _setUnknown($var)
        {
            if (!in_array($var, $this->_unknowns)) array_push($this->_unknowns, $var);
        }
        /**
         * Returns microtime as a float number
         * @return float microtime
         * @access private
         */
        private function _getMicrotime()
        {
            list($msec, $sec) = explode(' ', microtime());
            return (float)$msec + (float)$sec;
        }
        /**
         * Returns str encoded to hex code.
         * @param string str to be encoded
         * @param bool true/false specify whether to use hex_entity
         * @return string encoded in hex
         * @access private
         */
        private  function _escape_hex($str = '', $entity = false) {
            $prestr = $entity ? '&#x' : '%';
            $poststr= $entity ? ';' : '';
            for ($i=0; $i < strlen($str); $i++) {
                $return .= $prestr.bin2hex($str[$i]).$poststr;
            }
            return $return;
        }
        /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    The following functions have no use and are included just so that if the user
    is making use of vlibTemplateCache functions, this doesn't crash when changed to
    vlibTemplate if the user is quickly bypassing the vlibTemplateCache class.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
        function clearCache()        {vlibTemplateError::raiseError('VT_WARNING_NOT_CACHE_OBJ', WARNING, 'clearCache()');}
        function recache()           {vlibTemplateError::raiseError('VT_WARNING_NOT_CACHE_OBJ', WARNING, 'recache()');}
        function setCacheLifeTime()  {vlibTemplateError::raiseError('VT_WARNING_NOT_CACHE_OBJ', WARNING, 'setCacheLifeTime()');}
        function setCacheExtension() {vlibTemplateError::raiseError('VT_WARNING_NOT_CACHE_OBJ', WARNING, 'setCacheExtension()');}
    } // << end class Def
    //include_once (ISPC_CLASS_PATH.'/vlibTemplate/debug.php');
    include_once ISPC_INSTALL_ROOT.'/install/lib/classes/tpl_cache.inc.php';
} // << end if(!defined())..
?>
install/lib/classes/tpl_cache.inc.php
New file
@@ -0,0 +1,193 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0                                                      |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002 Active Fish Group                                 |
// +----------------------------------------------------------------------+
// | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk>                     |
// +----------------------------------------------------------------------+
//
// $Id: cache.php,v 1.1 2003/07/08 12:32:06 platinum Exp $
/**
 * Class uses all of vlibTemplate's functionality but caches the template files.
 * It creates an identical tree structure to your filesystem but with cached files.
 *
 * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
 * @since 22/02/2002
 * @package vLIB
 * @access public
 */
class tplc extends tpl {
    /*-----------------------------------------------------------------------------\
|     DO NOT TOUCH ANYTHING IN THIS CLASS, IT MAY NOT WORK OTHERWISE           |
\-----------------------------------------------------------------------------*/
    var $_cache = 1;     // tells vlibTemplate that we're caching
    var $_cachefile;     // full path to current cache file (even if it doesn't yet exist)
    var $_cacheexists;   // has this file been cached before
    var $_cachefilelocked; // is this file currently locked whilst writing
    var $_cachefiledir;  // dir of current cache file
    var $_clearcache = 0;
    /**
     * FUNCTION: clearCache
     * will unset a file, and set $this->_cacheexists to 0.
     *
     * @access public
     * @return boolean
     */
    function clearCache() {
        $this->_clearcache = 1;
        return true;
    }
    /**
     * FUNCTION: recache
     * alias for clearCache().
     *
     * @access public
     * @return boolean
     */
    function recache() {
        return $this->clearCache();
    }
    /**
     * FUNCTION: setCacheLifeTime
     * sets the lifetime of the cached file
     *
     * @param int $int number of seconds to set lifetime to
     * @access public
     * @return boolean
     */
    function setCacheLifeTime($int = null) {
        if ($int == null || !is_int($int)) return false;
        if ($int == 0) $int = 60;
        if ($int == -1) $int = 157680000; // set to 5 yrs time
        $this->OPTIONS['CACHE_LIFETIME'] = $int;
        return true;
    }
    /**
     * FUNCTION: setCacheExtension
     * sets the extention of the cache file
     *
     * @param str $str name of new cache extention
     * @access public
     * @return boolean
     */
    function setCacheExtension($str = null) {
        if ($str == null || !preg_match('/^[a-z0-9]+$/', strtolower($str))) return false;
        $this->OPTIONS['CACHE_EXTENSION'] = strtolower($str);
        return true;
    }
    /*----------------------------------------\
          Private Functions
-----------------------------------------*/
    /**
     * FUNCTION: _checkCache
     * checks if there's a cache, if there is then it will read the cache file as the template.
     */
    function _checkCache ($tmplfile) {
        $this->_cachefile = $this->_getFilename($tmplfile);
        if ($this->_clearcache) {
            if (file_exists($this->_cachefile)) unlink($this->_cachefile);
            return false;
        }
        if (file_exists($this->_cachefile)) {
            $this->_cacheexists = 1;
            // if it's expired
            if ((filemtime($this->_cachefile) + $this->OPTIONS['CACHE_LIFETIME']) < date('U')
                || filectime($this->_cachefile) < filemtime($tmplfile)) {
                $this->_cacheexists = 0;
                return false; // so that we know to recache
            }
            else {
                return true;
            }
        } else {
            $this->_cacheexists = 0;
            return false;
        }
    }
    /**
     * FUNCTION: _getFilename
     * gets the full pathname for the cached file
     *
     */
    function _getFilename($tmplfile) {
        return $this->OPTIONS['CACHE_DIRECTORY'].'/'.md5('vlibCachestaR'.realpath($tmplfile)).'.'.$this->OPTIONS['CACHE_EXTENSION'];
    }
    /**
     * FUNCTION: _createCache
     * creates the cached file
     *
     */
    function _createCache($data) {
        $cache_file = $this->_cachefile;
        if(!$this->_prepareDirs($cache_file)) return false; // prepare all of the directories
        $f = fopen($cache_file, "w");
        flock($f, 2); // set an EXclusive lock
        if (!$f) vlibTemplateError::raiseError('VT_ERROR_NO_CACHE_WRITE', KILL, $cache_file);
        fputs($f, $data); // write the parsed string from vlibTemplate
        flock($f, 3); // UNlock file
        fclose($f);
        touch($cache_file);
        return true;
    }
    /**
     * FUNCTION: _prepareDirs
     * prepares the directory structure
     *
     */
    function _prepareDirs($file) {
        if (empty($file)) die('no filename'); //do error in future
        $filepath = dirname($file);
        if (is_dir($filepath)) return true;
        $dirs = preg_split('/[\\/]/', $filepath);
        $currpath;
        foreach ($dirs as $dir) {
            $currpath .= $dir .'/';
            $type = @filetype($currpath);
            ($type=='link') and $type = 'dir';
            if ($type != 'dir' && $type != false && !empty($type)) {
                vlibTemplateError::raiseError('VT_ERROR_WRONG_CACHE_TYPE', KILL, 'directory: '.$currpath.', type: '.$type);
            }
            if ($type == 'dir') {
                continue;
            }
            else {
                $s = @mkdir($currpath, 0775);
                if (!$s) vlibTemplateError::raiseError('VT_ERROR_CACHE_MKDIR_FAILURE', KILL, 'directory: '.$currpath);
            }
        }
        return true;
    }
} // -- end vlibTemplateCache class
?>
install/lib/classes/tpl_error.inc.php
New file
@@ -0,0 +1,95 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0                                                      |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002 Active Fish Group                                 |
// +----------------------------------------------------------------------+
// | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk>                     |
// +----------------------------------------------------------------------+
//
// $Id: error.php,v 1.1 2003/07/08 12:32:06 platinum Exp $
define('FATAL', E_USER_ERROR);
define('WARNING', E_USER_WARNING);
define('NOTICE', E_USER_NOTICE);
define('KILL',   -1); // used for killing inside parsing.
/**
 * Class is used by vlibTemplate.
 * It handles all of the error reporting for vlibTemplate.
 *
 * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
 * @since 06/03/2002
 * @package vLIB
 * @access private
 */
class vlibTemplateError {
    /*-----------------------------------------------------------------------------\
|     DO NOT TOUCH ANYTHING IN THIS CLASS IT MAY NOT WORK OTHERWISE            |
\-----------------------------------------------------------------------------*/
    public static function raiseError ($code, $level = null, $extra=null) {
        if (!($level & error_reporting())&& $level != KILL) return; // binary AND checks for reporting level
        $error_codes = array(
            'VT_ERROR_NOFILE'               => 'vlibTemplate Error: Template ('.$extra.') file not found.',
            'VT_ERROR_PARSE'                => 'vlibTemplate Error: Parse error!<br>To debug this file, use vlibTemplateDebug instead of vlibTemplate in the class instantiation(i.e. new vlibTemplateDebug).',
            'VT_NOTICE_INVALID_TAG'         => 'vlibTemplate Notice: Invalid tag ('.$extra.').',
            'VT_ERROR_INVALID_TAG'          => 'vlibTemplate Error: Invalid tag ('.$extra.'). To disable this you must turn of the STRICT option.',
            'VT_NOTICE_INVALID_ATT'         => 'vlibTemplate Notice: Invalid attribute ('.$extra.').',
            'VT_WARNING_INVALID_ARR'        => 'vlibTemplate Warning: Invalid loop structure passed to vlibTemplate::setLoop() (loop name: '.$extra.').',
            'VT_ERROR_INVALID_ERROR_CODE'   => 'vlibTemplate Error: Invalid error raised.',
            'VT_ERROR_WRONG_NO_PARAMS'      => 'vlibTemplate Warning: Wrond parameter count passed to '.$extra.'.',
            'VT_ERROR_UNKNOWN_VAR'          => 'vlibTemplate Error: template var not found.',
            'VT_ERROR_NO_CACHE_WRITE'       => 'vlibTemplate Error: unable to write to cache file ('.$extra.').',
            'VT_ERROR_WRONG_CACHE_TYPE'     => 'vlibTemplate Error: non-directory file found in cache root with same name as directory ('.$extra.').',
            'VT_ERROR_CACHE_MKDIR_FAILURE'  => 'vlibTemplate Error: failed to create directory in cache root ('.$extra.').',
            'VT_WARNING_NOT_CACHE_OBJ'      => 'vlibTemplate Warning: called a vlibTemplateCache function ('.$extra.') without instantiating the vlibTemplateCache class.',
            'VT_WARNING_LOOP_NOT_SET'       => 'vlibTemplate Warning: called vlibTemplate::addRow() or vlibTemplate::addLoop() with an invalid loop name.',
            'VT_WARNING_INVALID_RESOURCE'   => 'vlibTemplate Warning: Invalid resource type passed to vlibTemplate::setDbLoop() for Db "'.$extra.'".',
            'VT_WARNING_INVALID_LOOP_DB'    => 'vlibTemplate Warning: Invalid Db type passed to vlibTemplate::setDbLoop(), "'.$extra.'" not currently available.',
            'VT_WARNING_INVALID_IF_OP'      => 'vlibTemplate Warning: The Operator "'.$extra.'" is not supported by vlibTemplate.'
        );
        $error_levels = array(
            'VT_ERROR_NOFILE'               => FATAL,
            'VT_ERROR_PARSE'                => FATAL,
            'VT_NOTICE_INVALID_TAG'         => NOTICE,
            'VT_ERROR_INVALID_TAG'          => FATAL,
            'VT_NOTICE_INVALID_ATT'         => NOTICE,
            'VT_WARNING_INVALID_ARR'        => WARNING,
            'VT_ERROR_INVALID_ERROR_CODE'   => FATAL,
            'VT_ERROR_WRONG_NO_PARAMS'      => WARNING,
            'VT_ERROR_UNKNOWN_VAR'          => WARNING,
            'VT_ERROR_NO_CACHE_WRITE'       => KILL,
            'VT_ERROR_WRONG_CACHE_TYPE'     => KILL,
            'VT_ERROR_CACHE_MKDIR_FAILURE'  => KILL,
            'VT_WARNING_NOT_CACHE_OBJ'      => WARNING,
            'VT_WARNING_LOOP_NOT_SET'       => WARNING,
            'VT_WARNING_INVALID_RESOURCE'   => WARNING,
            'VT_WARNING_INVALID_LOOP_DB'    => WARNING,
            'VT_WARNING_INVALID_IF_OP'      => WARNING
        );
        ($level === null) and $level = $error_levels[$code];
        if ($level == KILL) {
            die ($error_codes[$code]);
        }
        if ($msg = $error_codes[$code]) {
            trigger_error($msg, $level);
        } else {
            $level = $error_levels['VT_ERROR_INVALID_ERROR_CODE'];
            $msg = $error_codes['VT_ERROR_INVALID_ERROR_CODE'];
            trigger_error($msg, $level);
        }
        return;
    }
}
?>
install/lib/classes/tpl_ini.inc.php
New file
@@ -0,0 +1,119 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0                                                      |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002 Active Fish Group                                 |
// +----------------------------------------------------------------------+
// | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk>                     |
// +----------------------------------------------------------------------+
//
// $Id: vlibIni.php,v 1.1 2003/07/08 12:31:10 platinum Exp $
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This file contains configuration parametres for use  ;
; with the vLIB library. [ NOW A CLASS!! ]             ;
;                                                      ;
; vLIB uses this file so that for future releases, you ;
; will not have to delve through all the php script    ;
; again to set your specific variable/properties ..etc ;
;                                                      ;
; ---------------------------------------------------- ;
; ATTENTION: Do NOT remove any variable given in the   ;
; configurations below as they will probably still be  ;
; needed by vLIB. If you do not need a variable simply ;
; let it be.                                           ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/
if (!defined('vlibIniClassLoaded')) {
    define('vlibIniClassLoaded', 1);
    /**
     * vlibIni is a class used to store configuration parameters
     * for the vLIB library.
     *
     * @since 21/07/2002
     * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
     * @package vLIB
     * @access private
     */
    class vlibIni {
        /** config vars for vlibTemplate */
        public static function vlibTemplate () {
            global $conf;
            $tpl_dir = ISPC_INSTALL_ROOT."/install/tpl";
            $include_paths = array('/usr/local/ispconfig/server/conf-custom/install');
            return array(
                'TEMPLATE_DIR' => $tpl_dir,   // Default directory for your template files (full path)
                // leave the '/' or '\' off the end of the directory.
                'INCLUDE_PATHS' => $include_paths, // The include path is always searched first for a template file before the template_dir is checked
                'MAX_INCLUDES' => 10,                      // Drill depth for tmpl_include's
                'GLOBAL_VARS' => 1,                        // if set to 1, any variables not found in a
                // loop will search for a global var as well
                'GLOBAL_CONTEXT_VARS' => 1,                // if set to 1, vlibTemplate will add global vars
                // reflecting the environment.
                'LOOP_CONTEXT_VARS' => 1,                  // if set to 1, vlibTemplate will add loop specific vars
                // on each row of the loop.
                'SET_LOOP_VAR' => 1,                       // Sets a global variable for each top level loops
                'DEFAULT_ESCAPE' => 'none',                // 1 of the following: html, url, sq, dq, none
                'STRICT' => 0,                             // Dies when encountering an incorrect tmpl_*
                // style tags i.e. tmpl_vae
                'CASELESS' => 0,                           // Removes case sensitivity on all variables
                'UNKNOWNS' => 'ignore',                    // How to handle unknown variables.
                // 1 of the following: ignore, remove, leave,print, comment
                // 1 of the following: ignore, remove, leave, print, comment
                'TIME_PARSE' => '0',                       // Will enable you to time how long vlibTemplate takes to parse
                // your template. You then use the function: getParseTime().
                'ENABLE_PHPINCLUDE' => '1',                // Will allow template to include a php file using <TMPL_PHPINCLUDE>
                /* the following are only used by the vlibTemplateCache class. */
                'CACHE_DIRECTORY' => '/tmp',
                // Directory where the cached filesystem
                // will be set up (full path, and must be writable)
                // '/' or '\' off the end of the directory.
                'CACHE_LIFETIME' => 604800,                // Duration until file is re-cached in seconds (604800 = 1 week)
                'CACHE_EXTENSION' => 'vtc'                  // extention to be used by the cached file i.e. index.php will become
                // index.vtc (vlibTemplate Compiled)
            );
        } // << end function vlibTemplate
        /** config vars for vlibDate */
        public function vlibDate () {
            return array(
                'DEFAULT_LANG' => 'de'                     // default language for the date displays
            );
        }// << end function vlibDate
    }// << end class vlibIni
}
?>
install/lib/install.lib.php
@@ -828,5 +828,30 @@
    return $timezone;
}
function getapacheversion($get_minor = false) {
        global $app;
        $cmd = '';
        if(is_installed('apache2ctl')) $cmd = 'apache2ctl -v';
        elseif(is_installed('apachectl')) $cmd = 'apachectl -v';
        else {
            $app->log("Could not check apache version, apachectl not found.", LOGLEVEL_WARN);
            return '2.2';
        }
        exec($cmd, $output, $return_var);
        if($return_var != 0 || !$output[0]) {
            $app->log("Could not check apache version, apachectl did not return any data.", LOGLEVEL_WARN);
            return '2.2';
        }
        if(preg_match('/version:\s*Apache\/(\d+)(\.(\d+)(\.(\d+))*)?(\D|$)/i', $output[0], $matches)) {
            return $matches[1] . (isset($matches[3]) ? '.' . $matches[3] : '') . (isset($matches[5]) && $get_minor == true ? '.' . $matches[5] : '');
        } else {
            $app->log("Could not check apache version, did not find version string in apachectl output.", LOGLEVEL_WARN);
            return '2.2';
        }
    }
?>
install/lib/installer_base.lib.php
@@ -1251,11 +1251,12 @@
        $vhost_conf_dir = $conf['apache']['vhost_conf_dir'];
        $vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir'];
        // copy('tpl/apache_ispconfig.conf.master',$vhost_conf_dir.'/ispconfig.conf');
        $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.conf.master', 'tpl/apache_ispconfig.conf.master');
        $tpl = new tpl('apache_ispconfig.conf.master');
        $tpl->setVar('apache_version',getapacheversion());
        $records = $this->db->queryAllRecords('SELECT * FROM '.$conf['mysql']['master_database'].'.server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
        $ip_addresses = array();
        if(is_array($records) && count($records) > 0) {
            foreach($records as $rec) {
                if($rec['ip_type'] == 'IPv6') {
@@ -1268,15 +1269,15 @@
                    foreach($ports as $port) {
                        $port = intval($port);
                        if($port > 0 && $port < 65536 && $ip_address != '') {
                            $content .= 'NameVirtualHost '.$ip_address.":".$port."\n";
                            $ip_addresses[] = array('ip_address' => $ip_address, 'port' => $port);
                        }
                    }
                }
            }
        }
        $content .= "\n";
        wf($vhost_conf_dir.'/ispconfig.conf', $content);
        wf($vhost_conf_dir.'/ispconfig.conf', $tpl->grab());
        unset($tpl);
        if(!@is_link($vhost_conf_enabled_dir.'/000-ispconfig.conf')) {
            symlink($vhost_conf_dir.'/ispconfig.conf', $vhost_conf_enabled_dir.'/000-ispconfig.conf');
@@ -1530,23 +1531,24 @@
            }
            // Dont just copy over the virtualhost template but add some custom settings
            $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_apps.vhost.master', 'tpl/apache_apps.vhost.master');
            $content = str_replace('{apps_vhost_ip}', $conf['web']['apps_vhost_ip'], $content);
            $content = str_replace('{apps_vhost_port}', $conf['web']['apps_vhost_port'], $content);
            $content = str_replace('{apps_vhost_dir}', $conf['web']['website_basedir'].'/apps', $content);
            $content = str_replace('{website_basedir}', $conf['web']['website_basedir'], $content);
            $content = str_replace('{apps_vhost_servername}', $apps_vhost_servername, $content);
            $tpl = new tpl('apache_apps.vhost.master');
            $tpl->setVar('apps_vhost_ip',$conf['web']['apps_vhost_ip']);
            $tpl->setVar('apps_vhost_port',$conf['web']['apps_vhost_port']);
            $tpl->setVar('apps_vhost_dir',$conf['web']['website_basedir'].'/apps');
            $tpl->setVar('apps_vhost_basedir',$conf['web']['website_basedir']);
            $tpl->setVar('apps_vhost_servername',$apps_vhost_servername);
            $tpl->setVar('apache_version',getapacheversion());
            // comment out the listen directive if port is 80 or 443
            if($conf['web']['apps_vhost_ip'] == 80 or $conf['web']['apps_vhost_ip'] == 443) {
                $content = str_replace('{vhost_port_listen}', '#', $content);
                $tpl->setVar('vhost_port_listen','#');
            } else {
                $content = str_replace('{vhost_port_listen}', '', $content);
                $tpl->setVar('vhost_port_listen','');
            }
            wf($vhost_conf_dir.'/apps.vhost', $content);
            wf($vhost_conf_dir.'/apps.vhost', $tpl->grab());
            unset($tpl);
            //copy('tpl/apache_ispconfig.vhost.master', "$vhost_conf_dir/ispconfig.vhost");
            //* and create the symlink
@@ -1926,30 +1928,31 @@
            $vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir'];
            // Dont just copy over the virtualhost template but add some custom settings
            $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_ispconfig.vhost.master', 'tpl/apache_ispconfig.vhost.master');
            $content = str_replace('{vhost_port}', $conf['apache']['vhost_port'], $content);
            $tpl = new tpl('apache_ispconfig.vhost.master');
            $tpl->setVar('vhost_port',$conf['apache']['vhost_port']);
            // comment out the listen directive if port is 80 or 443
            if($conf['apache']['vhost_port'] == 80 or $conf['apache']['vhost_port'] == 443) {
                $content = str_replace('{vhost_port_listen}', '#', $content);
                $tpl->setVar('vhost_port_listen','#');
            } else {
                $content = str_replace('{vhost_port_listen}', '', $content);
                $tpl->setVar('vhost_port_listen','');
            }
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key')) {
                $content = str_replace('{ssl_comment}', '', $content);
                $tpl->setVar('ssl_comment','');
            } else {
                $content = str_replace('{ssl_comment}', '#', $content);
                $tpl->setVar('ssl_comment','#');
            }
            if(is_file($install_dir.'/interface/ssl/ispserver.crt') && is_file($install_dir.'/interface/ssl/ispserver.key') && is_file($install_dir.'/interface/ssl/ispserver.bundle')) {
                $content = str_replace('{ssl_bundle_comment}', '', $content);
                $tpl->setVar('ssl_bundle_comment','');
            } else {
                $content = str_replace('{ssl_bundle_comment}', '#', $content);
                $tpl->setVar('ssl_bundle_comment','#');
            }
            $tpl->setVar('apache_version',getapacheversion());
            wf($vhost_conf_dir.'/ispconfig.vhost', $content);
            wf($vhost_conf_dir.'/ispconfig.vhost', $tpl->grab());
            //copy('tpl/apache_ispconfig.vhost.master', $vhost_conf_dir.'/ispconfig.vhost');
            //* and create the symlink
            if($this->is_update == false) {
                if(@is_link($vhost_conf_enabled_dir.'/ispconfig.vhost')) unlink($vhost_conf_enabled_dir.'/ispconfig.vhost');
install/tpl/apache_apps.vhost.master
@@ -4,40 +4,46 @@
# for the ISPConfig apps vhost
######################################################
{vhost_port_listen} Listen {apps_vhost_port}
# NameVirtualHost *:{apps_vhost_port}
{tmpl_var name='vhost_port_listen'} Listen {tmpl_var name='apps_vhost_port'}
# NameVirtualHost *:{tmpl_var name='apps_vhost_port'}
<VirtualHost {apps_vhost_ip}:{apps_vhost_port}>
<VirtualHost {tmpl_var name='apps_vhost_ip'}:{tmpl_var name='apps_vhost_port'}>
  ServerAdmin webmaster@localhost
  {apps_vhost_servername}
  {tmpl_var name='apps_vhost_servername'}
  
  <FilesMatch "\.ph(p3?|tml)$">
    SetHandler None
  </FilesMatch>
  
  <IfModule mod_php5.c>
    DocumentRoot {apps_vhost_dir}
    DocumentRoot {tmpl_var name='apps_vhost_dir'}
    AddType application/x-httpd-php .php
    <Directory {apps_vhost_dir}>
      # php_admin_value open_basedir "{apps_vhost_dir}:/usr/share:/tmp"
      Options +FollowSymLinks
      AllowOverride None
      Order allow,deny
      Allow from all
    <Directory {tmpl_var name='apps_vhost_dir'}>
        Options FollowSymLinks
        AllowOverride None
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
    </Directory>
  </IfModule>
  
  <IfModule mod_fcgid.c>
    DocumentRoot {apps_vhost_dir}
    DocumentRoot {tmpl_var name='apps_vhost_dir'}
    SuexecUserGroup ispapps ispapps
    <Directory {apps_vhost_dir}>
      Options +Indexes +FollowSymLinks +MultiViews +ExecCGI
      AllowOverride AuthConfig Indexes Limit Options FileInfo
      AddHandler fcgid-script .php
      FCGIWrapper {website_basedir}/php-fcgi-scripts/apps/.php-fcgi-starter .php
      # FcgidBusyTimeout 3600
      Order allow,deny
      Allow from all
    <Directory {tmpl_var name='apps_vhost_dir'}>
        Options +Indexes +FollowSymLinks +MultiViews +ExecCGI
        AllowOverride AuthConfig Indexes Limit Options FileInfo
        AddHandler fcgid-script .php
        FCGIWrapper {tmpl_var name='apps_vhost_basedir'}/php-fcgi-scripts/apps/.php-fcgi-starter .php
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
    </Directory>
  </IfModule>
install/tpl/apache_ispconfig.conf.master
@@ -1,5 +1,4 @@
################################################
# ISPConfig Logfile configuration for vlogger
################################################
@@ -9,46 +8,107 @@
<Directory /var/www/clients>
    AllowOverride None
    Order Deny,Allow
    Deny from all
    <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
    Require all deny
    <tmpl_else>
    Order Deny,Allow
    Deny from all
    </tmpl_if>
</Directory>
# Do not allow access to the root file system of the server for security reasons
<Directory />
       AllowOverride None
       Order Deny,Allow
       Deny from all
    AllowOverride None
    <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
    Require all deny
    <tmpl_else>
    Order Deny,Allow
    Deny from all
    </tmpl_if>
</Directory>
<Directory /var/www/conf>
    AllowOverride None
    Order Deny,Allow
    Deny from all
    <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
    Require all deny
    <tmpl_else>
    Order Deny,Allow
    Deny from all
    </tmpl_if>
</Directory>
# Except of the following directories that contain website scripts
<Directory /usr/share/phpmyadmin>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
<Directory /usr/share/phpMyAdmin>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
<Directory /usr/share/squirrelmail>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
# Allow access to mailman on OpenSuSE
<Directory /usr/lib/mailman/cgi-bin>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
<Directory /usr/lib/mailman/icons>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
<Directory /var/lib/mailman/archives/>
        Options +FollowSymLinks
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
# allow path to awstats and alias for awstats icons
<Directory /usr/share/awstats>
        <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
        Require all granted
        <tmpl_else>
        Order allow,deny
        Allow from all
        </tmpl_if>
</Directory>
Alias /awstats-icon "/usr/share/awstats/icon"
NameVirtualHost *:80
NameVirtualHost *:443
<tmpl_loop name="ip_adresses">
NameVirtualHost {tmpl_var name="ip_address"}:{tmpl_var name="port"}
</tmpl_loop>
install/tpl/apache_ispconfig.vhost.master
@@ -4,10 +4,10 @@
# for the ISPConfig controlpanel
######################################################
{vhost_port_listen} Listen {vhost_port}
NameVirtualHost *:{vhost_port}
<tmpl_var name="vhost_port_listen"> Listen <tmpl_var name="vhost_port">
NameVirtualHost *:<tmpl_var name="vhost_port">
<VirtualHost _default_:{vhost_port}>
<VirtualHost _default_:<tmpl_var name="vhost_port">>
  ServerAdmin webmaster@localhost
  
  <FilesMatch "\.ph(p3?|tml)$">
@@ -22,8 +22,12 @@
      AllowOverride AuthConfig Indexes Limit Options FileInfo
      AddHandler fcgid-script .php
      FCGIWrapper /var/www/php-fcgi-scripts/ispconfig/.php-fcgi-starter .php
      <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
      Require all granted
      <tmpl_else>
      Order allow,deny
      Allow from all
      </tmpl_if>
    </Directory>
    IPCCommTimeout  7200
    MaxRequestLen 15728640
@@ -37,8 +41,12 @@
      # php_admin_value open_basedir "/usr/local/ispconfig/interface:/usr/share:/tmp"
      Options +FollowSymLinks
      AllowOverride None
      <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
      Require all granted
      <tmpl_else>
      Order allow,deny
      Allow from all
      </tmpl_if>
      php_value magic_quotes_gpc        0
    </Directory>
  </IfModule>
@@ -52,22 +60,30 @@
  </IfModule>
  # SSL Configuration
  {ssl_comment}SSLEngine On
  {ssl_comment}SSLCertificateFile /usr/local/ispconfig/interface/ssl/ispserver.crt
  {ssl_comment}SSLCertificateKeyFile /usr/local/ispconfig/interface/ssl/ispserver.key
  {ssl_bundle_comment}SSLCACertificateFile /usr/local/ispconfig/interface/ssl/ispserver.bundle
  <tmpl_var name="ssl_comment">SSLEngine On
  <tmpl_var name="ssl_comment">SSLCertificateFile /usr/local/ispconfig/interface/ssl/ispserver.crt
  <tmpl_var name="ssl_comment">SSLCertificateKeyFile /usr/local/ispconfig/interface/ssl/ispserver.key
  <tmpl_var name="ssl_bundle_comment">SSLCACertificateFile /usr/local/ispconfig/interface/ssl/ispserver.bundle
</VirtualHost>
<Directory /var/www/php-cgi-scripts>
    AllowOverride None
    <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
    Require all denied
    <tmpl_else>
    Order Deny,Allow
    Deny from all
    </tmpl_if>
</Directory>
<Directory /var/www/php-fcgi-scripts>
    AllowOverride None
    <tmpl_if name='apache_version' op='>' value='2.2' format='version'>
    Require all denied
    <tmpl_else>
    Order Deny,Allow
    Deny from all
    </tmpl_if>
</Directory>
install/update.php
@@ -66,6 +66,9 @@
define('ISPC_LOG_FILE', '/var/log/ispconfig_install.log');
define('ISPC_INSTALL_ROOT', realpath(dirname(__FILE__).'/../'));
//** Include the templating lib
require_once 'lib/classes/tpl.inc.php';
//** Check for ISPConfig 2.x versions
if(is_dir('/root/ispconfig') || is_dir('/home/admispconfig')) {
    die('This software cannot be installed on a server wich runs ISPConfig 2.x.');
interface/lib/config.inc.php
@@ -139,6 +139,7 @@
//** Default Language
$conf['language'] = 'en';
$conf['debug_language'] = false;
$conf['language_file_import_enabled'] = true; // Bool value: true / false
//** Default Country
$conf['country'] = 'DE';