<?php
/*
Officity - Web application platform - Version 6.0 - 2011-07-05

François Dispaux, Boris Verdeyen, Thomas Hermant,
Jérémie Roy, Grégory Meurice, Abdelila Harbi, 
Marc Mignonsin, Jonathan Sanchez, Julien Gonzalez, Pierre Fouchez

Sushee and Officity is © Copyright 2011 Nectil SA.

`/sushee-source/Kernel_ressources/install.php` is part of Officity.

Sushee 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 3 of the License, or
(at your option) any later version.

Officity and Sushee are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Sushee. If not, see <http://www.gnu.org/licenses/>.
*/
	
class Sushee_File{
	
	var $path;
	
	function Sushee_File($path){
		$this->path = $path;
	}
	
	function save($str){
		$fp = @fopen($this->path, 'w+');
		@fwrite($fp,$str);
	}
	
	function toString(){
		$handle = @fopen($this->path, "r");
		$str = '';
		if($handle!==false){
			while (!feof($handle)) {
	   			$buffer = fgets($handle, 4096);
	   			$str.=$buffer;
			}
		}
		return $str;
	}
	
	function exists(){
		return file_exists($this->path);
	}
}

class Sushee_DBRessource{
	
	var $res;
	
	function Sushee_DBRessource($res){
		$this->res = $res;
	}
	
	function fetchRow(){
		return mysql_fetch_array($this->res,MYSQL_ASSOC);
	}
	
}

class Sushee_DBConnection{
	
	var $db_name;
	var $db_login;
	var $db_password;
	var $conn;
	var $error;
	var $errorCode;
	var $sql;
	
	function connect($db_login,$db_password){
		$this->db_login = $db_login;
		$this->db_password = $db_password;
		$this->conn =  @mysql_connect('localhost', $db_login , $db_password);
		if($this->conn!==false){
			mysql_select_db('mysql');
		}
		return ($this->conn!==false);
	}
	
	function goToDB($db_name){
		return mysql_select_db($db_name);
	}
	
	function execute($sql){
		$this->error = false;
		$this->errorCode = false;
		$this->sql = $sql;
		$res = false;
		if(is_object($sql)){
			$sql_query = $sql->toString();
			$pieces = array();
			$this->PMA_splitSqlFile($pieces, $sql_query);
			$pieces_count = count($pieces);
			for ($i = 0; $i < $pieces_count; $i++) {
				$a_sql_query = $pieces[$i];
				$this->log($a_sql_query);
				$res = mysql_query($a_sql_query);
				if (!$res){
					break;
				}
			}
		}else{
			$this->log($sql);
			$res = mysql_query($sql);
		}
		$this->error = mysql_error();
		$this->errorCode = mysql_errno();
		if(is_bool($res)){
			return $res;
		}else{
			return new Sushee_DBRessource($res);
		}
	}
	
	function getSQL(){
		return $this->sql;
	}
	
	function log($sql){
		//$this->log.=$sql."\r";
		//echo $sql.'<br/>';
	}
	
	function getError(){
		return $this->error;
	}
	
	function getErrorCode(){
		return $this->errorCode;
	}
	
	function getInsertedID(){
		return mysql_insert_id();
	}
	
	function encode($value){
		return str_replace(array("\\","\""),array("\\\\","\\\""),stripcslashes($value));
	}
	
