<?php

/***************************************************************************
 *	PROJECT: ZokiSoft Smart Catalog
 *
 *	This program is a commercial software and any kind of using
 *	it must agree to ZokiSoft License Agreement.
 *
 *	This notice may not be removed from the code.
 *
 *	Copyright 2007-2008 ZokiSoft
 *	http://www.zokisoft.com/
 ***************************************************************************/

class Catalog extends Controller
{

	var $aPageOrder = array(
			'_welcome' 			=> '0',
			'_pre_permitions'	=> '0',
			'_database'			=> '0',
			'_config'			=> '0',
			'_config_catalog'	=> '0',
			'_post_permitions'	=> '0',
			'_htaccess'			=> '0',
			'_finalize'			=> '0'	);

/*
*
*	Constructor
*
*/
	function Catalog()
	{

		parent::Controller();

		$this->load->helper('url');
        $this->load->helper('form');

// Debug output
//	$this->output->enable_profiler(TRUE);

	}


/*
*
*	index page
*
*/
	function index()
	{

// fill aPageOrder array with values from _POST
		foreach ( $_POST as $sName => $sValue )
			if ( array_key_exists($sName, $this->aPageOrder) )
				$this->aPageOrder[$sName] = $sValue;


		foreach ( $this->aPageOrder as $sPage => $sValue )
		{
// if this page is not completed yet
			if ( '0' == $sValue )
			{
				if ( method_exists($this,$sPage) )
				{

					echo $this->_header();

					echo $this->$sPage();

					echo $this->_footer();

					return true;

				}
				else
				{
					echo 'installation scenario is corrupted, please, refer to software vendor';
					return false;
				}
			}


		}

		return true;
	}

/*
*	make header
*/
	function _header()
	{

		ob_start();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<title>Catalog installation</title>

<style type="text/css">

.pagestyle{
	margin: 0px;
	padding: 0px;
	font-family: Verdana,Arial,Helvetica,sans-serif;
	background-color: #B5D5F0;
}

.caption{
	padding-left: 10px;
	line-height: 30px;
	vertical-align: middle;
	font-size: 14px;
	font-weight: bold;
	color: #ffffff;
	background-color: #71BFE6;
	border: 1px solid #ffffff;
}

.content{
	padding:10px;
	font-size: 14px;
	color: #000000;
	background-color: #B5D5F0;
	border: 0px solid #000000;
}

.content_caption{
	font-size: 14px;
	color: #003F5F;
}

.msg_ok{
	padding-left:10px;
	font-weight: bold;
	color:#ffffff;
}

.msg_no{
	padding-left:10px;
	font-weight: bold;
	color:#ff0000;
}

.navbar{
	padding-left: 10px;
	line-height: 30px;
	vertical-align: middle;
	text-align: center;
	font-size: 14px;
	font-weight: bold;
	color: #ffffff;
	background-color: #71BFE6;
	border: 1px solid #ffffff;
}

.navbar a{
	font-size: 14px;
	font-weight: bold;
	color: #ffffff;
}


</style>

		<script language="javascript" type="text/javascript">

		</script>

	</head>
<body class="pagestyle">
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


/*
*	make footer
*/
	function _footer()
	{

		ob_start();
?>
</body>
</html>
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


// =======================================================================
// =======================================================================
// pages
// =======================================================================
// =======================================================================

/*
*
*	welcome message
*
*/
	function _welcome()
	{

		$this->aPageOrder[__FUNCTION__] = '1';

		ob_start();
?>

<div class="caption">
Weclome to Smart Catalog Install module!
</div>

<div class="content">
	<div class="content_caption">
		To install and setup Smart Catalog you should pass thru several common steps.<br />
		Please, complete all this steps to avoid misconfiguration of this programm!
	</div>

	<form name="DataForm" id="DataForm" action="" method="POST">
	<?= $this->_GetHiddenVals(); ?>
	</form>
</div>

<div class="navbar">
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Go To next page</a>
</div>

<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


/*
*
*	set file permitions to write config files
*
*/
	function _pre_permitions()
	{

		$this->aPageOrder[__FUNCTION__] = '1';

		$aFileList = array();

// config files:
		$aFileList['config'][] = array('./system/application/config/config.php', 'rw');
		$aFileList['config'][] = array('./system/application/config/config_catalog.php', 'rw');
		$aFileList['config'][] = array('./system/application/config/database.php', 'rw');

// check permitions:
		foreach ( $aFileList['config'] as $key => $aFile )
			if ( !$aFileList['config'][$key][] = $this->_CheckFilePermitions($aFile[0], $aFile[1]) )
				$this->aPageOrder[__FUNCTION__] = '0';

// uploads:
//		$aFileList['uploads'][] = array('./system/application/uploads/file', 'rw');
		$aFileList['uploads'][] = array('./system/application/uploads/post', 'rwx');
		$aFileList['uploads'][] = array('./views/_page', 'rwx');
		$aFileList['uploads'][] = array('./system/application/uploads/users', 'rwx');
		$aFileList['uploads'][] = array('./system/application/uploads/category', 'rwx');

// check permitions:
		foreach ( $aFileList['uploads'] as $key => $aFile )
			if ( !$aFileList['uploads'][$key][] = $this->_CheckFilePermitions($aFile[0], $aFile[1]) )
				$this->aPageOrder[__FUNCTION__] = '0';

// xml:
/*
		$aFileList['xml'][] = array('./views/_page', 'rwx');

// check permitions:
		foreach ( $aFileList['xml'] as $key => $aFile )
			if ( !$aFileList['xml'][$key][] = $this->_CheckFilePermitions($aFile[0], $aFile[1]) )
				$this->aPageOrder[__FUNCTION__] = '0';
*/

		ob_start();
?>
<div class="caption">
	This is file permitions page ;-)
	<br />
	You should manually change file permissions according this list:
</div>

<div class="content">
	<div class="content_caption">
		set this files to 666 mode to allow script modify them during runtime:
	</div>

	<ul>
		<? foreach ( $aFileList['config'] as $aFile ) : ?>
			<li>
				<?= $aFile[0] . ( $aFile[2] ? '<span class="msg_ok">ok</span>' : '<span class="msg_no">no</span>' ) ?>
			</li>
		<? endforeach; ?>
	</ul>

	<div class="content_caption">
		More over, you have to set in 777 mode following folders
		<br />
		( this is storage for user uploads ):
	</div>

	<ul>
		<? foreach ( $aFileList['uploads'] as $aFile ) : ?>
			<li>
				<?= $aFile[0] . ( $aFile[2] ? '<span class="msg_ok">ok</span>' : '<span class="msg_no">no</span>' ) ?>
			</li>
		<? endforeach; ?>
	</ul>
<!--
	<div class="content_caption">
		Eventually, dont fogret static pages -
		Set permissions for this directory to 666:
	</div>

	<ul>
		<? //foreach ( $aFileList['xml'] as $aFile ) : ?>
			<li>
				<? //$aFile[0] . ( $aFile[2] ? '<span class="msg_ok">ok</span>' : '<span class="msg_no">no</span>' ) ?>
			</li>
		<? //endforeach; ?>
	</ul>
-->
	<form name="DataForm" id="DataForm" action="" method="POST">
	<?= $this->_GetHiddenVals(); ?>
	</form>

</div>

<div class="navbar">
	<? if ( '0' == $this->aPageOrder[__FUNCTION__] ) : ?>
	if against some files you see red 'no' - you should set permitions to these files.
	<br />
	and press <a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">REFRESH</a></a> to update this page.
	<? else : ?>
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Next Page</a>
	<? endif; ?>
</div>

<?

		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}



/*
*
*	database
*
*/
	function _database()
	{

		$sErrMsg = '';

		if ( isset($_POST['DBUser']) )
		{

			$rLink = @mysql_connect ( $_POST['DBHost'], $_POST['DBUser'], $_POST['DBPassword']);
			if ( !$rLink )
			{
				$sErrMsg .= 'I cannot connect to the database because: ' . mysql_error() . '<br />';;
			}
			else
			{

				$bDb = @mysql_select_db ($_POST['DBName'], $rLink);

// drop database
/*
				if ( $bDb && !empty($_POST['DBDrop']) )
				{
					$sSql = 'DROP DATABASE IF EXISTS `' . $_POST['DBName'] . '`';
//					$rRes = mysql_query($sSql, $rLink);
				}
*/

// create database
				if ( !$bDb && !empty($_POST['DBCreate']) )
				{

					$sSql = 'CREATE DATABASE `' . $_POST['DBName'] . '`';
					$rRes = mysql_query($sSql, $rLink);

					if ( !$rRes )
					{
						$sErrMsg .= 'I cannot connect to the database because: ' . mysql_error() . '<br />';
					}
					else
					{
						$bDb = @mysql_select_db ($_POST['DBName'], $rLink);
					}
				}

				if ( !$bDb )
				{
					$sErrMsg .= 'Can\'t use database "' . $_POST['DBName'] . '": ' . mysql_error()  . '<br />';
				}
				else
				{

// upload data to DB
					$sSqlFile = './system/application/controllers/install/catalog.sql';
					$aSql = @file($sSqlFile);
				    if ( !is_array($aSql) )
    					$sErrMsg .= 'Can\'t read database file "' . $sSqlFile . '"<br />';

					$sCommand = '';

					foreach ( $aSql as $sLine )
					{

						$sLine = trim($sLine);

						if ( empty($sLine) ) continue;
						if ( '#' == $sLine[0] ) continue;
						if ( '-' == $sLine[0] ) continue;

						$sCommand .= $sLine;
        				if ( ';' != $sCommand[strlen($sCommand)-1] ) continue;

//				        echo $sCommand . '<hr />';
						$rRes = @mysql_query( $sCommand, $rLink );

						if ( !$rRes )
            				$sErrMsg .= 'Invalid instruction:<br />' . $sCommand . '<br />' . mysql_error() . "<br />";

						$sCommand = '';

					}

// write file

					$aVars = array(
						'hostname'	=>	$_POST['DBHost'],
						'username'	=>	$_POST['DBUser'],
						'password'	=>	$_POST['DBPassword'],
						'database'	=>	$_POST['DBName']
					);

					$this->_WriteFile( './system/application/config/database.php', $aVars );

					$this->aPageOrder[__FUNCTION__] = '1';

				}
			}
		}


		ob_start();
?>

<div class="caption">
	Now let's establish database connection
</div>

<div class="content">

	<? if ( !empty($sErrMsg) ) : ?>
		<div class='msg_no' style="margin:10px;text-align: center;"><?=$sErrMsg?></div>
	<? endif; ?>

	<form id="DataForm" name="DataForm" action="" method="post">
		<?= $this->_GetHiddenVals(); ?>
		<? if ( '0' ==  $this->aPageOrder[__FUNCTION__] ) : ?>
			DataBase User:<br /><input type="text" name="DBUser" value="<?=@$_POST['DBUser']?>" /><br />
			DataBase Password:<br /><input type="text" name="DBPassword" value="<?=@$_POST['DBPassword']?>" /><br />
			DataBase Name:<br /><input type="text" name="DBName" value="<?=@$_POST['DBName']?>" /><br />
			<input type="checkbox" name="DBCreate" id="DBCreate" />Try to Create DataBase if it is not exist;<br />
<!--			<input type="checkbox" name="DBDrop" id="DBDrop" />Drop Old DataBase;<br /> -->
			DataBase Host:<br /><input type="text" name="DBHost" value="localhost" /><br />
		<? else : ?>
			<div class='msg_ok'>
				The database has been created.
			</div>
		<? endif; ?>
	</form>

</div>

<div class="navbar">
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">NextPage</a>
</div>
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


/*
*
*	config
*
*/
	function _config()
	{

		if ( !empty($_POST['base_url']) && !empty($_POST['base_dir']) && !empty($_POST['encryption_key']) )
		{
// write file
					$aVars = array(
						'base_url'			=>	$_POST['base_url'],
						'base_dir'			=>	$_POST['base_dir'],
						'encryption_key'	=>	$_POST['encryption_key']
					);

					if ( '/' != substr($aVars['base_url'],-1,1) )
						$aVars['base_url'] .= '/';

					if ( '/' != substr($aVars['base_dir'],-1,1) )
						$aVars['base_dir'] .= '/';
						
					$this->_WriteFile( './system/application/config/config.php', $aVars );

					$this->aPageOrder[__FUNCTION__] = '1';

		}


		if (function_exists('realpath') AND @realpath(dirname(__FILE__)) !== FALSE )
		{
			$system_folder = str_replace("\\", "/", realpath(dirname(__FILE__)));
			$system_folder = substr($system_folder,0,strpos($system_folder, 'system'));
		}
		else
			$system_folder = '';

		$system_url = '';
		$system_url = (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : @getenv('SERVER_NAME');
		if ( empty($system_url) )
		 	$system_url = (isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : @getenv('HTTP_HOST');

		$system_url = 'http://' . $system_url;

		ob_start();

?>

<div class="caption">
	Setting up the config file:
</div>

<div class="content">

	<form id="DataForm" name="DataForm" action="" method="post">
		<?= $this->_GetHiddenVals(); ?>
		<? if ( '0' ==  $this->aPageOrder[__FUNCTION__] ) : ?>
			Your script URL:<br />
			<input type="text" name="base_url" value="<?=$system_url?>" size="40" /><br />
			Path to root directory:<br />
			<input type="text" name="base_dir" value="<?=$system_folder?>" size="40" /><br />
			Secret Word:<br />
			<input type="text" name="encryption_key" value="" size="40" /><br />
		<? else : ?>
			<div class='msg_ok'>
				File has been updated.
			</div>
		<? endif; ?>
	</form>

</div>

<div class="navbar">
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Next Page</a>
</div>
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}



/*
*
*	config general
*
*/
	function _config_catalog()
	{

		if ( !empty($_POST['mail_general']) )
		{
// write file
					$aVars = array(
						'mail_general'	=>	$_POST['mail_general'],
						'mail_reply'	=>	( $_POST['mail_reply'] ? $_POST['mail_reply'] : $_POST['mail_general'] ),
						'mail_admin'	=>	( $_POST['mail_admin'] ? $_POST['mail_admin'] : $_POST['mail_general'] ),
						'mail_links'	=>	( $_POST['mail_links'] ? $_POST['mail_links'] : $_POST['mail_general'] ),
						'mail_advert'	=>	( $_POST['mail_advert'] ? $_POST['mail_advert'] : $_POST['mail_general'] )
					);

					$this->_WriteFile( './system/application/config/config_catalog.php', $aVars );

					$this->aPageOrder[__FUNCTION__] = '1';

		}


		ob_start();
?>

<div class="caption">
	Setting up emails:<br />
</div>

<div class="content">

	<form id="DataForm" name="DataForm" action="" method="post">
		<?= $this->_GetHiddenVals(); ?>
		<? if ( '0' ==  $this->aPageOrder[__FUNCTION__] ) : ?>
			General Mail<br />
			<input type="text" name="mail_general" value="" size="40" /><br />
			Reply Mail<br />
			<input type="text" name="mail_reply" value="" size="40" /><br />
			Admin Mail<br />
			<input type="text" name="mail_admin" value="" size="40" /><br />
			Links Mail<br />
			<input type="text" name="mail_links" value="" size="40" /><br />
			Advertise Mail<br />
			<input type="text" name="mail_advert" value="" size="40" /><br />
		<? else : ?>
			<div class='msg_ok'>
				File has been updated
			</div>
		<? endif; ?>
	</form>
</div>

<div class="navbar">
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Next Page</a>
</div>

<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}



/*
*
*	restore permitions to some files for sequrity reasons
*
*/
	function _post_permitions()
	{

		$this->aPageOrder[__FUNCTION__] = '1';

		$aFileList = array();

// config files:
		$aFileList['config'][] = array('./system/application/config/config.php', 'r');
		$aFileList['config'][] = array('./system/application/config/config_catalog.php', 'r');
		$aFileList['config'][] = array('./system/application/config/database.php', 'r');

// check permitions:
		foreach ( $aFileList['config'] as $key => $aFile )
			if ( !$aFileList['config'][$key][] = $this->_CheckFilePermitions($aFile[0], $aFile[1]) )
				$this->aPageOrder[__FUNCTION__] = '0';



		ob_start();
?>

<div class="caption">
	This is file permitions page AGAIN ;-)
	<br />
	You should return this files to 644 mode for security reasons:
</div>

<div class="content">

	<ul>
		<? foreach ( $aFileList['config'] as $aFile ) : ?>
			<li>
				<?= $aFile[0] . ( $aFile[2] ? '<span class="msg_ok">ok</span>' : '<span class="msg_no">no</span>' ) ?>
			</li>
		<? endforeach; ?>
	</ul>

	<form name="DataForm" id="DataForm" action="" method="POST">
	<?= $this->_GetHiddenVals(); ?>
	</form>

</div>

<div class="navbar">
	<? if ( '0' == $this->aPageOrder[__FUNCTION__] ) : ?>
		if against some files you see red 'no' - you should set permitions to these files.
		<br />
		and press <a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">REFRESH</a></a> to update this page.
	<? else : ?>
		<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Next Page</a>
	<? endif; ?>
</div>
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


	function _htaccess()
	{

		$this->aPageOrder[__FUNCTION__] = '1';

		ob_start();
?>
<div class="caption">
	.htaccess file
</div>

<div class="content">

	<div class="content_caption">
		If you are installing this catalog to subfolder of you primary site, you should add correct <b>BaseName</b> rule
		in <i>.htaccess</i> file.
		<br />
		&nbsp;
		<br />
		For example, if you place catalog to subfolder 'public_html/catalog/', and you access Catalog via browser using path<br />
		<i>www.your_site.com/catalog</i>
		<br />
		&nbsp;
		<br />
		You should change BaseName from<br />
		<i>RewriteBase /</i><br />
		to<br />
		<i>RewriteBase /catalog/</i>
	</div>

	<form id="DataForm" name="DataForm" action="" method="post">
	<?= $this->_GetHiddenVals(); ?>
	</form>

</div>

<div class="navbar">
	<a href="javascript: void(0);" onClick="javascript: document.getElementById('DataForm').submit();">Next Page</a>
</div>
<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}


/*
*
*	end of setup
*
*/
	function _finalize()
	{

		ob_start();
?>
<div class="caption">
	Finish.
</div>

<div class="content">
	<div class="content_caption">
		You successfully pass all setup steps and now you can run Smart Catalog.
		<br />
		&nbsp;
		<br />
		<i>Warning:</i>Dont forget delete or at least remove this module from catalog.
		</br />
		To do this, go to root directory of catalog, then go to <i>system/application/controllers</i>.
		<br />
		Folder <i>install</i> is exactly that one you want :-)
		<br />
		&nbsp;
		<br />
		You can login to catalog using default admin profile:
		<br />
		login:&nbsp;<b>admin</b>
		<br />
		pass:&nbsp;<b>zoki</b>
	</div>
</div>

<div class="navbar">
	<a href="/" >Finish</a>
</div>

<?
		$sContent = ob_get_contents();
		ob_end_clean();

		return $sContent;

	}

// ===========================================================================
// UTILS =====================================================================
// ===========================================================================

	function _GetFilePermissions($sFilename)
	{

		clearstatcache();

		$sFullPermitions = sprintf('%o', fileperms($sFilename));

		return substr($sFullPermitions, strlen($sFullPermitions) - 3);

	}


	function _CheckFilePermitions($sFilename, $sPermitions )
	{

		clearstatcache();

		if ( !($iPerms = @fileperms($sFilename) ) )
			return false;

//echo $sFilename . '->' . substr(sprintf('%o', $iPerms), -4) . '<br />';

// check only third group
// Read
		if ( false !== strpos($sPermitions, 'r') )
		{
			if ( !($iPerms & 0x0004) )
				return false;
		}
		else
		{
			if ( $iPerms & 0x0004 )
				return false;
		}

// Write
		if ( false !== strpos($sPermitions, 'w') )
		{
			if ( !($iPerms & 0x0002) )
				return false;
		}
		else
		{
			if ( $iPerms & 0x0002 )
				return false;
		}

// eXecute
		if ( false !== strpos($sPermitions, 'x') )
		{
			if ( !($iPerms & 0x0001) )
				return false;
		}
		else
		{
			if ( $iPerms & 0x0001 )
				return false;
		}

		return true;

	}


	function _GetHiddenVals()
	{
		$sReturn = '';
		foreach ( $this->aPageOrder as $sPage => $sValue )
			if ( '1' == $sValue )
				$sReturn .= '<input type="hidden" name="' . $sPage . '" value="1" />';

		return $sReturn;
	}


	function _WriteFile( $sFileName, $aVars )
	{

		$sContent = file_get_contents($sFileName);

		foreach ( $aVars as $sKey => $sValue )
		{
			$aPattern[] = '/%' . $sKey . '%/';
			$aReplacement[] = $sValue;
		}

		$sContent = preg_replace( $aPattern, $aReplacement, $sContent);

		//file_put_contents($sFileName, $sContent);
		$f = fopen($sFileName, 'w');
		fwrite($f, $sContent);
		fclose($f);

	}

}
?>
