<?php
/* $Id: index.php,v 1.48 2003/11/27 15:51:12 k-fish Exp $ */

// ================================================
// Setup script for moregroupware
// handles installation (and soon update of mgw)
// ================================================

/* some providers disable realpath */
$no_realpath = false;
if (ini_get("disable_functions")!="") {
    foreach (explode(",",ini_get("disable_functions")) as $func) {
        if (trim($func)=="realpath") {
            $no_realpath = true;
        }
    }
}

/* constants */
define("SETUP_RUNNING", true);
define("TEMPLATE_DIR","templates/default/html");
($no_realpath) ? (define("ROOTPATH", _realpath(".."))) : (define("ROOTPATH", realpath(".."))) ;

/* DEBUGGING? */
define("DEBUG", false);
include("../include/log.inc.php");
$GLOBALS['log'] = new log(MGW_FATAL|MGW_ERROR|MGW_WARNING|MGW_NOTICE|MGW_INFO);
if (!DEBUG) {
    $GLOBALS['log']->off();
} else {
    $GLOBALS['log']->toFile();
}

$GLOBALS['log']->message(MGW_NOTICE, "Debugging started (".date('Y-m-d H:i').")", __LINE__, __FILE__, 1, "setup");
$GLOBALS['log']->message(MGW_INFO, "OS type: ".PHP_OS, __LINE__, __FILE__, 1, "setup");
if ($_POST) {
    ob_start();
    var_dump($_POST);
    $GLOBALS['log']->message(MGW_NOTICE, "\$_POST: ".ob_get_contents(), __LINE__, __FILE__, 1, "setup");
    ob_end_clean();   
}

$GLOBALS['log']->message(MGW_INFO, "Root: ".ROOTPATH, __LINE__, __FILE__, 1, "setup");

/* setup dir */
$setupdir = pathinfo(dirname(__FILE__)); 
define("SETUP_DIR", $setupdir["basename"]);
$GLOBALS['log']->message(MGW_INFO, "Setup directory: ".SETUP_DIR, __LINE__, __FILE__, 1, "setup");

/* files and directories that need to be created throughout the setup */
$configFile = ROOTPATH."/config.inc.php";
$htmlTemplates = ROOTPATH."/templates_c";
//$wmlTemplates = ROOTPATH."/templates_wml_c"; // FIXME wml output

/* log files */
$setupLog = ROOTPATH."/install.log";
$errorLog = ROOTPATH."/install.errors";

/* start a session so we don't have to keep passing post/get vars from page to page */
session_name('MGWSETUP');
session_start();
if(session_id()=='')
    setup_die("Setup is unable to start a session. (session.save_path is set to: ".ini_get('session.save_path').")<br />Please check your php.ini and configure your system manually.");

if ($_SESSION) {
    ob_start();
    var_dump($_SESSION);
    $GLOBALS['log']->message(MGW_NOTICE, "\$_SESSION: ".ob_get_contents(), __LINE__, __FILE__, 1, "setup");
    ob_end_clean();   
}

/* save all setup data to session */
if (!isset($_SESSION["SETUP"]))
    $_SESSION["SETUP"] = array();

/* in case of register_globals=off (as it should be) */
//$SETUP =& $_SESSION["SETUP"];

/* destroy session and send user to login page */
if (isset($_POST["login"])) {
    $url = $_SESSION["SETUP"]["rooturl"]."index.php";
    $_SESSION = array();
    session_destroy();

    clearstatcache();

    // make log and other files writable, so they can be deleted
    chmod($setupLog, octdec(666));
    chmod($errorLog, octdec(666));
    if($dir = opendir(ROOTPATH)){
	while (($file = readdir($dir)) !== false) {
	    if (strstr($file, 'missing.'))
		chmod(ROOTPATH.'/'.$file, octdec(666));
	}
	closedir($dir);
    }

    // delete compiled templates written by setup
    if($dir = opendir(ROOTPATH.'/templates_c')){
	while (($file = readdir($dir)) !== false) {
	    if (is_file(ROOTPATH.'/templates_c/'.$file))
		unlink(ROOTPATH.'/templates_c/'.$file);
	}
	closedir($dir);
    }

    header("Location: ".$url);
    exit();
}

