2003-10-13 18:48:12 +02:00
< ? php
/************************************************************************** \
2004-01-27 21:49:25 +01:00
* eGroupWare - Setup Check Installation *
2003-10-13 18:48:12 +02:00
* http :// www . eGroupWare . org *
* -------------------------------------------- *
* This program is free software ; you can redistribute it and / or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation ; either version 2 of the License , or ( at your *
* option ) any later version . *
\ **************************************************************************/
/* $Id$ */
2007-06-14 20:56:53 +02:00
@ set_time_limit ( 0 );
2004-02-03 07:21:25 +01:00
$run_by_webserver = !! $_SERVER [ 'PHP_SELF' ];
2004-03-14 11:57:33 +01:00
$is_windows = strtoupper ( substr ( PHP_OS , 0 , 3 )) == 'WIN' ;
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
if ( $run_by_webserver )
2003-10-13 18:48:12 +02:00
{
2005-03-04 13:40:28 +01:00
$GLOBALS [ 'egw_info' ] = array (
'flags' => array (
'noheader' => True ,
'nonavbar' => True ,
'currentapp' => 'home' ,
'noapi' => True
));
2004-03-09 22:05:28 +01:00
$safe_er = error_reporting ();
2004-02-03 07:21:25 +01:00
include ( './inc/functions.inc.php' );
2004-03-09 22:05:28 +01:00
error_reporting ( $safe_er );
2004-02-03 07:21:25 +01:00
2005-03-04 13:40:28 +01:00
$GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] = $GLOBALS [ 'egw_setup' ] -> detection -> check_header ();
if ( $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] == '10' )
2003-10-13 18:48:12 +02:00
{
2004-02-03 07:21:25 +01:00
// Check header and authentication
2005-03-04 13:40:28 +01:00
if ( ! $GLOBALS [ 'egw_setup' ] -> auth ( 'Config' ) && ! $GLOBALS [ 'egw_setup' ] -> auth ( 'Header' ))
2004-02-03 07:21:25 +01:00
{
Header ( 'Location: index.php' );
exit ;
}
2003-10-13 18:48:12 +02:00
}
2005-07-11 20:02:19 +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" />' ;
2004-02-03 07:21:25 +01:00
}
else
{
2004-03-14 11:57:33 +01:00
$passed_icon = '>>> Passed ' ;
2004-02-03 07:21:25 +01:00
$error_icon = '*** Error: ' ;
$warning_icon = '!!! Warning: ' ;
2004-03-14 11:57:33 +01:00
function lang ( $msg , $arg1 = NULL , $arg2 = NULL , $arg3 = NULL , $arg4 = NULL )
{
return is_null ( $arg1 ) ? $msg : str_replace ( array ( '%1' , '%2' , '%3' , '%4' ), array ( $arg1 , $arg2 , $arg3 , $arg4 ), $msg );
}
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
$checks = array (
2005-11-22 19:29:51 +01:00
'phpversion' => array (
'func' => 'php_version' ,
2006-06-21 01:00:55 +02:00
'value' => $GLOBALS [ 'egw_setup' ] -> required_php_version ,
'verbose_value' => $GLOBALS [ 'egw_setup' ] -> required_php_version . '+' ,
'recommended' => $GLOBALS [ 'egw_setup' ] -> recommended_php_version ,
2005-11-22 19:29:51 +01:00
),
2004-02-03 07:21:25 +01:00
'safe_mode' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
2004-03-14 11:57:33 +01:00
'warning' => lang ( 'safe_mode is turned on, which is generaly a good thing as it makes your install more secure.' ) . " \n " .
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 " .
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) !!!' )
2004-02-03 07:21:25 +01:00
),
'magic_quotes_runtime' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
2004-08-17 19:08:35 +02:00
'safe_mode' => 'magic_quotes_runtime = Off'
2004-02-03 07:21:25 +01:00
),
'register_globals' => array (
'func' => 'php_ini_check' ,
'value' => 0 ,
'verbose_value' => 'Off' ,
2004-03-14 11:57:33 +01:00
'warning' => lang ( " register_globals is turned On, eGroupWare does NOT require it and it's generaly more secure to have it turned Off " )
2004-02-03 07:21:25 +01:00
),
'memory_limit' => array (
'func' => 'php_ini_check' ,
2007-08-31 08:59:32 +02:00
'value' => '24M' ,
2004-02-03 07:21:25 +01:00
'check' => '>=' ,
2007-08-31 08:59:32 +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' ),
'change' => 'memory_limit = 24M'
2004-02-03 07:21:25 +01:00
),
'max_execution_time' => array (
'func' => 'php_ini_check' ,
'value' => 30 ,
'check' => '>=' ,
2004-03-14 11:57:33 +01:00
'error' => lang ( 'max_execution_time is set to less than 30 (seconds): eGroupWare sometimes needs a higher execution_time, expect occasional failures' ),
'safe_mode' => 'max_execution_time = 30'
),
2005-11-01 08:20:46 +01:00
'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!' ),
),
2004-03-14 11:57:33 +01:00
'include_path' => array (
'func' => 'php_ini_check' ,
'value' => '.' ,
'check' => 'contain' ,
'error' => lang ( 'include_path need to contain "." - the current directory' ),
2004-02-03 07:21:25 +01:00
),
'mysql' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'mysql' , 'MySQL' )
2004-02-03 07:21:25 +01:00
),
'pgsql' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'pgsql' , 'pgSQL' )
2004-02-03 07:21:25 +01:00
),
'mssql' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'mssql' , 'MsSQL' ),
2004-02-03 07:21:25 +01:00
'win_only' => True
),
2004-08-14 17:02:24 +02:00
'odbc' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'odbc' , 'MaxDB, MsSQL or Oracle' ),
2005-02-25 08:45:37 +01:00
),
'oci8' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The %1 extension is needed, if you plan to use a %2 database.' , 'oci' , 'Oracle' ),
2004-08-14 17:02:24 +02:00
),
2004-02-03 07:21:25 +01:00
'mbstring' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The mbstring extension is needed to fully support unicode (utf-8) or other multibyte-charsets.' )
2004-08-17 19:08:35 +02:00
),
'mbstring.func_overload' => array (
'func' => 'php_ini_check' ,
'value' => 7 ,
2005-07-11 20:02:19 +02:00
'warning' => '<div class="setup_info">' . lang ( 'The mbstring.func_overload = 7 is needed to fully support unicode (utf-8) or other multibyte-charsets.' ) . " </div> " ,
2004-08-17 19:08:35 +02:00
'change' => extension_loaded ( 'mbstring' ) || function_exists ( 'dl' ) && @ dl ( PHP_SHLIB_PREFIX . 'mbstring.' . PHP_SHLIB_SUFFIX ) ? 'mbstring.func_overload = 7' : '' ,
2004-02-03 07:21:25 +01:00
),
2005-02-21 09:01:33 +01:00
'session' => array (
'func' => 'extension_check' ,
2006-06-21 01:00:55 +02:00
'warning' => lang ( 'The session extension is needed to use php sessions (db-sessions work without).' )
2006-07-09 20:39:01 +02:00
),
2007-08-31 08:49:17 +02:00
'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. " ),
),
2004-02-03 07:21:25 +01:00
'.' => array (
'func' => 'permission_check' ,
'is_world_writable' => False ,
'recursiv' => True
),
'header.inc.php' => array (
'func' => 'permission_check' ,
'is_world_readable' => False ,
2005-03-04 13:40:28 +01:00
'only_if_exists' => @ $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] != 10
2004-02-03 07:21:25 +01:00
),
);
2007-11-27 01:36:25 +01:00
if ( extension_loaded ( 'session' ) && ini_get ( 'session.save_handler' ) == 'files' )
2006-07-09 20:39:01 +02:00
{
$checks [ session_save_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 ()),
'error' => lang ( 'You will NOT be able to log into eGroupWare using PHP sessions: "session could not be verified" !!!' ),
);
}
2006-06-21 01:00:55 +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
2006-06-21 01:00:55 +02:00
foreach ( $app_data [ 'check_install' ] as $name => $data )
{
if ( isset ( $checks [ $name ]))
{
if ( $checks [ $name ] == $data ) continue ; // identical check --> ignore it
2007-07-12 07:47:21 +02:00
if ( $data [ 'func' ] == 'pear_check' || in_array ( $data [ 'func' ], array ( 'extension_check' , 'php_ini_check' )) && ! isset ( $data [ 'warning' ]))
2006-06-21 01:00:55 +02:00
{
if ( $checks [ $name ][ 'from' ] && ! is_array ( $checks [ $name ][ 'from' ]))
{
$checks [ $name ][ 'from' ] = array ( $checks [ $name ][ 'from' ]);
}
2007-07-12 07:47:21 +02:00
if ( ! isset ( $data [ 'from' ])) $data [ 'from' ] = $app ;
2007-08-31 08:49:17 +02:00
if ( ! isset ( $checks [ $name ][ 'from' ]) || ! is_array ( $checks [ $name ][ 'from' ])) $checks [ $name ][ 'from' ] = array ();
2007-07-12 07:47:21 +02:00
if ( ! in_array ( $data [ 'from' ], $checks [ $name ][ 'from' ])) $checks [ $name ][ 'from' ][] = $data [ 'from' ];
2006-06-21 01:00:55 +02:00
}
else
{
$checks [ $app . '_' . $name ] = $data ;
}
}
else
{
2007-07-12 07:47:21 +02:00
if ( ! isset ( $data [ 'from' ])) $data [ 'from' ] = $app ;
2006-06-21 01:00:55 +02:00
$checks [ $name ] = $data ;
}
//echo "added check $data[func]($name) for $app"; _debug_array($data);
}
}
$sorted_checks = array ();
foreach ( array ( 'php_version' , 'php_ini_check' , 'extension_check' , 'pear_check' , 'gd_check' , 'permission_check' ) as $func )
{
foreach ( $checks as $name => $data )
{
if ( $data [ 'func' ] == $func )
{
$sorted_checks [ $name ] = $data ;
unset ( $checks [ $name ]);
}
}
}
if ( $checks ) $sorted_checks += $checks ;
$checks =& $sorted_checks ;
2004-08-17 19:08:35 +02:00
// some constants for pre php4.3
2004-02-03 07:21:25 +01:00
if ( ! defined ( 'PHP_SHLIB_SUFFIX' ))
2003-10-13 18:48:12 +02:00
{
2004-03-14 11:57:33 +01:00
define ( 'PHP_SHLIB_SUFFIX' , $is_windows ? 'dll' : 'so' );
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
if ( ! defined ( 'PHP_SHLIB_PREFIX' ))
2003-10-13 18:48:12 +02:00
{
2004-02-03 07:21:25 +01:00
define ( 'PHP_SHLIB_PREFIX' , PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '' );
2003-11-03 21:56:15 +01:00
}
2005-11-22 19:29:51 +01:00
function php_version ( $name , $args )
{
global $passed_icon , $error_icon ;
2007-01-01 15:33:43 +01:00
$version_ok = version_compare ( phpversion (), $args [ 'value' ]) >= 0 ;
2005-11-22 19:29:51 +01:00
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 " ;
}
2004-02-03 07:21:25 +01:00
2007-01-01 15:33:43 +01:00
/**
* quering the pear registry to find out which pear packages and versions are installed
*
* @ return array with package - name => version pairs , eg . array ( 'Log' => '1.9.8' , 'PEAR' => '1.4.11' )
*/
function get_installed_pear_packages ()
{
$pear_config = '' ; // use the system default
// fix for SuSE having the pear.conf only for cli, will fail with open_basedir - no idea what to do then
if ( @ is_dir ( '/etc/php5/apache2' ) && ! file_exists ( '/etc/php5/apache2/pear.conf' ) && @ file_exists ( '/etc/php5/cli/pear.conf' ))
{
$pear_config = '/etc/php5/cli/pear.conf' ;
}
2007-05-28 13:46:47 +02:00
@ include_once 'PEAR/Config.php' ;
2007-01-01 15:33:43 +01:00
if ( ! class_exists ( 'PEAR_Config' )) return false ;
$config = new PEAR_Config ( '' , $pear_config );
2007-06-14 20:56:53 +02:00
//echo "<pre>config = ".print_r($config,true)."</pre>\n";
2007-01-01 15:33:43 +01:00
$channel = $config -> get ( 'default_channel' );
2007-06-14 20:56:53 +02:00
//echo "<pre>channel = ".print_r($channel,true)."</pre>\n";
2007-01-01 15:33:43 +01:00
2007-04-26 08:17:41 +02:00
if ( ! method_exists ( $config , 'getRegistry' )) return false ; // PEAR version to old
2007-01-01 15:33:43 +01:00
$reg = & $config -> getRegistry ();
2007-06-14 20:56:53 +02:00
//echo "<pre>reg = ".print_r($reg,true)."</pre>\n";
// a bug in pear causes an endless loop if the install-dir does not exist
// bug reported: http://pear.php.net/bugs/bug.php?id=11317
if ( ! file_exists ( $reg -> install_dir )) return false ;
2007-01-01 15:33:43 +01:00
$installed = $reg -> packageInfo ( null , null , $channel );
2007-06-14 20:56:53 +02:00
2007-01-01 15:33:43 +01:00
//echo "<pre>installed =".print_r($installed,true)."</pre>\n";
2007-06-14 20:56:53 +02:00
$packages = array ();
2007-01-01 15:33:43 +01:00
foreach ( $installed as $package )
{
$name = isset ( $package [ 'package' ]) ? $package [ 'package' ] : $package [ 'name' ];
$version = $package [ 'version' ];
if ( is_array ( $version )) $version = $version [ 'release' ];
$packages [ $name ] = $version ;
// echo "<p>$name: ".print_r($package['version'],true)."</p>\n";
}
ksort ( $packages );
return $packages ;
}
2005-11-01 08:20:46 +01:00
function pear_check ( $package , $args )
{
global $passed_icon , $warning_icon ;
static $pear_available = null ;
2007-01-01 15:33:43 +01:00
static $pear_packages = null ;
2005-11-01 08:20:46 +01:00
2007-01-01 15:33:43 +01:00
$min_version = isset ( $args [ 'version' ]) ? $args [ 'version' ] : null ;
2005-11-01 08:20:46 +01:00
2007-01-01 15:33:43 +01:00
if ( is_null ( $pear_packages ))
{
$pear_packages = get_installed_pear_packages ();
2005-11-01 08:20:46 +01:00
}
2007-06-14 20:56:53 +02:00
$version_available = false ;
2007-01-01 15:33:43 +01:00
// check if egw-pear is availible and packages is included
if ( $package && is_dir ( '../egw-pear' ) && file_exists ( '../egw-pear/' . str_replace ( '_' , '/' , $package ) . '.php' ))
2005-11-01 08:20:46 +01:00
{
2007-01-01 15:33:43 +01:00
$available = true ;
2007-06-14 20:56:53 +02:00
$version_available = '999.egw-pear' ;
2005-11-01 08:20:46 +01:00
}
2007-01-01 15:33:43 +01:00
// packages found in the pear registry --> use that info
elseif ( $pear_packages )
{
$pear_available = true ;
// check if package is installed
if ( $package && isset ( $pear_packages [ $package ])) $available = true ;
// check if it's the right version
2007-06-14 20:56:53 +02:00
$version_available = $pear_packages [ $package ? $package : 'PEAR' ];
2007-01-01 15:33:43 +01:00
}
else // use the old checks as fallback
{
if ( is_null ( $pear_available ))
{
2007-06-14 20:56:53 +02:00
$pear_available = @ include_once ( 'PEAR.php' );
2006-06-21 01:00:55 +02:00
2007-01-01 15:33:43 +01:00
if ( ! class_exists ( 'PEAR' )) $pear_available = false ;
}
if ( $pear_available && $package )
{
$file = str_replace ( '_' , '/' , $package ) . '.php' ;
2007-06-14 20:56:53 +02:00
$available = @ include_once ( $file );
2007-01-01 15:33:43 +01:00
if ( ! class_exists ( $package )) $available = false ;
}
}
2007-07-12 07:47:21 +02:00
// is the right version availible
2007-06-25 12:00:25 +02:00
$available = ( @ $available || $pear_available && ! $package ) && ( ! $min_version || version_compare ( $min_version , $version_available ) <= 0 );
2007-01-01 15:33:43 +01:00
echo '<div>' . ( $available ? $passed_icon : $warning_icon ) . ' <span' . ( $available ? '' : ' class="setup_warning"' ) . '>' .
lang ( 'Checking PEAR%1 is installed' ,( $package ? '::' . $package : '' ) . ( $min_version ? " ( $min_version ) " : '' )) . ': ' .
2007-06-14 20:56:53 +02:00
( $available ? ( $version_available ? $version_available : lang ( 'True' )) : lang ( 'False' )) . " </span></div> \n " ;
2007-01-01 15:33:43 +01:00
if ( ! $available ) // give further info only if not availible
2005-11-01 08:20:46 +01:00
{
2006-06-21 01:00:55 +02:00
echo '<div class="setup_info">' . lang ( 'PEAR%1 is needed by: %2.' , $package ? '::' . $package : '' ,
is_array ( $args [ 'from' ]) ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ]);
2007-01-01 15:33:43 +01:00
if ( ! $pear_available )
2006-06-21 01:00:55 +02:00
{
echo ' ' . lang ( 'PEAR (%1) is a PHP repository and is usually in a package called %2.' ,
'<a href="http://pear.php.net" target="_blank">pear.php.net</a>' , 'php-pear' );
}
2007-06-14 20:56:53 +02:00
elseif ( $min_version && ! $version_available )
2007-01-01 15:33:43 +01:00
{
echo ' ' . lang ( 'We could not determine the version of %1, please make sure it is at least %2' , $package , $min_version );
}
2007-06-14 20:56:53 +02:00
elseif ( $min_version && version_compare ( $min_version , $version_available ) > 0 )
2007-01-01 15:33:43 +01:00
{
echo ' ' . lang ( 'Your installed version of %1 is %2, required is at least %3, please run: ' ,
2007-06-14 20:56:53 +02:00
$package , $version_available , $min_version ) . ' pear update ' . $package ;
2007-01-01 15:33:43 +01:00
}
elseif ( $package )
{
echo ' ' . lang ( 'You can install it by running:' ) . ' pear install ' . $package ;
}
2006-06-21 01:00:55 +02:00
echo " </div> " ;
2005-11-01 08:20:46 +01:00
}
echo " \n " ;
return $available ;
}
2004-02-03 07:21:25 +01:00
function extension_check ( $name , $args )
2003-11-03 21:56:15 +01:00
{
2007-07-12 07:47:21 +02:00
//echo "<p>extension_check($name,".print_r($args,true).")</p>\n";
2004-03-14 11:57:33 +01:00
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
2004-02-03 07:21:25 +01:00
2004-03-14 11:57:33 +01:00
if ( isset ( $args [ 'win_only' ]) && $args [ 'win_only' ] && ! $is_windows )
2004-02-03 07:21:25 +01:00
{
return True ; // check only under windows
}
2004-05-19 11:37:14 +02:00
// we check for the existens of 'dl', as multithreaded webservers dont have it !!!
2005-07-11 20:02:19 +02:00
$available = extension_loaded ( $name ) || function_exists ( 'dl' ) && @ dl ( PHP_SHLIB_PREFIX . $name . '.' . PHP_SHLIB_SUFFIX );
2004-02-03 07:21:25 +01:00
2005-07-11 20:02:19 +02:00
echo '<div>' . ( $available ? $passed_icon : $warning_icon ) . ' <span' . ( $available ? '' : ' class="setup_warning"' ) . '>' . lang ( 'Checking extension %1 is loaded or loadable' , $name ) . ': ' . ( $available ? lang ( 'True' ) : lang ( 'False' )) . " </span></div> \n " ;
2004-02-03 07:21:25 +01:00
2005-07-11 20:02:19 +02:00
if ( ! $available )
2004-02-03 07:21:25 +01:00
{
2006-06-21 01:00:55 +02:00
if ( ! isset ( $args [ 'warning' ]))
{
$args [ 'warning' ] = lang ( 'The %1 extension is needed from: %2.' , $name ,
2007-05-23 08:44:38 +02:00
is_array ( $args [ 'from' ]) ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ]);
2006-06-21 01:00:55 +02:00
}
echo " <div class='setup_info'> " . $args [ 'warning' ] . '</div>' ;
2004-02-03 07:21:25 +01:00
}
2004-03-14 11:57:33 +01:00
echo " \n " ;
2005-07-11 20:02:19 +02:00
return $available ;
2003-10-13 18:48:12 +02:00
}
2006-11-07 07:32:00 +01:00
function function_check ( $name , $args )
{
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
$available = function_exists ( $name );
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 " ;
if ( ! $available )
{
if ( ! isset ( $args [ 'warning' ]))
{
$args [ 'warning' ] = lang ( 'The function %1 is needed from: %2.' , $name ,
is_array ( $args [ 'from' ] ? implode ( ', ' , $args [ 'from' ]) : $args [ 'from' ]));
}
echo " <div class='setup_info'> " . $args [ 'warning' ] . '</div>' ;
}
echo " \n " ;
return $available ;
}
2004-02-03 07:21:25 +01: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' ;
}
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
// owner
$sP .= (( $in_Perms & 0x0100 ) ? 'r' : '-' ) .
2003-10-13 18:48:12 +02:00
(( $in_Perms & 0x0080 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0040 ) ? (( $in_Perms & 0x0800 ) ? 's' : 'x' ) :
2004-02-03 07:21:25 +01:00
(( $in_Perms & 0x0800 ) ? 'S' : '-' ));
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
// group
$sP .= (( $in_Perms & 0x0020 ) ? 'r' : '-' ) .
2003-10-13 18:48:12 +02:00
(( $in_Perms & 0x0010 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0008 ) ? (( $in_Perms & 0x0400 ) ? 's' : 'x' ) :
2004-02-03 07:21:25 +01:00
(( $in_Perms & 0x0400 ) ? 'S' : '-' ));
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
// world
$sP .= (( $in_Perms & 0x0004 ) ? 'r' : '-' ) .
(( $in_Perms & 0x0002 ) ? 'w' : '-' ) .
(( $in_Perms & 0x0001 ) ? (( $in_Perms & 0x0200 ) ? 't' : 'x' ) :
(( $in_Perms & 0x0200 ) ? 'T' : '-' ));
return $sP ;
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
function permission_check ( $name , $args , $verbose = True )
2003-10-13 18:48:12 +02:00
{
2004-03-14 11:57:33 +01:00
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
2004-02-03 07:21:25 +01:00
//echo "<p>permision_check('$name',".print_r($args,True).",'$verbose')</p>\n";
2003-10-13 18:48:12 +02:00
2006-07-09 20:39:01 +02:00
// add a ../ for non-absolute pathes
$rel_name = $name ;
2007-04-29 17:13:54 +02:00
if ( substr ( $name , 0 , 3 ) != '../' && $name { 0 } != '/' && $name { 0 } != '\\' && strpos ( $name , ':' ) === false )
2004-02-03 07:21:25 +01:00
{
$name = '../' . $name ;
}
if ( ! file_exists ( $name ) && isset ( $args [ 'only_if_exists' ]) && $args [ 'only_if_exists' ])
2003-11-03 21:56:15 +01:00
{
2004-02-03 07:21:25 +01:00
return True ;
}
2004-03-14 11:57:33 +01:00
$perms = $checks = '' ;
2004-03-22 00:45:28 +01:00
if ( file_exists ( $name ))
2004-02-03 07:21:25 +01:00
{
2004-03-22 00:45:28 +01:00
$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 ));
2003-11-03 21:56:15 +01:00
}
2004-03-23 18:02:34 +01:00
$checks = array ();
2005-09-19 13:55:02 +02:00
if ( isset ( $args [ 'is_readable' ]))
{
2006-07-09 20:39:01 +02:00
$checks [] = lang ( 'readable by the webserver' );
$check_not = ( ! $args [ 'is_readable' ] ? lang ( 'not' ) : '' );
2005-09-19 13:55:02 +02:00
}
if ( isset ( $args [ 'is_writable' ]))
{
2006-07-09 20:39:01 +02:00
$checks [] = lang ( 'writable by the webserver' );
$check_not = ( ! $args [ 'is_writable' ] ? lang ( 'not' ) : '' );
2005-09-19 13:55:02 +02:00
}
if ( isset ( $args [ 'is_world_readable' ]))
{
2006-07-09 20:39:01 +02:00
$checks [] = lang ( 'world readable' );
$check_not = ( ! $args [ 'is_world_readable' ] ? lang ( 'not' ) : '' );
2005-09-19 13:55:02 +02:00
}
if ( isset ( $args [ 'is_world_writable' ]))
{
2006-07-09 20:39:01 +02:00
$checks [] = lang ( 'world writable' );
$check_not = ( ! $args [ 'is_world_writable' ] ? lang ( 'not' ) : '' );
2005-09-19 13:55:02 +02:00
}
2004-03-23 18:02:34 +01:00
$checks = implode ( ', ' , $checks );
2004-03-14 11:57:33 +01:00
$icon = $passed_icon ;
2006-08-06 07:37:42 +02:00
if ( isset ( $args [ 'msg' ]) && ( $msg = $args [ 'msg' ]))
2006-07-09 20:39:01 +02:00
{
$msg .= ': ' . $perms . " <br /> \n " ;
}
else
{
$msg = lang ( 'Checking file-permissions of %1 for %2 %3: %4' , $rel_name , $check_not , $checks , $perms ) . " <br /> \n " ;
}
2006-11-07 07:32:00 +01:00
$extra_error_msg = '' ;
2006-08-06 07:37:42 +02:00
if ( isset ( $args [ 'error' ]) && $args [ 'error' ])
2006-07-09 20:39:01 +02:00
{
$extra_error_msg = " <br /> \n " . $args [ 'error' ];
}
2004-02-03 07:21:25 +01:00
if ( ! file_exists ( $name ))
{
2006-07-09 20:39:01 +02:00
echo '<div>' . $error_icon . '<span class="setup_error">' . $msg . lang ( '%1 does not exist !!!' , $rel_name ) . $extra_error_msg . " </span></div> \n " ;
2004-02-03 07:21:25 +01:00
return False ;
}
2004-03-09 22:05:28 +01:00
$warning = False ;
2004-03-14 11:57:33 +01:00
if ( ! $GLOBALS [ 'run_by_webserver' ] && ( @ $args [ 'is_readable' ] || @ $args [ 'is_writable' ]))
2004-02-03 07:21:25 +01:00
{
2005-07-11 20:02:19 +02:00
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 " ;
2004-02-03 07:21:25 +01:00
unset ( $args [ 'is_readable' ]);
unset ( $args [ 'is_writable' ]);
$warning = True ;
}
$Ok = True ;
if ( isset ( $args [ 'is_writable' ]) && is_writable ( $name ) != $args [ 'is_writable' ])
{
2006-07-09 20:39:01 +02:00
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 " ;
2004-02-03 07:21:25 +01:00
$Ok = False ;
}
if ( isset ( $args [ 'is_readable' ]) && is_readable ( $name ) != $args [ 'is_readable' ])
{
2006-07-09 20:39:01 +02:00
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 " ;
2004-02-03 07:21:25 +01:00
$Ok = False ;
}
2004-03-14 11:57:33 +01:00
if ( ! $is_windows && isset ( $args [ 'is_world_readable' ]) && ! ( fileperms ( $name ) & 04 ) == $args [ 'is_world_readable' ])
2004-02-03 07:21:25 +01:00
{
2006-07-09 20:39:01 +02:00
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 " ;
2004-02-03 07:21:25 +01:00
$Ok = False ;
}
2004-03-14 11:57:33 +01:00
if ( ! $is_windows && isset ( $args [ 'is_world_writable' ]) && ! ( fileperms ( $name ) & 02 ) == $args [ 'is_world_writable' ])
2004-02-03 07:21:25 +01:00
{
2006-07-09 20:39:01 +02:00
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 " ;
2004-02-03 07:21:25 +01:00
$Ok = False ;
}
if ( $Ok && ! $warning && $verbose )
{
2004-03-22 00:45:28 +01:00
echo $passed_icon . ' ' . $msg ;
2004-02-03 07:21:25 +01:00
}
2004-03-09 22:05:28 +01:00
if ( $Ok && @ $args [ 'recursiv' ] && is_dir ( $name ))
2003-10-13 18:48:12 +02:00
{
2004-03-22 00:45:28 +01:00
if ( $verbose )
{
2005-07-11 20:02:19 +02:00
echo " <div class='setup_info'> " . lang ( 'This might take a while, please wait ...' ) . " </div> \n " ;
2004-03-22 00:45:28 +01:00
flush ();
}
2004-03-14 11:57:33 +01:00
@ set_time_limit ( 0 );
2004-02-03 07:21:25 +01:00
$handle = @ opendir ( $name );
while ( $handle && ( $file = readdir ( $handle )))
2003-10-13 18:48:12 +02:00
{
2004-02-03 07:21:25 +01:00
if ( $file != '.' && $file != '..' )
{
$Ok = $Ok && permission_check (( $name != '.' ? $name . '/' : '' ) . $file , $args , False );
}
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
if ( $handle ) closedir ( $handle );
2003-10-13 18:48:12 +02:00
}
2004-03-22 00:45:28 +01:00
if ( $verbose ) echo " \n " ;
2004-02-03 07:21:25 +01:00
return $Ok ;
2003-10-13 18:48:12 +02:00
}
2004-08-17 19:08:35 +02:00
function mk_value ( $value )
{
if ( ! preg_match ( '/^([0-9]+)([mk]+)$/i' , $value , $matches )) return $value ;
return ( strtolower ( $matches [ 2 ]) == 'm' ? 1024 * 1024 : 1024 ) * ( int ) $matches [ 1 ];
}
2004-02-03 07:21:25 +01:00
function php_ini_check ( $name , $args )
{
2004-03-14 11:57:33 +01:00
global $passed_icon , $error_icon , $warning_icon , $is_windows ;
2003-11-03 21:56:15 +01:00
2004-02-03 07:21:25 +01:00
$safe_mode = ini_get ( 'safe_mode' );
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
$ini_value = ini_get ( $name );
$check = isset ( $args [ 'check' ]) ? $args [ 'check' ] : '=' ;
$verbose_value = isset ( $args [ 'verbose_value' ]) ? $args [ 'verbose_value' ] : $args [ 'value' ];
2004-03-09 22:05:28 +01:00
$ini_value_verbose = '' ;
2004-02-03 07:21:25 +01:00
if ( $verbose_value == 'On' || $verbose_value == 'Off' )
2003-10-13 18:48:12 +02:00
{
2004-02-03 07:21:25 +01:00
$ini_value_verbose = ' = ' . ( $ini_value ? 'On' : 'Off' );
2003-11-03 21:56:15 +01:00
}
2004-02-03 07:21:25 +01:00
switch ( $check )
2003-11-03 21:56:15 +01:00
{
2004-02-03 07:21:25 +01:00
case 'not set' :
2004-03-14 11:57:33 +01:00
$check = lang ( 'not set' );
2004-02-03 07:21:25 +01:00
$result = ! ( $ini_value & $args [ 'value' ]);
break ;
case 'set' :
2004-03-14 11:57:33 +01:00
$check = lang ( 'set' );
2004-02-03 07:21:25 +01:00
$result = !! ( $ini_value & $args [ 'value' ]);
break ;
case '>=' :
$result = ! $ini_value || // value not used, eg. no memory limit
2004-08-17 19:08:35 +02:00
( int ) mk_value ( $ini_value ) >= ( int ) mk_value ( $args [ 'value' ]);
2004-02-03 07:21:25 +01:00
break ;
2004-03-14 11:57:33 +01:00
case 'contain' :
$check = lang ( 'contain' );
$sep = $is_windows ? '[; ]+' : '[: ]+' ;
$result = in_array ( $args [ 'value' ], split ( $sep , $ini_value ));
break ;
2004-02-03 07:21:25 +01:00
case '=' :
default :
$result = $ini_value == $args [ 'value' ];
break ;
2003-10-13 18:48:12 +02:00
}
2005-07-11 20:02:19 +02:00
$msg = ' ' . lang ( 'Checking php.ini' ) . " : $name $check $verbose_value : <span class='setup_info'>ini_get(' $name ')=' $ini_value ' $ini_value_verbose </span> " ;
2004-03-14 11:57:33 +01:00
if ( $result )
{
2005-07-11 20:02:19 +02:00
echo " <div> " . $passed_icon . $msg . " </div> \n " ;
2004-03-14 11:57:33 +01:00
}
2004-02-03 07:21:25 +01:00
if ( ! $result )
2003-10-13 18:48:12 +02:00
{
2007-07-12 07:47:21 +02:00
if ( isset ( $args [ 'error' ]))
{
echo " <div> " . $error_icon . ' <span class="setup_error">' . $msg . '</span><div class="setup_info">' . $args [ 'error' ] . " </div></div> \n " ;
}
elseif ( isset ( $args [ 'warning' ]))
2004-02-03 07:21:25 +01:00
{
2005-07-11 20:02:19 +02:00
echo " <div> " . $warning_icon . ' <span class="setup_warning">' . $msg . '</span><div class="setup_info">' . $args [ 'warning' ] . " </div></div> \n " ;
2004-02-03 07:21:25 +01:00
}
2007-07-12 07:47:21 +02:00
elseif ( ! isset ( $args [ 'safe_mode' ]))
2004-02-03 07:21:25 +01:00
{
2007-07-12 07:47:21 +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-02-03 07:21:25 +01:00
}
2004-03-09 22:05:28 +01:00
if ( isset ( $args [ 'safe_mode' ]) && $safe_mode || @ $args [ 'change' ])
2004-02-03 07:21:25 +01:00
{
2004-03-14 11:57:33 +01:00
if ( ! isset ( $args [ 'warning' ]) && ! isset ( $args [ 'error' ]))
{
2005-07-11 20:02:19 +02:00
echo '<div>' . $error_icon . ' <span class="setup_error">' . $msg . '</span></div>' ;
2004-03-14 11:57:33 +01:00
}
2005-07-11 20:02:19 +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 " ;
2004-08-17 19:08:35 +02:00
echo '*** ' . lang ( 'AND reload your webserver, so the above changes take effect !!!' ) . " </div> \n " ;
2004-02-03 07:21:25 +01:00
}
2003-10-13 18:48:12 +02:00
}
2004-03-14 11:57:33 +01:00
return $result ;
2004-02-03 07:21:25 +01:00
}
2003-10-13 18:48:12 +02:00
2004-05-04 09:41:02 +02:00
function get_php_ini ()
{
ob_start ();
phpinfo ( INFO_GENERAL );
$phpinfo = ob_get_contents ();
ob_end_clean ();
return preg_match ( '/\(php.ini\).*<\/td><td[^>]*>([^ <]+)/' , $phpinfo , $found ) ? $found [ 1 ] : False ;
}
2004-06-08 07:00:27 +02:00
function gd_check ()
{
global $passed_icon , $warning_icon ;
2005-11-01 08:20:46 +01:00
2004-06-08 07:00:27 +02:00
$available = ( function_exists ( 'imagecopyresampled' ) || function_exists ( 'imagecopyresized' ));
2005-07-11 20:02:19 +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 " ;
2004-06-08 07:00:27 +02:00
if ( ! $available )
{
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 " ;
}
2005-11-01 08:20:46 +01:00
return $available ;
2004-06-08 07:00:27 +02:00
}
2004-02-03 07:21:25 +01:00
if ( $run_by_webserver )
{
2005-03-04 13:40:28 +01:00
$tpl_root = $GLOBALS [ 'egw_setup' ] -> html -> setup_tpl_dir ( 'setup' );
2004-02-03 07:21:25 +01:00
$setup_tpl = CreateObject ( 'setup.Template' , $tpl_root );
$setup_tpl -> set_file ( array (
'T_head' => 'head.tpl' ,
'T_footer' => 'footer.tpl' ,
));
$ConfigDomain = get_var ( 'ConfigDomain' , Array ( 'POST' , 'COOKIE' ));
2004-05-05 23:05:13 +02:00
if ( @ $_GET [ 'intro' ]) {
2004-07-10 11:26:28 +02:00
if ( $ConfigLang = get_var ( 'ConfigLang' , array ( 'POST' , 'COOKIE' )))
{
2005-03-04 13:40:28 +01:00
$GLOBALS [ 'egw_setup' ] -> set_cookie ( 'ConfigLang' , $ConfigLang ,( int ) ( time () + ( 1200 * 9 )), '/' );
2004-07-10 11:26:28 +02:00
}
2005-03-04 13:40:28 +01:00
$GLOBALS [ 'egw_setup' ] -> html -> show_header ( lang ( 'Welcome to the eGroupWare Installation' ), False , 'config' );
2004-05-05 23:05:13 +02:00
echo '<h1>' . lang ( 'Welcome to the eGroupWare Installation' ) . " </h1> \n " ;
2004-07-10 11:26:28 +02:00
if ( ! $ConfigLang )
{
echo '<p><form action="check_install.php?intro=1" method="Post">Please Select your language ' . lang_select ( True , 'en' ) . " </form></p> \n " ;
}
2005-07-11 20:02:19 +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>' ;
echo '<p>' . lang ( 'We will now run a series of tests, which may take a few minutes. Click the link below to proceed.' ) . '</p>' ;
2004-05-05 23:05:13 +02:00
echo '<h3><a href="check_install.php">' . lang ( 'Run installation tests' ) . '</a></h3>' ;
2006-03-08 10:39:42 +01:00
echo '<p><a href="manageheader.php">' . lang ( 'Skip the installation tests (not recommended)' ) . " </a></p> \n " ;
2004-05-05 23:05:13 +02:00
$setup_tpl -> pparse ( 'out' , 'T_footer' );
exit ;
} else {
2005-03-04 13:40:28 +01:00
$GLOBALS [ 'egw_setup' ] -> html -> show_header ( lang ( 'Checking the eGroupWare Installation' ), False , 'config' , $ConfigDomain ? $ConfigDomain . '(' . @ $GLOBALS [ 'egw_domain' ][ $ConfigDomain ][ 'db_type' ] . ')' : '' );
2004-05-05 23:05:13 +02:00
echo '<h1>' . lang ( 'Checking the eGroupWare Installation' ) . " </h1> \n " ;
2004-08-17 19:08:35 +02:00
# echo "<pre style=\"text-align: left;\">\n";;
2004-05-05 23:05:13 +02:00
}
2004-02-03 07:21:25 +01:00
}
else
{
echo " Checking the eGroupWare Installation \n " ;
echo " ==================================== \n \n " ;
}
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
$Ok = True ;
foreach ( $checks as $name => $args )
{
$check_ok = $args [ 'func' ]( $name , $args );
$Ok = $Ok && $check_ok ;
}
2003-10-13 18:48:12 +02:00
2004-02-03 07:21:25 +01:00
if ( $run_by_webserver )
2003-10-13 18:48:12 +02:00
{
2004-08-17 19:08:35 +02:00
# echo "</pre>\n";;
2004-02-03 07:21:25 +01:00
2005-03-04 13:40:28 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'setup' ][ 'stage' ][ 'header' ] != 10 )
2003-10-13 18:48:12 +02:00
{
2004-02-03 07:21:25 +01:00
if ( ! $Ok )
{
2004-05-05 23:05:13 +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 " ;
2004-02-03 07:21:25 +01:00
}
else
{
echo '<h3><a href="manageheader.php">' . lang ( 'Continue to the Header Admin' ) . " </a></h3> \n " ;
}
2003-10-13 18:48:12 +02:00
}
else
{
2004-03-14 11:57:33 +01:00
echo '<h3>' ;
if ( ! $Ok )
{
2004-05-05 23:05:13 +02:00
echo lang ( 'Please fix the above errors (%1) and warnings(%2)' , $error_icon , $warning_icon ) . '. ' ;
2004-03-14 11:57:33 +01:00
}
2005-07-11 20:02:19 +02:00
echo '<br /><a href="' . str_replace ( 'check_install.php' , '' , $_SERVER [ 'HTTP_REFERER' ]) . '">' . lang ( 'Return to Setup' ) . " </a></h3> \n " ;
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
$setup_tpl -> pparse ( 'out' , 'T_footer' );
//echo "</body>\n</html>\n";
2003-10-13 18:48:12 +02:00
}
2004-02-03 07:21:25 +01:00
?>