	function PMA_splitSqlFile(&$ret, $sql, $release=32330){
		$sql          = trim($sql);
		$sql_len      = strlen($sql);
		$char         = '';
		$string_start = '';
		$in_string    = FALSE;
		$time0        = time();

		for ($i = 0; $i < $sql_len; ++$i) {
			$char = $sql[$i];

			// We are in a string, check for not escaped end of strings except for
			// backquotes that can't be escaped
			if ($in_string) {
				for (;;) {
					$i         = strpos($sql, $string_start, $i);
					// No end of string found -> add the current substring to the
					// returned array
					if (!$i) {
						$ret[] = $sql;
						return TRUE;
					}
					// Backquotes or no backslashes before quotes: it's indeed the
					// end of the string -> exit the loop
					else if ($string_start == '`' || $sql[$i-1] != '\\') {
						$string_start      = '';
						$in_string         = FALSE;
						break;
					}
					// one or more Backslashes before the presumed end of string...
					else {
						// ... first checks for escaped backslashes
						$j                     = 2;
						$escaped_backslash     = FALSE;
						while ($i-$j > 0 && $sql[$i-$j] == '\\') {
							$escaped_backslash = !$escaped_backslash;
							$j++;
						}
						// ... if escaped backslashes: it's really the end of the
						// string -> exit the loop
						if ($escaped_backslash) {
							$string_start  = '';
							$in_string     = FALSE;
							break;
						}
						// ... else loop
						else {
							$i++;
						}
					} // end if...elseif...else
				} // end for
			} // end if (in string)

			// We are not in a string, first check for delimiter...
			else if ($char == ';') {
				// if delimiter found, add the parsed part to the returned array
				$ret[]      = substr($sql, 0, $i);
				$sql        = ltrim(substr($sql, min($i + 1, $sql_len)));
				$sql_len    = strlen($sql);
				if ($sql_len) {
					$i      = -1;
				} else {
					// The submited statement(s) end(s) here
					return TRUE;
				}
			} // end else if (is delimiter)

			// ... then check for start of a string,...
			else if (($char == '"') || ($char == '\'') || ($char == '`')) {
				$in_string    = TRUE;
				$string_start = $char;
			} // end else if (is start of string)

			// ... for start of a comment (and remove this comment if found)...
			else if ($char == '#'
					 || ($char == ' ' && $i > 1 && $sql[$i-2] . $sql[$i-1] == '--')) {
				// starting position of the comment depends on the comment type
				$start_of_comment = (($sql[$i] == '#') ? $i : $i-2);
				// if no "\n" exits in the remaining string, checks for "\r"
				// (Mac eol style)
				$end_of_comment   = (strpos(' ' . $sql, "\012", $i+2))
								  ? strpos(' ' . $sql, "\012", $i+2)
								  : strpos(' ' . $sql, "\015", $i+2);
				if (!$end_of_comment) {
					// no eol found after '#', add the parsed part to the returned
					// array if required and exit
					if ($start_of_comment > 0) {
						$ret[]    = trim(substr($sql, 0, $start_of_comment));
					}
					return TRUE;
				} else {
					$sql          = substr($sql, 0, $start_of_comment)
								  . ltrim(substr($sql, $end_of_comment));
					$sql_len      = strlen($sql);
					$i--;
				} // end if...else
			} // end else if (is comment)

			// ... and finally disactivate the "/*!...*/" syntax if MySQL < 3.22.07
			else if ($release < 32270
					 && ($char == '!' && $i > 1  && $sql[$i-2] . $sql[$i-1] == '/*')) {
				$sql[$i] = ' ';
			} // end else if

			// loic1: send a fake header each 30 sec. to bypass browser timeout
			$time1     = time();
			if ($time1 >= $time0 + 30) {
				$time0 = $time1;
				header('X-pmaPing: Pong');
			} // end if
		} // end for

		// add any rest to the returned array
		if (!empty($sql) && ereg('[^[:space:]]+', $sql)) {
			$ret[] = $sql;
		}

		return TRUE;
	}
}

class Sushee_InstallFormField{
	var $label;
	var $comment;
	var $fieldname;
	var $value;
	var $mandatory;
	
	function Sushee_InstallFormField($label,$comment,$fieldname,$value=false,$mandatory=false){
		$this->label = $label;
		$this->comment = $comment;
		$this->fieldname = $fieldname;
		$this->value = $value;
		$this->mandatory = $mandatory;
	}
	
	function display(){
		if(!$this->value && isset($_POST[$this->fieldname])){
			$this->value = $_POST[$this->fieldname];
		}
		echo 
			'<tr>
				<td class="label">
					<label>'.$this->label.'</label>';
		if($this->comment)
			echo '<em>('.$this->comment.')</em>';
		echo
				'</td>
				<td class="input">
					<input type="text" name="'.$this->fieldname.'" value="'.$this->value.'"/>';
		if($this->mandatory)
			echo '<strong class="mandatory">*</strong>';
		echo		'</td>
			</tr>';
	}
}

class Sushee_InstallFieldSet{
	
	var $legend;
	var $components;
	
	function Sushee_InstallFieldSet($legend,$components){
		$this->legend = $legend;
		$this->components = $components;
	}
	
	function display(){
		echo 
			'<fieldset>
				<legend>'.$this->legend.'</legend>
				<table class="form">';
		foreach($this->components as $field){
			$field->display();
		}
		echo
			'</table>
		</fieldset>';
	}
	
}

class Sushee_InstallWarning{
	
	var $message;
	
	function Sushee_InstallWarning($message){
		$this->message = $message;
	}
	
	function display(){
		echo '<p class="warning">'.$this->message.'</p>';
	}
}

class Sushee_InstallError{
	
	var $message;
	
	function Sushee_InstallError($message){
		$this->message = $message;
	}
	
	function display(){
		echo '<p class="error">'.$this->message.'</p>';
	}
}

class Sushee_InstallForm{
	
	var $components;
	
	function Sushee_InstallForm($legend,$components){
		$this->legend = $legend;
		$this->components = $components;
	}
	