/* restart setup */
if (isset($_POST["restart"]) && $_SESSION["SETUP"]['authenticated']) {
    $logArray = array();
    $logArray[] = "Setup restarting... doing cleanup!\n\n";

    /* kill old logs */
    if (file_exists($setupLog)){
    	unlink($setupLog);
    	$logArray[] = "Unlinked $setupLog\n";
        $GLOBALS['log']->message(MGW_NOTICE, "Deleted SETUP log", __LINE__, __FILE__, 1, "setup");
    }
    if (file_exists($errorLog)){
    	unlink($errorLog);
    	$logArray[] = "Unlinked $errorLog\n";
        $GLOBALS['log']->message(MGW_NOTICE, "Deleted ERROR log", __LINE__, __FILE__, 1, "setup");
    }
    
    /* check for tables and drop if needed */
    if(isset($_SESSION["SETUP"]["dbtype"]) && $_SESSION["SETUP"]["dbtype"] != ''){
	include("../include/adodb/adodb.inc.php");
	$conn = ADONewConnection($_SESSION["SETUP"]["dbtype"]);
	if (!$conn->Connect($_SESSION["SETUP"]["dbhost"], $_SESSION["SETUP"]["dbuser"], $_SESSION["SETUP"]["dbpass"], $_SESSION["SETUP"]["dbname"]))
	    $logArray[] = "Connection failed while trying to drop tables from a failed install: Is your database server still running?\n";
	else{
	    $tables = $conn->MetaTables();
	    $logArray[] = "Dropping tables from a failed install:\n";
	    $GLOBALS['log']->message(MGW_NOTICE, "Droping tables from a failed install (see ".$setupLog." for details).", __LINE__, __FILE__, 1, "setup");
	    foreach($tables as $table){
	        if(substr($table,0,4) == "mgw_"){
		    $res = $conn->Execute("DROP TABLE $table");
		    $logArray[] = $table."\n";
		}
	    }
	}
    }
    else{
	$logArray[] = "Skipping DB cleanup, DBTYPE not set.\n\n";
    }
    $logArray[] = "Done.\n\n";
    
    /* write log files */
    $str = "";
    if ($fp = @fopen($setupLog, "a+")) {
    	if (count($logArray)>0) {
	    for ($i=0; $i<count($logArray); $i++) {
            	$str .= $logArray[$i];
    	    	fwrite($fp, $logArray[$i]);
    	    }
       	}
        fclose($fp);
    }
    
    if (file_exists($configFile)) {
        unlink($configFile);
        $GLOBALS['log']->message(MGW_NOTICE, "Removing old config file.", __LINE__, __FILE__, 1, "setup");
    }
    $_SESSION = array();
    $_SESSION["SETUP"] = array();
    //$_SESSION["SETUP"] =& $_SESSION["SETUP"]; // needless, as $_SESSION["SETUP"] is a reference!?!
    $GLOBALS['log']->message(MGW_NOTICE, "\$_SESSION var reset to array().", __LINE__, __FILE__, 1, "setup");
}

/* error control */
if (!isset($_SESSION["js_for_errors"])) {
    $_SESSION["js_for_errors"] = true;
}
if (isset($_POST["js_for_errors"])) {
    ($_POST["js_for_errors"]=="1") ? ($_SESSION["js_for_errors"] = true) : ($_SESSION["js_for_errors"] = false) ;
}

if (!isset($_SESSION["SETUP"]["settings_ok"])) $_SESSION["SETUP"]["settings_ok"] = false;

/* includes */
include("../include/lang.inc.php");
include("../include/version.inc.php");

/* set smarty dir, we know it is ../include/smarty */
if ($no_realpath) {
    define("SMARTY_DIR",_realpath("..")."/include/smarty/");
} else {
    define("SMARTY_DIR",realpath("../include/smarty").'/');
}

require_once(SMARTY_DIR."Smarty.class.php");

/* root to setup */
define("SETUP_ROOT", ROOTPATH.'/'.SETUP_DIR);

/* find smarty must be able to write in  templates_c
 * nothing we can do about this
 */
$smarty_compile = ROOTPATH.'/templates_c';
if ($no_realpath) {
    $smarty_templates = _realpath(".")."templates/default/html/";
} else {
    $smarty_templates = realpath("./templates/default/html").'/';
}


if (!is_dir($smarty_compile)){
    mkdir($smarty_compile, octdec(700)) or setup_die("Setup needs a place to write some temporary data. It does this in '".SETUP_ROOT.'/'.$smarty_compile."'.<br /><br />Automatic creation of this directory failed. Please create it manually and give the user of your webserver 'R/W' rights on this directory");
}
elseif(!is_writeable($smarty_compile)) setup_die("Setup needs a place to write some temporary data. It does this in '".SETUP_ROOT.'/'.$smarty_compile."'.<br /><br />The directory exists, but please give the user of your webserver 'R/W' rights on this directory.");

