2003-10-13 18:48:12 +02:00
< ? php
2008-08-20 08:04:28 +02:00
/**
2018-04-11 15:13:21 +02:00
* EGroupware Setup - Check installation enviroment
2008-08-20 08:04:28 +02:00
*
* @ link http :// www . egroupware . org
* @ package setup
* @ author Miles Lott < milos @ groupwhere . org >
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id $
*/
2016-05-03 00:26:40 +02:00
use EGroupware\Api ;
2008-08-20 08:04:28 +02:00
$run_by_webserver = !! $_SERVER [ 'PHP_SELF' ];
$is_windows = strtoupper ( substr ( PHP_OS , 0 , 3 )) == 'WIN' ;
if ( $run_by_webserver )
{
$safe_er = error_reporting ();
include ( './inc/functions.inc.php' );
error_reporting ( $safe_er );
$GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] = $GLOBALS [ 'egw_setup' ] -> detection -> check_header ();
if ( $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] == '10' )
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
// Check header and authentication
if ( ! $GLOBALS [ 'egw_setup' ] -> auth ( 'Config' ) && ! $GLOBALS [ 'egw_setup' ] -> auth ( 'Header' ))
2004-03-14 11:57:33 +01:00
{
2008-08-20 08:04:28 +02:00
Header ( 'Location: index.php' );
exit ;
2004-03-14 11:57:33 +01:00
}
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
$passed_icon = '<img src="templates/default/images/completed.png" title="Passed" alt="Passed" align="middle" />' ;
$error_icon = '<img src="templates/default/images/incomplete.png" title="Error" alt="Error" align="middle" />' ;
$warning_icon = '<img src="templates/default/images/dep.png" title="Warning" alt="Warning" align="middle" />' ;
}
else
{
$passed_icon = '>>> Passed ' ;
$error_icon = '*** Error: ' ;
$warning_icon = '!!! Warning: ' ;
function lang ( $msg , $arg1 = NULL , $arg2 = NULL , $arg3 = NULL , $arg4 = NULL )
2006-07-09 20:39:01 +02:00
{
2008-08-20 08:04:28 +02:00
return is_null ( $arg1 ) ? $msg : str_replace ( array ( '%1' , '%2' , '%3' , '%4' ), array ( $arg1 , $arg2 , $arg3 , $arg4 ), $msg );
2006-07-09 20:39:01 +02:00
}
2008-08-20 08:04:28 +02:00
}
2010-09-25 09:38:27 +02:00
2008-08-20 08:04:28 +02:00
$checks = array (
'phpversion' => array (
'func' => 'php_version' ,
'value' => $GLOBALS [ 'egw_setup' ] -> required_php_version ,
'verbose_value' => $GLOBALS [ 'egw_setup' ] -> required_php_version . '+' ,
'recommended' => $GLOBALS [ 'egw_setup' ] -> recommended_php_version ,
),
'safe_mode' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
'warning' => lang ( 'safe_mode is turned on, which is generaly a good thing as it makes your install more secure.' ) . " \n " .
2018-04-11 15:13:21 +02:00
lang ( 'If safe_mode is turned on, EGw is not able to change certain settings on runtime, nor can we load any not yet loaded module.' ) . " \n " .
lang ( '*** You have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get EGw fully working !!!' ) . " \n " .
2008-08-20 08:04:28 +02:00
lang ( '*** Do NOT update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your DB in an unrecoverable state (your data is lost) !!!' )
),
'magic_quotes_runtime' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
'safe_mode' => 'magic_quotes_runtime = Off'
),
'register_globals' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
2018-04-11 15:13:21 +02:00
'warning' => lang ( " register_globals is turned On, EGroupware does NOT require it and it's generaly more secure to have it turned Off " )
2008-08-20 08:04:28 +02:00
),
'display_errors' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
'warning' => lang ( '%1 is set to %2. This is NOT recommeded for a production system, as displayed error messages can contain passwords or other sensitive information!' , 'display_errors' , ini_get ( 'display_errors' )),
),
'memory_limit' => array (
'func' => 'php_ini_check' ,
2014-02-22 18:12:24 +01:00
'value' => '128M' ,
2008-08-20 08:04:28 +02:00
'check' => '>=' ,
2018-04-11 15:13:21 +02:00
'error' => lang ( 'memory_limit is set to less than %1: some applications of EGroupware need more than the recommend 8M, expect occasional failures' , '24M' ),
2008-08-20 08:04:28 +02:00
'change' => 'memory_limit = 24M'
),
'max_execution_time' => array (
'func' => 'php_ini_check' ,
'value' => 30 ,
'check' => '>=' ,
2018-04-11 15:13:21 +02:00
'error' => lang ( 'max_execution_time is set to less than 30 (seconds): EGroupware sometimes needs a higher execution_time, expect occasional failures' ),
2008-08-20 08:04:28 +02:00
'safe_mode' => 'max_execution_time = 30'
),
'file_uploads' => array (
'func' => 'php_ini_check' ,
'value' => 1 ,
'verbose_value' => 'On' ,
'error' => lang ( 'File uploads are switched off: You can NOT use any of the filemanagers, nor can you attach files in several applications!' ),
),
'upload_max_filesize' => array (
'func' => 'php_ini_check' ,
'value' => '8M' ,
'check' => '>=' ,
'error' => lang ( '%1 is set to %2, you will NOT be able to upload or attach files bigger then that!' , 'upload_max_filesize' , ini_get ( 'upload_max_filesize' )),
'change' => 'upload_max_filesize = 8M'
),
'post_max_size' => array (
'func' => 'php_ini_check' ,
'value' => '8M' ,
'check' => '>=' ,
'error' => lang ( '%1 is set to %2, you will NOT be able to upload or attach files bigger then that!' , 'post_max_size' , ini_get ( 'max_post_size' )),
'change' => 'post_max_size = 8M'
),
2014-12-15 15:29:56 +01:00
'allow_url_fopen' => array (
'func' => 'php_ini_check' ,
'value' => 1 ,
'verbose_value' => 'On' ,
'error' => lang ( '%1 setting "%2" = %3 disallows access via http!' ,
'php.ini' , 'allow_url_fopen' , array2string ( ini_get ( 'allow_url_fopen' ))),
),
2008-08-20 08:04:28 +02:00
'session' => array (
'func' => 'extension_check' ,
'error' => lang ( 'The session extension is required!' )
),
'include_path' => array (
'func' => 'php_ini_check' ,
'value' => '.' ,
'check' => 'contain' ,
'error' => lang ( 'include_path need to contain "." - the current directory' ),
),
2010-09-29 11:15:29 +02:00
'date.timezone' => array (
'func' => 'php_ini_check' ,
'value' => 'System/Localtime' ,
'verbose_value' => '"System/Localtime"' ,
'check' => '!=' ,
'error' => lang ( 'No VALID timezone set! ("%1" is NOT sufficient, you have to use a timezone identifer like "%2", see %3full list of valid identifers%4)' ,
'System/Localtime' , 'Europe/Berlin' , '<a href="http://www.php.net/manual/en/timezones.php" target="_blank">' , '</a>' ),
),
2008-08-20 08:04:28 +02:00
'pdo' => array (
'func' => 'extension_check' ,
'error' => lang ( 'The PDO extension plus a database specific driver is needed by the VFS (virtual file system)!' ),
),
2016-03-09 07:58:46 +01:00
'mysqli' => array (
2008-08-20 08:04:28 +02:00
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'mysql' , 'MySQL' )
),
'pdo_mysql' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pdo_mysql' , 'MySQL' )
),
'pgsql' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pgsql' , 'pgSQL' )
),
'pdo_pgsql' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pdo_pgsql' , 'pgSQL' )
),
2014-02-22 18:12:24 +01:00
/* disable checks for other database extensions , as we are not really supporting them anymore
2008-08-20 08:04:28 +02:00
'mssql' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'mssql' , 'MsSQL' ),
'win_only' => True
),
'pdo_dblib' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pdo_dblib' , 'MsSQL' ),
'win_only' => True
),
'odbc' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'odbc' , 'MaxDB, MsSQL or Oracle' ),
),
'pdo_odbc' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pdo_odbc' , 'MaxDB, MsSQL or Oracle' ),
),
'oci8' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'oci' , 'Oracle' ),
),
'pdo_oci' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pdo_oci' , 'Oracle' ),
2014-02-22 18:12:24 +01:00
), */
2008-08-20 08:04:28 +02:00
'mbstring' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The mbstring extension is needed to fully support unicode (utf-8) or other multibyte-charsets.' )
),
'ldap' => array (
'func' => 'extension_check' ,
'warning' => lang ( " The ldap extension is needed, if you use ldap as account or contact storage, authenticate against ldap or active directory. It's not needed for a standard SQL installation. " ),
),
'' => array (
2019-06-17 18:11:40 +02:00
'func' => 'dependency_check' ,
'error' => lang ( 'EGroupware requires several dependencies installed via: %1' , 'composer install' ),
2008-08-20 08:04:28 +02:00
),
2009-10-01 11:51:28 +02:00
realpath ( '..' ) => array (
2008-08-20 08:04:28 +02:00
'func' => 'permission_check' ,
'is_world_writable' => False ,
2009-10-01 11:51:28 +02:00
'only_if_exists' => true , // quitens "file does not exist" for doc symlinks in Debian to files outside open_basedir
2008-08-20 08:04:28 +02:00
'recursiv' => True
),
2009-10-01 11:51:28 +02:00
realpath ( '../header.inc.php' ) => array (
2008-08-20 08:04:28 +02:00
'func' => 'permission_check' ,
'is_world_readable' => False ,
'only_if_exists' => @ $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] != 10
),
2009-08-14 11:48:49 +02:00
'ctype' => array (
'func' => 'extension_check' ,
'error' => lang ( " The ctype extension is needed by HTMLpurifier to check content of FCKeditor agains Cross Site Skripting. " ),
),
2010-06-11 15:36:11 +02:00
'json' => array (
'func' => 'extension_check' ,
'error' => lang ( 'The json extension is required by EGroupware for AJAX.' ),
),
2016-06-17 11:17:21 +02:00
'zip' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The zip extension is required for merge-print with office documents.' ),
),
2011-09-06 11:53:28 +02:00
'tidy' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The tidy extension is need in merge-print to clean up html before inserting it in office documents.' ),
),
2018-04-09 16:02:00 +02:00
'xsl' => array (
'func' => 'extension_check' ,
'warning' => lang ( 'The xsl extension is need in merge-print for processing html and office documents.' ),
),
2011-09-06 11:53:28 +02:00
'xmlreader' => array (
'func' => 'extension_check' ,
'error' => lang ( 'The xmlreader extension is required by EGroupware in several applications.' ),
),
2008-08-20 08:04:28 +02:00
);
2009-12-01 14:58:39 +01:00
if ( extension_loaded ( 'session' ) && ini_get ( 'session.save_handler' ) == 'files' && ( $session_path = realpath ( session_save_path ())))
2008-08-20 08:04:28 +02:00
{
2009-12-01 14:58:39 +01:00
$sp_visible = true ;
if (( $open_basedir = ini_get ( 'open_basedir' )) && $open_basedir != 'none' )
{
foreach ( explode ( PATH_SEPARATOR , $open_basedir ) as $dir )
{
$dir = realpath ( $dir );
if (( $sp_visible = substr ( $session_path , 0 , strlen ( $dir )) == $dir )) break ;
}
}
if ( $sp_visible ) // only check if session_save_path is visible by webserver
{
$checks [ $session_path ] = array (
'func' => 'permission_check' ,
'is_writable' => true ,
'msg' => lang ( " Checking if php.ini setting session.save_path='%1' is writable by the webserver " , session_save_path ()),
2018-04-11 15:13:21 +02:00
'error' => lang ( 'You will NOT be able to log into EGroupware using PHP sessions: "session could not be verified" !!!' ),
2009-12-01 14:58:39 +01:00
);
}
2008-08-20 08:04:28 +02:00
}
$setup_info = $GLOBALS [ 'egw_setup' ] -> detection -> get_versions ();
foreach ( $setup_info as $app => $app_data )
{
if ( ! isset ( $app_data [ 'check_install' ])) continue ;
2003-10-13 18:48:12 +02:00
2008-08-20 08:04:28 +02:00
foreach ( $app_data [ 'check_install' ] as $name => $data )
{
if ( isset ( $checks [ $name ]))
2006-06-21 01:00:55 +02:00
{
2008-08-20 08:04:28 +02:00
if ( $checks [ $name ] == $data ) continue ; // identical check --> ignore it
2008-08-05 08:23:52 +02:00
2008-08-20 08:04:28 +02:00
if ( $data [ 'func' ] == 'pear_check' || in_array ( $data [ 'func' ], array ( 'extension_check' , 'php_ini_check' )) && ! isset ( $data [ 'warning' ]))
{
if ( isset ( $checks [ $name ][ 'from' ]) && $checks [ $name ][ 'from' ] && ! is_array ( $checks [ $name ][ 'from' ]))
2006-06-21 01:00:55 +02:00
{
2008-08-20 08:04:28 +02:00
$checks [ $name ][ 'from' ] = array ( $checks [ $name ][ 'from' ]);
2006-06-21 01:00:55 +02:00
}
2008-08-20 08:04:28 +02:00
if ( ! isset ( $data [ 'from' ])) $data [ 'from' ] = $app ;
if ( ! isset ( $checks [ $name ][ 'from' ]) || ! is_array ( $checks [ $name ][ 'from' ])) $checks [ $name ][ 'from' ] = array ();
if ( ! in_array ( $data [ 'from' ], $checks [ $name ][ 'from' ])) $checks [ $name ][ 'from' ][] = $data [ 'from' ];
2006-06-21 01:00:55 +02:00
}
else
{
2008-08-20 08:04:28 +02:00
$checks [ $app . '_' . $name ] = $data ;
2006-06-21 01:00:55 +02:00
}
}
2008-08-20 08:04:28 +02:00
else
2006-06-21 01:00:55 +02:00
{
2008-08-20 08:04:28 +02:00
if ( ! isset ( $data [ 'from' ])) $data [ 'from' ] = $app ;
$checks [ $name ] = $data ;
2006-06-21 01:00:55 +02:00
}
2008-08-20 08:04:28 +02:00
//echo "added check $data[func]($name) for $app"; _debug_array($data);
2006-06-21 01:00:55 +02:00
}
2008-08-20 08:04:28 +02:00
}
2019-06-17 18:11:40 +02:00
// load required extensions from composer.json too:
$composer = json_decode ( file_get_contents ( EGW_SERVER_ROOT . '/composer.json' ), true );
foreach ( $composer [ 'require' ] as $name => $version )
{
if ( substr ( $name , 0 , 4 ) === 'ext-' ) // && !isset($checks[substr($name, 4)]))
{
$name = 'ext-hugo' ;
$checks [ substr ( $name , 4 )] = [
'func' => 'extension_check' ,
'error' => lang ( 'The %1 extension is needed from: %2.' , substr ( $name , 4 ), 'EGroupware' ),
];
}
}
2008-08-20 08:04:28 +02:00
$sorted_checks = array ();
2010-09-25 09:38:27 +02:00
foreach ( array ( 'php_version' , 'php_ini_check' , 'extension_check' , 'pear_check' , 'gd_check' , 'permission_check' ) as $func )
2008-08-20 08:04:28 +02:00
{
foreach ( $checks as $name => $data )
2003-10-13 18:48:12 +02:00
{
2008-08-20 08:04:28 +02:00
if ( $data [ 'func' ] == $func )
{
$sorted_checks [ $name ] = $data ;
unset ( $checks [ $name ]);
}
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
}
if ( $checks ) $sorted_checks += $checks ;
function php_version ( $name , $args )
{
global $passed_icon , $error_icon ;
2014-12-15 10:36:27 +01:00
unset ( $name ); // not used, but required by function signature
2008-08-20 08:04:28 +02:00
$version_ok = version_compare ( phpversion (), $args [ 'value' ]) >= 0 ;
echo '<div>' . ( $version_ok ? $passed_icon : $error_icon ) . ' <span' . ( $version_ok ? '' : ' class="setup_error"' ) . '>' .
lang ( 'Checking required PHP version %1 (recommended %2)' , $args [ 'verbose_value' ], $args [ 'recommended' ]) . ': ' .
phpversion () . ' ==> ' . ( $version_ok ? lang ( 'True' ) : lang ( 'False' )) . " </span></div> \n " ;
}
2015-01-18 13:05:09 +01:00
/**
* Check if given package is installed via composer in EGroupware ' s vendor directory
*
* @ param string $package package - name in composer notation eg . " pear-pear.horde.org/Horde_Imap_Client " or " pear-pear.php.net/Net_Sieve "
*/
function composer_check ( $package )
{
static $installed = null ;
if ( ! isset ( $installed ))
{
$installed = array ();
if ( file_exists ( EGW_SERVER_ROOT . '/vendor' ) && file_exists ( $json = EGW_SERVER_ROOT . '/vendor/composer/installed.json' ))
{
foreach ( json_decode ( file_get_contents ( $json ), true ) as $package_data )
{
$installed [ strtolower ( $package_data [ 'name' ])] = $package_data [ 'version' ];
}
}
}
//error_log(__METHOD__."('$package') returning ".array2string($installed[strtolower($package)]));
return $installed [ strtolower ( $package )];
}
2008-08-20 08:04:28 +02:00
/**
2019-06-17 18:11:40 +02:00
* Check all dependencies from composer . lock are installed
2008-08-20 08:04:28 +02:00
*
2019-06-17 18:11:40 +02:00
* @ param boolean $verbose true : list all packages , false : list only missing packages
2008-08-20 08:04:28 +02:00
*/
2019-06-17 18:11:40 +02:00
function dependency_check ( $verbose = true )
2008-08-20 08:04:28 +02:00
{
2019-06-17 18:11:40 +02:00
global $passed_icon , $warning_icon , $error_icon ;
2005-11-22 19:29:51 +01:00
2019-06-17 18:11:40 +02:00
if ( ! file_exists ( EGW_SERVER_ROOT . '/vendor' ) || ! file_exists ( $json = EGW_SERVER_ROOT . '/vendor/composer/installed.json' ))
2008-08-20 08:04:28 +02:00
{
2019-06-17 18:11:40 +02:00
echo '<div>' . $error_icon . ' <span class="setup_error">' .
lang ( 'No dependencies are installed: you need to run "%1" AND either "%2" OR "%3"!' ,
'cd ' . EGW_SERVER_ROOT , './install-cli.php install' , 'composer install' ) . " </div> \n " ;
return ;
2008-08-20 08:04:28 +02:00
}
2019-06-17 18:11:40 +02:00
$composer_lock = json_decode ( file_get_contents ( EGW_SERVER_ROOT . '/composer.lock' ), true );
$ok = $wrong_version = $missing = 0 ;
foreach ( $composer_lock [ 'packages' ] as $package )
2013-10-29 10:05:16 +01:00
{
2019-06-17 18:11:40 +02:00
$installed = composer_check ( $package [ 'name' ]);
$version_ok = ! empty ( $installed ) && version_compare ( $installed , $package [ 'version' ], '==' );
2007-06-14 20:56:53 +02:00
2019-06-17 18:11:40 +02:00
if ( empty ( $installed ))
2007-01-01 15:33:43 +01:00
{
2019-06-17 18:11:40 +02:00
$missing ++ ;
$icon = $error_icon ;
$class = ' class="setup_error"' ;
2015-01-18 13:05:09 +01:00
}
2019-06-17 18:11:40 +02:00
elseif ( ! $version_ok )
2015-01-18 13:05:09 +01:00
{
2019-06-17 18:11:40 +02:00
$wrong_version ++ ;
$icon = $warning_icon ;
$class = ' class="setup_warning"' ;
2007-01-01 15:33:43 +01:00
}
2019-06-17 18:11:40 +02:00
else
2008-08-20 08:04:28 +02:00
{
2019-06-17 18:11:40 +02:00
$ok ++ ;
$icon = $passed_icon ;
$class = '' ;
2008-08-20 08:04:28 +02:00
}
2008-08-05 08:23:52 +02:00
2019-06-17 18:11:40 +02:00
if ( $verbose || ! $version_ok )
2007-01-01 15:33:43 +01:00
{
2019-06-17 18:11:40 +02:00
echo '<div>' . $icon . ' <span' . $class . '>' .
lang ( 'Checking package %1 is installed' , $package [ 'name' ] . ':' . $package [ 'version' ]) .
': ' . ( empty ( $installed ) ? lang ( 'not installed' ) : $installed ) . " </div> \n " ;
2014-08-27 12:25:17 +02:00
}
2008-08-20 08:04:28 +02:00
}
2019-06-17 18:11:40 +02:00
if ( $ok && ! $verbose )
{
echo '<div>' . $passed_icon . ' <span class="setup_error">' .
lang ( 'Checking dependencies: %1 packages are installed in the required version.' , $ok ) . " </div> \n " ;
}
}
2008-08-05 08:23:52 +02:00
2019-06-17 18:11:40 +02:00
/**
* @ deprecated use composer . json
*/
function pear_check ( $package , $args )
{
unset ( $package , $args );
2008-08-20 08:04:28 +02:00
}
2007-06-14 20:56:53 +02:00
2008-08-20 08:04:28 +02:00
function extension_check ( $name , $args )
{
//echo "<p>extension_check($name,".print_r($args,true).")</p>\n";
2019-06-17 18:11:40 +02:00
global $passed_icon , $warning_icon , $is_windows , $error_icon ;
2008-08-05 08:23:52 +02:00
2008-08-20 08:04:28 +02:00
if ( isset ( $args [ 'win_only' ]) && $args [ 'win_only' ] && ! $is_windows )
{
return True ; // check only under windows
}
// we check for the existens of 'dl', as multithreaded webservers dont have it !!!
2009-04-20 14:43:44 +02:00
$available = check_load_extension ( $name );
2019-06-17 18:11:40 +02:00
$icon = $available ? $passed_icon : ( isset ( $args [ 'error' ]) ? $error_icon : $warning_icon );
$class = $available ? '' : ( isset ( $args [ 'error' ]) ? ' class="setup_error"' : ' class="setup_warning"' );
2008-08-20 08:04:28 +02:00
2019-06-17 18:11:40 +02:00
echo '<div>' . $icon . ' <span' . $class . '>' . lang ( 'Checking extension %1 is loaded or loadable' , $name ) .
': ' . ( $available ? lang ( 'True' ) : lang ( 'False' )) . " </span></div> \n " ;
2007-01-01 15:33:43 +01:00
2008-08-20 08:04:28 +02:00
if ( ! $available )
{
if ( ! isset ( $args [ 'warning' ]))
2005-11-01 08:20:46 +01:00
{
2008-08-20 08:04:28 +02:00
$args [ 'warning' ] = lang ( 'The %1 extension is needed from: %2.' , $name ,
2006-06-21 01:00:55 +02:00
is_array ( $args [ 'from' ]) ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ]);
2005-11-01 08:20:46 +01:00
}
2019-06-17 18:11:40 +02:00
echo " <div class='setup_info'> " . ( isset ( $args [ 'error' ]) ? $args [ 'error' ] : $args [ 'warning' ]) . '</div>' ;
2005-11-01 08:20:46 +01:00
}
2008-08-20 08:04:28 +02:00
echo " \n " ;
2005-11-01 08:20:46 +01:00
2008-08-20 08:04:28 +02:00
return $available ;
}
2004-02-03 07:21:25 +01:00
2008-08-20 08:04:28 +02:00
function function_check ( $name , $args )
{
2014-12-15 10:36:27 +01:00
global $passed_icon , $warning_icon ;
2008-08-20 08:04:28 +02:00
$available = function_exists ( $name );
2004-02-03 07:21:25 +01:00
2008-08-20 08:04:28 +02:00
echo '<div>' . ( $available ? $passed_icon : $warning_icon ) . ' <span' . ( $available ? '' : ' class="setup_warning"' ) . '>' . lang ( 'Checking function %1 exists' , $name ) . ': ' . ( $available ? lang ( 'True' ) : lang ( 'False' )) . " </span></div> \n " ;
2004-02-03 07:21:25 +01:00
2008-08-20 08:04:28 +02:00
if ( ! $available )
{
if ( ! isset ( $args [ 'warning' ]))
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
$args [ 'warning' ] = lang ( 'The function %1 is needed from: %2.' , $name ,
is_array ( $args [ 'from' ] ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ]));
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
echo " <div class='setup_info'> " . $args [ 'warning' ] . '</div>' ;
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
echo " \n " ;
2003-10-13 18:48:12 +02:00
2008-08-20 08:04:28 +02:00
return $available ;
}
2006-11-07 07:32:00 +01:00
2008-08-20 08:04:28 +02:00
function verbosePerms ( $in_Perms )
{
if ( $in_Perms & 0x1000 ) // FIFO pipe
{
$sP = 'p' ;
}
elseif ( $in_Perms & 0x2000 ) // Character special
{
$sP = 'c' ;
}
elseif ( $in_Perms & 0x4000 ) // Directory
{
$sP = 'd' ;
}
elseif ( $in_Perms & 0x6000 ) // Block special
{
$sP = 'b' ;
}
elseif ( $in_Perms & 0x8000 ) // Regular
{
$sP = '-' ;
}
elseif ( $in_Perms & 0xA000 ) // Symbolic Link
{
$sP = 'l' ;
}
elseif ( $in_Perms & 0xC000 ) // Socket
{
$sP = 's' ;
}
else // UNKNOWN
{
$sP = 'u' ;
}
2006-11-07 07:32:00 +01:00
2008-08-20 08:04:28 +02:00
// owner
$sP .= (( $in_Perms & 0x0100 ) ? 'r' : '-' ) .
(( $in_Perms & 0x0080 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0040 ) ? (( $in_Perms & 0x0800 ) ? 's' : 'x' ) :
(( $in_Perms & 0x0800 ) ? 'S' : '-' ));
// group
$sP .= (( $in_Perms & 0x0020 ) ? 'r' : '-' ) .
(( $in_Perms & 0x0010 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0008 ) ? (( $in_Perms & 0x0400 ) ? 's' : 'x' ) :
(( $in_Perms & 0x0400 ) ? 'S' : '-' ));
// world
$sP .= (( $in_Perms & 0x0004 ) ? 'r' : '-' ) .
(( $in_Perms & 0x0002 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0001 ) ? (( $in_Perms & 0x0200 ) ? 't' : 'x' ) :
(( $in_Perms & 0x0200 ) ? 'T' : '-' ));
return $sP ;
}
function permission_check ( $name , $args , $verbose = True )
{
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
//echo "<p>permision_check('$name',".print_r($args,True).",'$verbose')</p>\n";
// add a ../ for non-absolute pathes
$rel_name = $name ;
2009-04-28 21:25:35 +02:00
if ( $name && substr ( $name , 0 , 3 ) != '../' && $name [ 0 ] != '/' && $name [ 0 ] != '\\' && strpos ( $name , ':' ) === false )
2008-08-20 08:04:28 +02:00
{
$name = '../' . $name ;
}
2009-10-01 11:51:28 +02:00
2008-08-20 08:04:28 +02:00
if ( ! file_exists ( $name ) && isset ( $args [ 'only_if_exists' ]) && $args [ 'only_if_exists' ])
{
return True ;
}
2006-11-07 07:32:00 +01:00
2008-08-20 08:04:28 +02:00
$perms = $checks = '' ;
if ( file_exists ( $name ))
{
$owner = function_exists ( 'posix_getpwuid' ) ? posix_getpwuid ( @ fileowner ( $name )) : array ( 'name' => 'nn' );
$group = function_exists ( 'posix_getgrgid' ) ? posix_getgrgid ( @ filegroup ( $name )) : array ( 'name' => 'nn' );
$perms = " $owner[name] / $group[name] " . verbosePerms ( @ fileperms ( $name ));
}
2006-11-07 07:32:00 +01:00
2008-08-20 08:04:28 +02:00
$checks = array ();
if ( isset ( $args [ 'is_readable' ]))
{
$checks [] = lang ( 'readable by the webserver' );
$check_not = ( ! $args [ 'is_readable' ] ? lang ( 'not' ) : '' );
}
if ( isset ( $args [ 'is_writable' ]))
{
$checks [] = lang ( 'writable by the webserver' );
$check_not = ( ! $args [ 'is_writable' ] ? lang ( 'not' ) : '' );
}
if ( isset ( $args [ 'is_world_readable' ]))
{
$checks [] = lang ( 'world readable' );
$check_not = ( ! $args [ 'is_world_readable' ] ? lang ( 'not' ) : '' );
2006-11-07 07:32:00 +01:00
}
2008-08-20 08:04:28 +02:00
if ( isset ( $args [ 'is_world_writable' ]))
{
$checks [] = lang ( 'world writable' );
$check_not = ( ! $args [ 'is_world_writable' ] ? lang ( 'not' ) : '' );
}
2006-11-07 07:32:00 +01:00
2008-08-20 08:04:28 +02:00
if ( isset ( $args [ 'msg' ]) && ( $msg = $args [ 'msg' ]))
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
$msg .= ': ' . $perms . " <br /> \n " ;
}
else
{
2014-12-15 10:36:27 +01:00
$msg = lang ( 'Checking file-permissions of %1 for %2 %3: %4' , $rel_name , $check_not , implode ( ', ' , $checks ), $perms ) . " <br /> \n " ;
2008-08-20 08:04:28 +02:00
}
$extra_error_msg = '' ;
if ( isset ( $args [ 'error' ]) && $args [ 'error' ])
{
$extra_error_msg = " <br /> \n " . $args [ 'error' ];
}
if ( ! file_exists ( $name ))
{
echo '<div>' . $error_icon . '<span class="setup_error">' . $msg . lang ( '%1 does not exist !!!' , $rel_name ) . $extra_error_msg . " </span></div> \n " ;
return False ;
}
$warning = False ;
if ( ! $GLOBALS [ 'run_by_webserver' ] && ( @ $args [ 'is_readable' ] || @ $args [ 'is_writable' ]))
{
echo $warning_icon . ' ' . $msg . lang ( 'Check can only be performed, if called via a webserver, as the user-id/-name of the webserver is not known.' ) . " \n " ;
unset ( $args [ 'is_readable' ]);
unset ( $args [ 'is_writable' ]);
$warning = True ;
}
$Ok = True ;
if ( isset ( $args [ 'is_writable' ]) && is_writable ( $name ) != $args [ 'is_writable' ])
{
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . ' ' . lang ( '%1 is %2%3 !!!' , $rel_name , $args [ 'is_writable' ] ? lang ( 'not' ) . ' ' : '' , lang ( 'writable by the webserver' )) . $extra_error_msg . " </span></div> \n " ;
$Ok = False ;
}
if ( isset ( $args [ 'is_readable' ]) && is_readable ( $name ) != $args [ 'is_readable' ])
{
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . ' ' . lang ( '%1 is %2%3 !!!' , $rel_name , $args [ 'is_readable' ] ? lang ( 'not' ) . ' ' : '' , lang ( 'readable by the webserver' )) . $extra_error_msg . " </span></div> \n " ;
$Ok = False ;
}
if ( ! $is_windows && isset ( $args [ 'is_world_readable' ]) && ! ( fileperms ( $name ) & 04 ) == $args [ 'is_world_readable' ])
{
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . ' ' . lang ( '%1 is %2%3 !!!' , $rel_name , $args [ 'is_world_readable' ] ? lang ( 'not' ) . ' ' : '' , lang ( 'world readable' )) . $extra_error_msg . " </span></div> \n " ;
$Ok = False ;
}
if ( ! $is_windows && isset ( $args [ 'is_world_writable' ]) && ! ( fileperms ( $name ) & 02 ) == $args [ 'is_world_writable' ])
{
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . ' ' . lang ( '%1 is %2%3 !!!' , $rel_name , $args [ 'is_world_writable' ] ? lang ( 'not' ) . ' ' : '' , lang ( 'world writable' )) . $extra_error_msg . " </span></div> \n " ;
$Ok = False ;
}
if ( $Ok && ! $warning && $verbose )
{
echo $passed_icon . ' ' . $msg ;
}
if ( $Ok && @ $args [ 'recursiv' ] && is_dir ( $name ))
{
if ( $verbose )
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
@ set_time_limit ( 0 );
echo " <div class='setup_info'> " . lang ( 'This might take a while, please wait ...' ) . " </div> \n " ;
flush ();
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
@ set_time_limit ( 0 );
$handle = @ opendir ( $name );
while ( $handle && ( $file = readdir ( $handle )))
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
if ( $file != '.' && $file != '..' )
{
$Ok = $Ok && permission_check (( $name != '.' ? $name . '/' : '' ) . $file , $args , False );
}
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
if ( $handle ) closedir ( $handle );
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
if ( $verbose ) echo " \n " ;
2003-10-13 18:48:12 +02:00
2008-08-20 08:04:28 +02:00
return $Ok ;
}
2003-10-13 18:48:12 +02:00
2008-08-20 08:04:28 +02:00
function mk_value ( $value )
{
2014-12-15 10:36:27 +01:00
$matches = null ;
2008-08-20 08:04:28 +02:00
if ( ! preg_match ( '/^([0-9]+)([mk]+)$/i' , $value , $matches )) return $value ;
2004-02-03 07:21:25 +01:00
2008-08-20 08:04:28 +02:00
return ( strtolower ( $matches [ 2 ]) == 'm' ? 1024 * 1024 : 1024 ) * ( int ) $matches [ 1 ];
}
2004-03-23 18:02:34 +01:00
2008-08-20 08:04:28 +02:00
function php_ini_check ( $name , $args )
{
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
2004-03-23 18:02:34 +01:00
2008-08-20 08:04:28 +02:00
$safe_mode = ini_get ( 'safe_mode' );
2004-03-22 00:45:28 +01:00
2008-08-20 08:04:28 +02:00
$ini_value = ini_get ( $name );
$check = isset ( $args [ 'check' ]) ? $args [ 'check' ] : '=' ;
$verbose_value = isset ( $args [ 'verbose_value' ]) ? $args [ 'verbose_value' ] : $args [ 'value' ];
$ini_value_verbose = '' ;
if ( $verbose_value == 'On' || $verbose_value == 'Off' )
{
$ini_value_verbose = ' = ' . ( $ini_value ? 'On' : 'Off' );
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
switch ( $check )
2004-08-17 19:08:35 +02:00
{
2008-08-20 08:04:28 +02:00
case 'not set' :
$check = lang ( 'not set' );
$result = ! ( $ini_value & $args [ 'value' ]);
break ;
case 'set' :
$check = lang ( 'set' );
$result = !! ( $ini_value & $args [ 'value' ]);
break ;
case '>=' :
$result = ! $ini_value || // value not used, eg. no memory limit
( int ) mk_value ( $ini_value ) >= ( int ) mk_value ( $args [ 'value' ]);
break ;
case 'contain' :
$check = lang ( 'contain' );
2010-09-27 16:28:36 +02:00
$sep = $is_windows ? '/[; ]+/' : '/[: ]+/' ;
$result = in_array ( $args [ 'value' ], preg_split ( $sep , $ini_value ));
2008-08-20 08:04:28 +02:00
break ;
2010-09-29 11:15:29 +02:00
case '!=' :
$check = lang ( 'set and not' );
$result = ! empty ( $ini_value ) && $ini_value != $args [ 'value' ];
break ;
2008-08-20 08:04:28 +02:00
case '=' :
default :
$result = $ini_value == $args [ 'value' ];
break ;
2004-08-17 19:08:35 +02:00
}
2010-09-29 11:15:29 +02:00
if ( $name == 'date.timezone' )
{
try {
$tz = new DateTimeZone ( $ini_value );
unset ( $tz );
}
catch ( Exception $e ) {
2014-12-15 10:36:27 +01:00
unset ( $e );
2010-09-29 11:15:29 +02:00
$result = false ; // no valid timezone
}
}
2008-08-20 08:04:28 +02:00
$msg = ' ' . lang ( 'Checking php.ini' ) . " : $name $check $verbose_value : <span class='setup_info'>ini_get(' $name ')=' $ini_value ' $ini_value_verbose </span> " ;
2008-08-05 08:23:52 +02:00
2008-08-20 08:04:28 +02:00
if ( $result )
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
echo " <div> " . $passed_icon . $msg . " </div> \n " ;
}
if ( ! $result )
{
if ( isset ( $args [ 'error' ]))
2003-10-13 18:48:12 +02:00
{
2008-08-20 08:04:28 +02:00
echo " <div> " . $error_icon . ' <span class="setup_error">' . $msg . '</span><div class="setup_info">' . $args [ 'error' ] . " </div></div> \n " ;
2003-11-03 21:56:15 +01:00
}
2008-08-20 08:04:28 +02:00
elseif ( isset ( $args [ 'warning' ]))
2003-11-03 21:56:15 +01:00
{
2008-08-20 08:04:28 +02:00
echo " <div> " . $warning_icon . ' <span class="setup_warning">' . $msg . '</span><div class="setup_info">' . $args [ 'warning' ] . " </div></div> \n " ;
2003-10-13 18:48:12 +02:00
}
2008-08-20 08:04:28 +02:00
elseif ( ! isset ( $args [ 'safe_mode' ]))
2004-03-14 11:57:33 +01:00
{
2008-08-20 08:04:28 +02:00
echo " <div> " . $warning_icon . ' <span class="setup_warning">' . $msg . '</span><div class="setup_info">' .
lang ( '%1 is needed by: %2.' , $name , is_array ( $args [ 'from' ]) ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ])
. " </div></div> \n " ;
2004-03-14 11:57:33 +01:00
}
2008-08-20 08:04:28 +02:00
if ( isset ( $args [ 'safe_mode' ]) && $safe_mode || @ $args [ 'change' ])
2003-10-13 18:48:12 +02:00
{
2008-08-20 08:04:28 +02:00
if ( ! isset ( $args [ 'warning' ]) && ! isset ( $args [ 'error' ]))
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . '</span></div>' ;
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
echo " <div class='setup_error'> \n " ;
echo '*** ' . lang ( 'Please make the following change in your php.ini' ) . ' (' . get_php_ini () . '): ' . ( @ $args [ 'safe_mode' ] ? $args [ 'safe_mode' ] : $args [ 'change' ]) . " <br /> \n " ;
echo '*** ' . lang ( 'AND reload your webserver, so the above changes take effect !!!' ) . " </div> \n " ;
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
return $result ;
}
2003-10-13 18:48:12 +02:00
2008-08-20 08:04:28 +02:00
function get_php_ini ()
{
ob_start ();
phpinfo ( INFO_GENERAL );
$phpinfo = ob_get_contents ();
ob_end_clean ();
2004-05-04 09:41:02 +02:00
2014-12-15 10:36:27 +01:00
$found = null ;
2008-08-20 08:04:28 +02:00
return preg_match ( '/\(php.ini\).*<\/td><td[^>]*>([^ <]+)/' , $phpinfo , $found ) ? $found [ 1 ] : False ;
}
2004-05-04 09:41:02 +02:00
2008-08-20 08:04:28 +02:00
function gd_check ()
{
global $passed_icon , $warning_icon ;
2005-11-01 08:20:46 +01:00
2008-08-20 08:04:28 +02:00
$available = ( function_exists ( 'imagecopyresampled' ) || function_exists ( 'imagecopyresized' ));
2008-08-05 08:23:52 +02:00
2008-08-20 08:04:28 +02:00
echo " <div> " . ( $available ? $passed_icon : $warning_icon ) . ' <span' . ( $available ? '' : ' class="setup_warning"' ) . '>' . lang ( 'Checking for GD support...' ) . ': ' . ( $available ? lang ( 'True' ) : lang ( 'False' )) . " </span></div> \n " ;
2008-08-05 08:23:52 +02:00
2008-08-20 08:04:28 +02:00
if ( ! $available )
2004-02-03 07:21:25 +01:00
{
2008-08-20 08:04:28 +02:00
echo lang ( 'Your PHP installation does not have appropriate GD support. You need gd library version 1.8 or newer to see Gantt charts in projects.' ) . " \n " ;
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
return $available ;
}
if ( $run_by_webserver )
{
$tpl_root = $GLOBALS [ 'egw_setup' ] -> html -> setup_tpl_dir ( 'setup' );
2016-05-03 00:26:40 +02:00
$setup_tpl = new Api\Framework\Template ( $tpl_root );
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_file ( array (
'T_head' => 'head.tpl' ,
'T_footer' => 'footer.tpl' ,
));
2016-05-03 00:26:40 +02:00
$ConfigDomain = $_REQUEST [ 'ConfigDomain' ];
2008-08-20 08:04:28 +02:00
if ( @ $_GET [ 'intro' ]) {
2010-02-13 03:57:22 +01:00
if (( $ConfigLang = setup :: get_lang ()))
2008-08-20 08:04:28 +02:00
{
$GLOBALS [ 'egw_setup' ] -> set_cookie ( 'ConfigLang' , $ConfigLang ,( int ) ( time () + ( 1200 * 9 )), '/' );
}
2018-04-11 15:13:21 +02:00
$GLOBALS [ 'egw_setup' ] -> html -> show_header ( lang ( 'Welcome to the EGroupware Installation' ), False , 'config' );
echo '<h1>' . lang ( 'Welcome to the EGroupware Installation' ) . " </h1> \n " ;
2008-08-20 08:04:28 +02:00
if ( ! $ConfigLang )
{
2011-02-03 03:01:48 +01:00
echo '<p><form action="check_install.php?intro=1" method="Post">Please Select your language ' . setup_html :: lang_select ( True , 'en' ) . " </form></p> \n " ;
2008-08-20 08:04:28 +02:00
}
2018-04-11 15:13:21 +02:00
echo '<p>' . lang ( 'The first step in installing EGroupware is to ensure your environment has the necessary settings to correctly run the application.' ) . '</p>' ;
2008-08-20 08:04:28 +02:00
echo '<p>' . lang ( 'We will now run a series of tests, which may take a few minutes. Click the link below to proceed.' ) . '</p>' ;
echo '<h3><a href="check_install.php">' . lang ( 'Run installation tests' ) . '</a></h3>' ;
echo '<p><a href="manageheader.php">' . lang ( 'Skip the installation tests (not recommended)' ) . " </a></p> \n " ;
$setup_tpl -> pparse ( 'out' , 'T_footer' );
exit ;
} else {
2018-04-11 15:13:21 +02:00
$GLOBALS [ 'egw_setup' ] -> html -> show_header ( lang ( 'Checking the EGroupware Installation' ), False , 'config' , $ConfigDomain ? $ConfigDomain . '(' . @ $GLOBALS [ 'egw_domain' ][ $ConfigDomain ][ 'db_type' ] . ')' : '' );
echo '<h1>' . lang ( 'Checking the EGroupware Installation' ) . " </h1> \n " ;
2008-08-20 08:04:28 +02:00
# echo "<pre style=\"text-align: left;\">\n";;
2004-02-03 07:21:25 +01:00
}
2008-08-20 08:04:28 +02:00
}
else
{
2018-04-11 15:13:21 +02:00
echo " Checking the EGroupware Installation \n " ;
2008-08-20 08:04:28 +02:00
echo " ==================================== \n \n " ;
}
$Ok = True ;
2014-12-15 10:36:27 +01:00
foreach ( $sorted_checks as $name => $args )
2008-08-20 08:04:28 +02:00
{
$check_ok = $args [ 'func' ]( $name , $args );
$Ok = $Ok && $check_ok ;
}
if ( $run_by_webserver )
{
# echo "</pre>\n";;
if ( $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] != 10 )
2003-10-13 18:48:12 +02:00
{
2008-08-20 08:04:28 +02:00
if ( ! $Ok )
2003-10-13 18:48:12 +02:00
{
2008-08-20 08:04:28 +02:00
echo '<h3>' . lang ( 'Please fix the above errors (%1) and warnings(%2)' , $error_icon , $warning_icon ) . " </h3> \n " ;
echo '<h3><a href="check_install.php">' . lang ( 'Click here to re-run the installation tests' ) . " </a></h3> \n " ;
echo '<h3>' . lang ( 'or %1Continue to the Header Admin%2' , '<a href="manageheader.php">' , '</a>' ) . " </h3> \n " ;
2003-10-13 18:48:12 +02:00
}
else
{
2008-08-20 08:04:28 +02:00
echo '<h3><a href="manageheader.php">' . lang ( 'Continue to the Header Admin' ) . " </a></h3> \n " ;
2003-10-13 18:48:12 +02:00
}
}
2008-08-20 08:04:28 +02:00
else
{
echo '<h3>' ;
if ( ! $Ok )
{
echo lang ( 'Please fix the above errors (%1) and warnings(%2)' , $error_icon , $warning_icon ) . '. ' ;
}
2010-09-17 19:25:44 +02:00
echo '<br /><a href="' . str_replace ( 'check_install.php' , '' , @ $_SERVER [ 'HTTP_REFERER' ]) . '">' . lang ( 'Return to Setup' ) . " </a></h3> \n " ;
2008-08-20 08:04:28 +02:00
}
$setup_tpl -> pparse ( 'out' , 'T_footer' );
//echo "</body>\n</html>\n";
}