	function display(){
		echo 
			'<form action="install.php" method="post">
				<h1>'.$this->legend.'</h1>';
		foreach($this->components as $field){
			$field->display();
		}
		echo '<div class="submit-box"><input type="submit" value="Configure" onclick="this.disabled=\'disabled\';"/></div>';
		echo
			'</form>';
	}
	
}

class Sushee_OSDetector{
	
	static function execute(){
		$uname= php_uname();
		if (strtoupper(substr($uname, 0, 3))=="WIN")
			return "windows";
		else if(strtoupper(substr($uname, 0, 5))=="LINUX")
			return "linux";
		else
			return "other";
	}
}

class Sushee_XSLTDetector{
	
	var $config = false;
	
	function execute(){
		$this->config = '';
		// for windows, we include xsltproc in the zip
		if(Sushee_OSDetector::execute()=='windows'){
			$this->config = '$GLOBALS["use_libxslt"] = true;';
			return true;
		}
		// PHP xslt extension
		if(class_exists('XSLTProcessor')){
			$this->config = '$GLOBALS["use_phpxslt"] = true;';
			return true;
		}else{
			// xsltproc on command line
			$str = shell_exec('xsltproc -V');
			if(strpos($str,'libxml')!==false){
				$this->config = '$GLOBALS["use_libxslt"] = true;';
				return true;
			}else{
				return false;
			}
		}
		
	}
	
	function getConfig(){
		if($this->config===false){
			$this->execute();
		}
		return $this->config;
	}
	
}

class Sushee_SQLNameCleaner{
	
	static function execute($str){
		$forbidden_chars = array(';',',','\'','"','+','*','/','=','$','&','!','(',')','<','>',' ','.');
		return str_replace($forbidden_chars,'',$str);
	}
}

class Sushee_XMLEncoder{
	
	static function execute($str){
		$str = preg_replace ( '/&(?=[^#])|&$/','&amp;', $str);
		$str = str_replace("'", "&apos;", $str);
		$str = str_replace(">", "&gt;", $str); // because DB can contain XML
		$str = str_replace("<", "&lt;", $str);
		$str = str_replace("\"", "&quot;", $str);
		$str = str_replace("&#34;", "&quot;", $str);
		return $str;
	}
	
}

class Sushee_Password{
	
	static function execute($passStr){
		$nr=0x50305735;
		$nr2=0x12345671;
		$add=7;
		$charArr = preg_split("//", $passStr);

		    foreach ($charArr as $char) {
		              if (($char == '') || ($char == ' ') || ($char == '\t')) continue;
		              $charVal = ord($char);
		              $nr ^= ((($nr & 63) + $add) * $charVal) + ($nr << 8);
		              $nr &= 0x7fffffff;
		              $nr2 += ($nr2 << 8) ^ $nr;
		              $nr2 &= 0x7fffffff;
		              $add += $charVal;
		      }
		return sprintf("%08x%08x", $nr, $nr2);
	}
}