/* lets check for some fatal safe_mode errors for smarty */
if (isset($_GET["nofatal"]) and $_GET["nofatal"]==1) {
    $_SESSION["safe_mode_fatal"] = false;   
} else {
    $_SESSION["safe_mode_fatal"] = true;
}
if (ini_get("safe_mode")=="1") {
    $GLOBALS['log']->message(MGW_WARNING, "Safe mode is ON.", __LINE__, __FILE__, 1, "setup");
    if (isset($_SESSION["safe_mode_fatal"]) && !$_SESSION["safe_mode_fatal"]) {
        /* nothing */
        $GLOBALS['log']->message(MGW_FATAL, "Was asked to continue anyway!! Well...", __LINE__, __FILE__, 1, "setup");
    } else {
        /* safe_mode_gid? */
        if (ini_get("safe_mode_gid")=="1") {
            $gid = true;
        } else {
            $gid = false;
        }
        $stat1 = stat(ROOTPATH.'/');
        $stat2 = stat(ROOTPATH."/templates_c/");
        if (($stat1[5]==$stat2[5]) || ($gid && $stat1[6]==$stat2[6])) {
            $_SESSION["safe_mode_fatal"] = false;
        } else {
            $_SESSION["safe_mode_fatal"] = true;
            setup_die("The setup script found a fatal error and can't continue. Safe mode restriction are 'On' in the PHP configuration. Because the user/group ID of the temporary files directory does not match that of it's parent directory we will not be able to write any files.<br />You can create this directory yourself and give the web server write access to overcome the problem.<br /><br /><a href='".$_SERVER['PHP_SELF']."?nofatal=1'>Continue</a> anyway.");
        }
        $GLOBALS['log']->message(MGW_WARNING, "!!!", __LINE__, __FILE__, 1, "setup");
    }
}

/* create smarty, and set class directories 
 * set smarty to single dir mode in case safe mode is on 
 */
$smarty = new Smarty;
$smarty->caching = false;
$smarty->template_dir = $smarty_templates;
$smarty->compile_dir = $smarty_compile;
$smarty->use_sub_dirs = false;
$GLOBALS['log']->message(MGW_NOTICE, "Smarty initialized", __LINE__, __FILE__, 1, "setup");
$smarty->assign("SESSIONID", session_id());
$smarty->assign("SESSIONNAME", session_name());

$_SESSION["SETUP"]["steps"] = 6;
if (!isset($_SESSION["SETUP"]["step"])) $_SESSION["SETUP"]["step"] = 1;
if (!isset($_SESSION["SETUP"]["lang"])) $_SESSION["SETUP"]["lang"] = "en";

if (isset($_POST["lang_charset"])) {
    $lc = explode(";", $_POST["lang_charset"]);
    $_SESSION["SETUP"]["lang"] = $lc[0];
    $_SESSION["SETUP"]["charset"] = $lc[1];
}
/* get language strings */
define('CACHE_FOLDER', '');
Lang::setLocaledText($_SESSION["SETUP"]['lang'],'setup','../setup');

// some security - if a config file exists, check admin password
if(isset($_POST['adminpass'])){
    @include($configFile);
    include("../include/adodb/adodb.inc.php");

    $conn = ADONewConnection($appconf["dbvendor"]);
    $conn->Connect($appconf["dbhost"], $appconf["dbuser"], $appconf["dbpassword"], $appconf["dbname"]);
    $res = $conn->GetOne('SELECT pw FROM mgw_users WHERE id=1');
    if(md5($_POST['adminpass']) == $res)
	$_SESSION["SETUP"]['authenticated'] = true;
    else{
	unset($_POST);
	$_SESSION["SETUP"]["step"] = 1;
	$smarty->assign('askpass', true);
	$smarty->assign("jserrorarray", array(Lang::getLanguageString('adminpasserror')));
    }
    unset($appconf);
}
elseif(file_exists($configFile) && (!isset($_SESSION["SETUP"]['authenticated']) || !$_SESSION["SETUP"]['authenticated'])){
    unset($_POST);
    $_SESSION["SETUP"]["step"] = 1;
    $smarty->assign('askpass', true);
}
else{
    $smarty->assign('askpass', false);
}