$installed = false;
$errors = array();
if(sizeof($_POST)>0){
	if(!$_POST['db_login'] || !$_POST['firstname'] || !$_POST['db_name'] || !$_POST['lastname'] || !$_POST['email']){
		$errors[] = new Sushee_InstallError('You have to fill all the fields marked by a red cross');
	}else{
		$db_name = Sushee_SQLNameCleaner::execute($_POST['db_name']);
		// connecting
		$db_conn = new Sushee_DBConnection();
		$res = $db_conn->connect($_POST['db_login'],$_POST['db_password']);
		if(!$res){
			$errors[] = new Sushee_InstallError('Could not connect to the database with the login and password given');
		}else{
			//creating config file
			$db_config_file = new Sushee_File('sushee.conf.php');
			$xslt_detect = new Sushee_XSLTDetector();
			$content = '<?php
$GLOBALS["SusheeRoot"]="'.getcwd().'";
'.$xslt_detect->getConfig().'
$GLOBALS["db_host"] = "localhost";
$GLOBALS["db_login"] = "'.$_POST['db_login'].'";
$GLOBALS["db_password"] = "'.$_POST['db_password'].'";
$GLOBALS["generic_backoffice_db"] = "'.$_POST['db_name'].'";
$GLOBALS["db_name"] = "'.$_POST['db_name'].'";
	?>';
			$db_config_file->save( $content );
			if(!$db_config_file->exists()){
				$errors[] = new Sushee_InstallError('Could not save the config file `sushee.conf.php` in the current directory. Make the directory writable or create the file by hand with this content (and relaunch this installer) : <br/>'.nl2br(Sushee_XMLEncoder::execute($content)));
			}else{
				// creating database
				$res = $db_conn->execute('CREATE DATABASE `'.$db_name.'`');
				$db_conn->goToDB($db_name);
				if(!$res){
					$errors[] = new Sushee_InstallError('Could not create the database : '.$db_conn->getError().' ('.$db_conn->getErrorCode().')');
				}else{
					
					// installing database
					$sql_file = new Sushee_File('sushee/Library/sql/install.sql');
					$res = $db_conn->execute($sql_file);

					if(!$res){
						$errors[] = new Sushee_InstallError('Could not create the complete database structure : '.$db_conn->getError().' ('.$db_conn->getErrorCode().') : '.$db_conn->getSQL());
					}else{
						// creating administrator user
						$password = Sushee_Password::execute($_POST['password']);
						$rs = $db_conn->execute('SELECT `ID` FROM `contacts` WHERE `Email1`="'.$db_conn->encode($_POST['email']).'" AND `Activity` = 1');
						if($rs)
							$row = $rs->fetchRow();
						else
							$row = false;
						if($row){
							$res = $db_conn->execute('UPDATE `contacts` SET `FirstName`="'.$db_conn->encode($_POST['firstname']).'",`LastName`="'.$db_conn->encode($_POST['lastname']).'",Password="'.$password.'" WHERE `Email1`="'.$db_conn->encode($_POST['email']).'"');
							$contactID = $row['ID'];
						}else{
							$res = $db_conn->execute('INSERT INTO `contacts`(`FirstName`,`LastName`,`Email1`,`Password`) VALUES("'.$db_conn->encode($_POST['firstname']).'","'.$db_conn->encode($_POST['lastname']).'","'.$db_conn->encode($_POST['email']).'","'.$password.'")');
							$contactID = $db_conn->getInsertedID();
						}
						
						
						if(!$contactID || is_object($contactID)){
							$errors[] = new Sushee_InstallError('Could not create the administator access : '.$db_conn->getError().' ('.$db_conn->getErrorCode().') : '.$db_conn->getSQL());
						}else{
							

							$db_conn->execute('INSERT INTO `dependencies`(`OriginID`,`TargetID`,`DependencyTypeID`) VALUES(2,\''.$contactID.'\',3)'); // 2 is the administrator keying, 3 is the deptype keyringUsers
							
							$installed = true;
							header("HTTP/1.1 301 Moved Permanently");
							header ('location: apps/');
							header("Connection: close");
							exit();
						}
					}

				}
			}

		}
	}
					
}
// Asks for DB params, for configuration
if(!$installed){
	echo
	'<html>
		<style>
			fieldset{
				margin-bottom:20px;
				width:100%;
			}
			legend{
				font-weight:bold;
			}
			table.form{
				width:100%;
			}
			td.label,td.input{
				width:50%;
			}
			td.input input{
				width:90%;
			}
			.submit-box{
				width:100%;
				text-align:center;;
			}
			.submit-box input{
				font-size:1.2em;
			}
			.warning,.error{
				color:orange;
				width:100%;
				text-align:center;
			}
			.warning{
				border:1px dotted orange;
				margin-left:10px;
				padding:4px
			}
			.warning a{
				color:orange;
			}
			.error{
				color:red;
			}
			form{
				width:600px;
			}
			.mandatory{
				color:red;
			}
		</style>
		<body>';
	
	$components = array();
	$xslt_detect = new Sushee_XSLTDetector();
	if($xslt_detect->execute()===false){
		$components[] = new Sushee_InstallWarning('Please install <br/><strong><a href="http://xmlsoft.org/XSLT/xsltproc2.html">xsltproc</a></strong> <br/>or <br/>the <strong><a href="http://be.php.net/manual/fr/xsl.installation.php">PHP XSL extension</a></strong> <br/>on your system. Its necessary to run Officity.');
	}else{
		
		$components[] = new Sushee_InstallFormField('MySQL Login','','db_login','',true);
		$components[] = new Sushee_InstallFormField('MySQL password','','db_password');
		$components[] = new Sushee_InstallFormField('MySQL DBName','will be created if it doesnt exist yet','db_name','sushee',true);
		$mysql_config = new Sushee_InstallFieldSet('MySQL configuration',$components);

		$components = array();
		$components[] = new Sushee_InstallFormField('Admin firstname','','firstname','',true);
		$components[] = new Sushee_InstallFormField('Admin lastname','','lastname','',true);
		$components[] = new Sushee_InstallFormField('Admin email','','email','',true);
		$components[] = new Sushee_InstallFormField('Admin password','','password','',true);
		$admin_config = new Sushee_InstallFieldSet('Administrator',$components);

		$components = array();
		// warnings given by an attempt to install the database
		if(is_array($errors) && sizeof($errors)>0){
			$components = $errors;
		}
		$components[] = $mysql_config;
		$components[] = $admin_config;
		$components[] = new Sushee_InstallWarning('Don\'t forget to delete this file once Officity is up and running');
	}
	
	
	$install_config = new Sushee_InstallForm('Configure Officity',$components);
	
	$install_config->display();
	
}


?>
	</body>
</html>