// what shall we do?
if (isset($_POST["install"])) {
    $_SESSION["SETUP"]['uninstall'] = false;
    $_SESSION["SETUP"]['update'] = false;
    $_SESSION["SETUP"]['step'] = 2;
    $GLOBALS['log']->message(MGW_NOTICE, "Install selected, step set to: 2", __LINE__, __FILE__, 1, "setup");
}
elseif (isset($_POST["update"])) {
    $_SESSION["SETUP"]['uninstall'] = false;
    $_SESSION["SETUP"]['update'] = true;
    $_SESSION["SETUP"]['step'] = 2;
    $GLOBALS['log']->message(MGW_NOTICE, "Update selected, step set to: 2", __LINE__, __FILE__, 1, "setup");
}
elseif (isset($_POST["uninstall"])) {
    $_SESSION["SETUP"]["steps"] = 4;
    $_SESSION["SETUP"]['uninstall'] = true;
    $_SESSION["SETUP"]['update'] = false;
    $_SESSION["SETUP"]['step'] = 2;
    $GLOBALS['log']->message(MGW_NOTICE, "Uninstall selected, step set to: 2", __LINE__, __FILE__, 1, "setup");
}
elseif (isset($_POST["next"]) and abs($_SESSION["SETUP"]["step"])<$_SESSION["SETUP"]["steps"]) {
    $_SESSION["SETUP"]["step"] = abs($_SESSION["SETUP"]["step"]);
    $_SESSION["SETUP"]["step"]++;
    $GLOBALS['log']->message(MGW_NOTICE, "Next pressed, step set to: ".$_SESSION["SETUP"]["step"], __LINE__, __FILE__, 1, "setup");
}
elseif (isset($_POST["prev"]) and abs($_SESSION["SETUP"]["step"])>1) {
    if ($_SESSION["SETUP"]["step"]>0) $_SESSION["SETUP"]["step"]--; else  $_SESSION["SETUP"]["step"] = abs($_SESSION["SETUP"]["step"]);
    $GLOBALS['log']->message(MGW_NOTICE, "Prev pressed, step set to: ".$_SESSION["SETUP"]["step"], __LINE__, __FILE__, 1, "setup");
}

// save information from forms
if ($_SESSION["SETUP"]["step"]==4 and !$_SESSION["SETUP"]["settings_ok"]) {
    include("inc/save_settings.inc.php");
    $GLOBALS['log']->message(MGW_NOTICE, "Saving DB settings", __LINE__, __FILE__, 1, "setup");
}
if ($_SESSION["SETUP"]["step"]==5 and $_SESSION["SETUP"]["auth_method"]=="ldap" and !$_SESSION["SETUP"]["ldap_ok"]) {
    include("inc/save_ldap.inc.php");
    $GLOBALS['log']->message(MGW_NOTICE, "Saving LDAP settings", __LINE__, __FILE__, 1, "setup");
} 

/* handle each step */
switch ($_SESSION["SETUP"]["step"]) {
 case 1:
    $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_1.inc.php", __LINE__, __FILE__, 1, "setup");
    include("inc/step_1.inc.php");
    break;
 case 2:
    $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_2.inc.php", __LINE__, __FILE__, 1, "setup");
    include("inc/step_2.inc.php");
    break;
 case 3:
    if ($_SESSION["SETUP"]["system"]!=true) {
	$_SESSION["SETUP"]["step"] = 2;
        $GLOBALS['log']->message(MGW_WARNING, "Step changed to: ".$_SESSION["SETUP"]["step"], __LINE__, __FILE__, 1, "setup");
        $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_2.inc.php", __LINE__, __FILE__, 1, "setup");
	    include("inc/step_2.inc.php");
    } else {
        $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_3.inc.php", __LINE__, __FILE__, 1, "setup");
	    include("inc/step_3.inc.php");
    }
     break;
 case 4:
    if (!$_SESSION["SETUP"]["settings_ok"]) {
	$_SESSION["SETUP"]["step"] = 3;
        $GLOBALS['log']->message(MGW_WARNING, "Step changed to: ".$_SESSION["SETUP"]["step"], __LINE__, __FILE__, 1, "setup");
        $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_3.inc.php", __LINE__, __FILE__, 1, "setup");
	    include("inc/step_3.inc.php");
    } else {
	    include("inc/step_4.inc.php");
    }
    break;
 case 5:
    if ($_SESSION["SETUP"]["auth_method"]=="ldap" and !$_SESSION["SETUP"]["ldap_ok"]) {
	$_SESSION["SETUP"]["step"] = 4;
        $GLOBALS['log']->message(MGW_WARNING, "Step changed to: ".$_SESSION["SETUP"]["step"], __LINE__, __FILE__, 1, "setup");
        $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_4.inc.php", __LINE__, __FILE__, 1, "setup");
	    include("inc/step_4.inc.php");
    } else {
        $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_5.inc.php", __LINE__, __FILE__, 1, "setup");
	    include("inc/step_5.inc.php");
    }
    break;
 case 6:
    $GLOBALS['log']->message(MGW_INFO, "Going to: inc/step_6.inc.php", __LINE__, __FILE__, 1, "setup");
    include("inc/step_6.inc.php");
    break;
 default:
     /* do shit */
}

$smarty->assign("imgpathmaster", "./templates/default/media/");

$smarty->assign("title", "more.groupware - ");
if (!isset($_SESSION["SETUP"]["charset"])) {
    $smarty->assign("charset", "iso-8859-1");
    header('Content-Type: text/html; charset=iso-8859-1');
} else {
    $smarty->assign("charset", $_SESSION["SETUP"]["charset"]);
    header('Content-Type: text/html; charset='.$_SESSION["SETUP"]["charset"]);
}

$smarty->assign("mgwversion", $gwversion);
$smarty->assign("var_steps", $_SESSION["SETUP"]["steps"]);
$smarty->assign("var_step", abs($_SESSION["SETUP"]["step"]));
$smarty->assign("js_errors", $_SESSION["js_for_errors"]);

/* append default setup navigation */
if (!isset($nav)) {
    if (abs($_SESSION["SETUP"]["step"])>1)  {
    	$smarty->append("nav", array(0=>"prev",1=>Lang::getLanguageString("prev"),2=>1));
    }

    if ($_SESSION["SETUP"]["step"] == 1) {
	if(file_exists($configFile)) {
	    $smarty->append("nav", array(0=>"uninstall",1=>Lang::getLanguageString("uninstall"),2=>1));
	    $smarty->append("nav", array(0=>"update",1=>Lang::getLanguageString("update"),2=>0));
	}
	else{
	    $smarty->append("nav", array(0=>"uninstall",1=>Lang::getLanguageString("uninstall"),2=>0));
	    $smarty->append("nav", array(0=>"install",1=>Lang::getLanguageString("install"),2=>1));
	}
    }
    elseif ($_SESSION["SETUP"]["step"]<$_SESSION["SETUP"]["steps"]) {
    	$smarty->append("nav", array(0=>"next",1=>Lang::getLanguageString("next"),2=>1));
    } else {
    	$smarty->append("nav", array(0=>"next",1=>Lang::getLanguageString("next"),2=>0));
    }
}

$smarty->assign("step_template", "step_".$_SESSION["SETUP"]["step"].".tpl");

$GLOBALS['log']->message(MGW_NOTICE, "Sending output to client", __LINE__, __FILE__, 1, "setup");
$smarty->display("setup.tpl");

if (DEBUG) echo("<br><table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\"><tr><td><pre>".$GLOBALS['log']->endFlush()."</pre></td></tr></table>");

exit();

function _realpath($str) {
    global $setupdir;
    
    $current_dir = getcwd();
    chdir($str);
    $path = getcwd();
    chdir($current_dir);
    
    return $path;
}

function setup_die($e) {
    exit("<html><head><title>Error</title><link rel='stylesheet' type='text/css' href='./templates/default/css/setup.css'></head><body bgcolor='#c8c9d4'><table align='center' width='500'><tr><td><br /><table border='0' cellpadding='6' cellspacing='1' bgcolor='black'><tr><td align='center' bgcolor='#ededed' style='font: 12px Arial;'><strong>ERROR</strong></td></tr><tr><td bgcolor='#ededed' style='font: 12px Arial;'><br />Setup died with this message:<br /><br />$e<br /><br />Have a <a href='../docs/html/en/index.html'>look at the manual</a> for more information. Chances are, that you need to <a href='http://www.moregroupware.org/manual/mgw-manual-en.tar.gz'>download</a> it first - or <a href='http://www.moregroupware.org/manual/en/index.html'>read it online</a>.</td></tr><tr><td align='right' bgcolor='#ffffff'><form name='setupform' action='index.php' method='POST'><input type='submit' name='restart' value='restart' class='submit' /></form></td></tr></table></td></tr></table></body></html>");
}
?>
