<?php
//POST PARAMS
$_POST['dbaction']			= isset($_POST['dbaction'])  ? $_POST['dbaction'] : 'create';
$_POST['dbhost']			= isset($_POST['dbhost'])    ? DUPX_U::sanitize(trim($_POST['dbhost'])) : null;
$_POST['dbname']			= isset($_POST['dbname'])    ? trim($_POST['dbname']) : null;
$_POST['dbuser']			= isset($_POST['dbuser'])    ? $_POST['dbuser'] : null;
$_POST['dbpass']			= isset($_POST['dbpass'])    ? $_POST['dbpass'] : null;
$_POST['dbcharset']			= isset($_POST['dbcharset']) ? DUPX_U::sanitize(trim($_POST['dbcharset'])) : $GLOBALS['DBCHARSET_DEFAULT'];
$_POST['dbcollate']			= isset($_POST['dbcollate']) ? DUPX_U::sanitize(trim($_POST['dbcollate'])) : $GLOBALS['DBCOLLATE_DEFAULT'];
$_POST['dbnbsp']			= (isset($_POST['dbnbsp']) && $_POST['dbnbsp'] == '1') ? true : false;
$_POST['ssl_admin']			= (isset($_POST['ssl_admin']))  ? true : false;
$_POST['cache_wp']			= (isset($_POST['cache_wp']))   ? true : false;
$_POST['cache_path']		= (isset($_POST['cache_path'])) ? true : false;
$_POST['archive_name']		= isset($_POST['archive_name']) ? $_POST['archive_name'] : null;
$_POST['retain_config']		= (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false;
$_POST['dbcollatefb']       = isset($_POST['dbcollatefb']) ? $_POST['dbcollatefb'] : false;

//LOGGING
$POST_LOG = $_POST;
unset($POST_LOG['dbpass']);
ksort($POST_LOG);

//PAGE VARS
$date_time      = @date('h:i:s');
$root_path		= DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
$ajax2_start	= DUPX_U::getMicrotime();
$JSON = array();
$JSON['pass'] = 0;

/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end*/
$ajax1_error_level = error_reporting();
error_reporting(E_ERROR);

//====================================================================================================
//DATABASE TEST CONNECTION
//====================================================================================================
if (isset($_GET['dbtest']))
{
	$html     = "";
	$baseport =  parse_url($_POST['dbhost'], PHP_URL_PORT);
	$dbConn   = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']);
	$dbErr	  = mysqli_connect_error();

	$dbFound  = mysqli_select_db($dbConn, $_POST['dbname']);
	$port_view = (is_int($baseport) || substr($_POST['dbhost'], -1) == ":") ? "Port=[Set in Host]" : "Port={$_POST['dbport']}";

	$tstSrv   = ($dbConn)  ? "<div class='dupx-pass'>Success</div>" : "<div class='dupx-fail'>Fail</div>";
	$tstDB    = ($dbFound) ? "<div class='dupx-pass'>Success</div>" : "<div class='dupx-fail'>Fail</div>";

    $dbversion_info         = DUPX_DB::getServerInfo($dbConn);
    $dbversion_info         = empty($dbversion_info) ? 'no connection' : $dbversion_info;
    $dbversion_info_fail    = $dbConn && version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0;

    $dbversion_compat       = DUPX_DB::getVersion($dbConn);
	$dbversion_compat       = empty($dbversion_compat) ? 'no connection' : $dbversion_compat;
    $dbversion_compat_fail  = $dbConn && version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0;

    $tstInfo = ($dbversion_info_fail)
		? "<div class='dupx-notice'>{$dbversion_info}</div>"
        : "<div class='dupx-pass'>{$dbversion_info}</div>";

	$tstCompat = ($dbversion_compat_fail)
		? "<div class='dupx-notice'>This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]</div>"
		: "<div class='dupx-pass'>This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]</div>";

	$html	 .= <<<DATA
	<div class='s2-db-test'>
		<small>
			Using Connection String:<br/>
			Host={$_POST['dbhost']}; Database={$_POST['dbname']}; Uid={$_POST['dbuser']}; Pwd={$_POST['dbpass']}; {$port_view}
		</small>
		<table class='s2-db-test-dtls'>
			<tr>
				<td>Host:</td>
				<td>{$tstSrv}</td>
			</tr>
			<tr>
				<td>Database:</td>
				<td>{$tstDB}</td>
			</tr>
			<tr>
				<td>Version:</td>
				<td>{$tstInfo}</td>
			</tr>
            <tr>
				<td>Compatibility:</td>
				<td>{$tstCompat}</td>
			</tr>
		</table>
DATA;

	//--------------------------------
	//WARNING: Unable to connect
	$html .=  (!$dbConn ||  !$dbFound)
		? "<div class='warn-msg'>" . ERR_DBCONNECT_INFO .  "</div>"
		: '';

	//WARNING: DB has tables with create option
	if ($_POST['dbaction'] == 'create')
	{
		$tblcount = DUPX_DB::countTables($dbConn, $_POST['dbname']);
		$html .= ($tblcount > 0)
			? "<div class='warn-msg'><b>WARNING:</b> " . sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount) . "</div>"
			: '';
	}

	//WARNNG: Input has utf8
	$dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']);
	$dbUTF8_tst  = false;
	foreach ($dbConnItems as $value) {
		if (DUPX_U::isNonASCII($value)) {
			$dbUTF8_tst = true;
			break;
		}
	}

    //WARNING: UTF8 Data in Connection String
	$html .=  (!$dbConn && $dbUTF8_tst)
		? "<div class='warn-msg'><b>WARNING:</b> " . ERR_TESTDB_UTF8 .  "</div>"
		: '';

	//NOTICE: Version Too Low
	$html .=  ($dbversion_info_fail)
		? "<div class='warn-msg'><b>NOTICE:</b> " . ERR_TESTDB_VERSION_INFO . "</div>"
		: '';

    //NOTICE: Version Incompatibility
	$html .=  ($dbversion_compat_fail)
		? "<div class='warn-msg'><b>NOTICE:</b> " . ERR_TESTDB_VERSION_COMPAT . "</div>"
		: '';

	$html .= "</div>";
	die($html);
}

//===============================
//ERROR MESSAGES
//===============================

//ERR_MAKELOG
($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG);

//ERR_MYSQLI_SUPPORT
function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT);

//ERR_DBCONNECT
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']);
@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}");
($dbh) or DUPX_Log::error(ERR_DBCONNECT . mysqli_connect_error());
if ($_POST['dbaction'] == 'empty') {
	mysqli_select_db($dbh, $_POST['dbname']) or DUPX_Log::error(sprintf(ERR_DBCREATE, $_POST['dbname']));
}
//ERR_DBEMPTY
if ($_POST['dbaction'] == 'create' ) {
	$tblcount = DUPX_DB::countTables($dbh, $_POST['dbname']);
	if ($tblcount > 0) {
		DUPX_Log::error(sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount));
	}
}



$log = <<<LOG
\n\n********************************************************************************
* DUPLICATOR-LITE: INSTALL-LOG
* STEP-2 START @ {$date_time}
* NOTICE: Do NOT post to public sites or forums
********************************************************************************
LOG;
DUPX_Log::info($log);

$log  = "--------------------------------------\n";
$log .= "POST DATA\n";
$log .= "--------------------------------------\n";
$log .= print_r($POST_LOG, true);
DUPX_Log::info($log, 2);


//====================================================================================================
//DATABASE ROUTINES
//====================================================================================================
$log = '';
$faq_url = $GLOBALS['FAQ_URL'];
$utm_prefix = '?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=';
$db_file_size = filesize('database.sql');
$php_mem = $GLOBALS['PHP_MEMORY_LIMIT'];
$php_mem_range = DUPX_U::getBytes($GLOBALS['PHP_MEMORY_LIMIT']);
$php_mem_range = $php_mem_range == null ?  0 : $php_mem_range - 5000000; //5 MB Buffer

//Fatal Memory errors from file_get_contents is not catchable.
//Try to warn ahead of time with a buffer in memory difference
if ($db_file_size >= $php_mem_range  && $php_mem_range != 0)
{
	$db_file_size = DUPX_U::readableByteSize($db_file_size);
	$msg = "\nWARNING: The database script is '{$db_file_size}' in size.  The PHP memory allocation is set\n";
	$msg .= "at '{$php_mem}'.  There is a high possibility that the installer script will fail with\n";
	$msg .= "a memory allocation error when trying to load the database.sql file.  It is\n";
	$msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n";
    $msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n";
	DUPX_Log::info($msg);
}

@chmod("{$root_path}/database.sql", 0777);
$sql_file = file_get_contents('database.sql', true);

//ERROR: Reading database.sql file
if ($sql_file === FALSE || strlen($sql_file) < 10)
{
	$msg = "<b>Unable to read the database.sql file from the archive.  Please check these items:</b> <br/>";
	$msg .= "1. Validate permissions and/or group-owner rights on these items: <br/>";
	$msg .= " - File: database.sql <br/> - Directory: [{$root_path}] <br/>";
    $msg .= "<i>see: <a href='{$faq_url}{$utm_prefix}inst_step2_dbperms#faq-trouble-055-q' target='_blank'>{$faq_url}#faq-trouble-055-q</a></i> <br/>";
	$msg .= "2. Validate the database.sql file exists and is in the root of the archive.zip file <br/>";
	$msg .= "<i>see: <a href='{$faq_url}{$utm_prefix}inst_step2_sqlroot#faq-installer-020-q' target='_blank'>{$faq_url}#faq-installer-020-q</a></i> <br/>";
	DUPX_Log::error($msg);
}

//Removes invalid space characters
//Complex Subject See: http://webcollab.sourceforge.net/unicode.html
if ($_POST['dbnbsp'])
{
	DUPX_Log::info("NOTICE: Ran fix non-breaking space characters\n");
	$sql_file = preg_replace('/\xC2\xA0/', ' ', $sql_file);
}

//Write new contents to install-data.sql
$sql_file_copy_status   = file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file);
$sql_result_file_data	= explode(";\n", $sql_file);
$sql_result_file_length = count($sql_result_file_data);
$sql_result_file_path	= "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}";
$sql_file = null;
$db_collatefb_log = '';

if($_POST['dbcollatefb']){
    $supportedCollations = DUPX_DB::getSupportedCollationsList($dbh);
    $collation_arr = array(
        'utf8mb4_unicode_520_ci',
        'utf8mb4_unicode_520',
        'utf8mb4_unicode_ci',
        'utf8mb4',
        'utf8_unicode_520_ci',
        'utf8_unicode_520',
        'utf8_unicode_ci',
        'utf8'
    );
    $latest_supported_collation = '';
    $latest_supported_index = -1;

    foreach ($collation_arr as $key => $val){
        if(in_array($val,$supportedCollations)){
            $latest_supported_collation = $val;
            $latest_supported_index = $key;
            break;
        }
    }

	//No need to replace if current DB is up to date
    if($latest_supported_index != 0){
        for($i=0; $i < $latest_supported_index; $i++){
            foreach ($sql_result_file_data as $index => $col_sql_query){
                if(strpos($col_sql_query,$collation_arr[$i]) !== false){
                    $sql_result_file_data[$index] = str_replace($collation_arr[$i], $latest_supported_collation, $col_sql_query);
                    if(strpos($collation_arr[$i],'utf8mb4') !== false && strpos($latest_supported_collation,'utf8mb4') === false){
                        $sql_result_file_data[$index] = str_replace('utf8mb4','utf8',$sql_result_file_data[$index]);
                    }
					$sub_query = str_replace("\n", '', substr($col_sql_query, 0, 75));
                    $db_collatefb_log .= "   - Collation '{$collation_arr[$i]}' set to '{$latest_supported_collation}' on query [{$sub_query}...]\n";
                }
            }
        }
    }
}

//WARNING: Create installer-data.sql failed
if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path))
{
	$sql_file_size = DUPX_U::readableByteSize(filesize('database.sql'));
	$msg  = "\nWARNING: Unable to properly copy database.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}.  Please check these items:\n";
	$msg .= "- Validate permissions and/or group-owner rights on database.sql and directory [{$root_path}] \n";
	$msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n";
	DUPX_Log::info($msg);
}

//=================================
//START DB RUN
@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}");
@mysqli_query($dbh, "SET max_allowed_packet = {$GLOBALS['DB_MAX_PACKETS']}");
DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);

//Will set mode to null only for this db handle session
//sql_mode can cause db create issues on some systems
$qry_session_custom = true;
switch ($_POST['dbmysqlmode']) {
	case 'DISABLE':
		@mysqli_query($dbh, "SET SESSION sql_mode = ''");
		break;
	case 'CUSTOM':
		$dbmysqlmode_opts	 = $_POST['dbmysqlmode_opts'];
		$qry_session_custom	 = @mysqli_query($dbh, "SET SESSION sql_mode = '{$dbmysqlmode_opts}'");
		if ($qry_session_custom == false) {
			$sql_error	 = mysqli_error($dbh);
			$log		 = "WARNING: Trying to set a custom sql_mode setting issue has been detected:\n{$sql_error}.\n";
			$log		 .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n";
		}
		break;
}

//Set defaults in-case the variable could not be read
$dbvar_maxtime		= DUPX_DB::getVariable($dbh, 'wait_timeout');
$dbvar_maxpacks		= DUPX_DB::getVariable($dbh, 'max_allowed_packet');
$dbvar_sqlmode		= DUPX_DB::getVariable($dbh, 'sql_mode');
$dbvar_maxtime		= is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime;
$dbvar_maxpacks		= is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks;
$dbvar_sqlmode		= empty($dbvar_sqlmode) ? 'NOT_SET'  : $dbvar_sqlmode;
$dbvar_version		= DUPX_DB::getVersion($dbh);
$sql_file_size1		= DUPX_U::readableByteSize(@filesize("database.sql"));
$sql_file_size2		= DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}"));
$db_collatefb		= isset($_POST['dbcollatefb']) ? 'On' : 'Off';


DUPX_Log::info("--------------------------------------");
DUPX_Log::info("DATABASE ENVIRONMENT");
DUPX_Log::info("--------------------------------------");
DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}");
DUPX_Log::info("FILE SIZE:\tdatabase.sql ({$sql_file_size1}) - installer-data.sql ({$sql_file_size2})");
DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}");
DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}");
DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}");
DUPX_Log::info("NEW SQL FILE:\t[{$sql_result_file_path}]");
DUPX_Log::info("COLLATE RESET:\t{$db_collatefb}\n{$db_collatefb_log}");

if ($qry_session_custom == false) {
	DUPX_Log::info("\n{$log}\n");
}

//CREATE DB
switch ($_POST['dbaction']) {
	case "create":
		mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `{$_POST['dbname']}`");
		mysqli_select_db($dbh, $_POST['dbname'])
		or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $_POST['dbname']));
		break;
	case "empty":
		//DROP DB TABLES
		$drop_log = "Database already empty. Ready for install.";
		$sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'";
		$found_tables = null;
		if ($result = mysqli_query($dbh, $sql)) {
			while ($row = mysqli_fetch_row($result)) {
				$found_tables[] = $row[0];
			}
			if (count($found_tables) > 0) {
				foreach ($found_tables as $table_name) {
					$sql = "DROP TABLE `{$_POST['dbname']}`.`{$table_name}`";
					if (!$result = mysqli_query($dbh, $sql)) {
						DUPX_Log::error(sprintf(ERR_DBTRYCLEAN, $_POST['dbname']));
					}
				}
			}
			$drop_log = count($found_tables);
		}
		break;
}


//WRITE DATA
DUPX_Log::info("--------------------------------------");
DUPX_Log::info("DATABASE RESULTS");
DUPX_Log::info("--------------------------------------");
$profile_start = DUPX_U::getMicrotime();
$fcgi_buffer_pool = 5000;
$fcgi_buffer_count = 0;
$dbquery_rows = 0;
$dbtable_rows = 1;
$dbquery_errs = 0;
$counter = 0;
@mysqli_autocommit($dbh, false);

while ($counter < $sql_result_file_length) {

	$query_strlen = strlen(trim($sql_result_file_data[$counter]));

	if ($dbvar_maxpacks < $query_strlen) {

		DUPX_Log::info("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]");
		$dbquery_errs++;

	} elseif ($query_strlen > 0) {

		@mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter])));
		$err = mysqli_error($dbh);

		//Check to make sure the connection is alive
		if (!empty($err)) {

			if (!mysqli_ping($dbh)) {
				mysqli_close($dbh);
				$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport'] );
				// Reset session setup
				@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}");
				DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
			}
			DUPX_Log::info("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]");
			$dbquery_errs++;

		//Buffer data to browser to keep connection open
		} else {
			if ($GLOBALS['DB_FCGI_FLUSH'] && $fcgi_buffer_count++ > $fcgi_buffer_pool) {
				$fcgi_buffer_count = 0;
				DUPX_U::fcgiFlush();
			}
			$dbquery_rows++;
		}
	}
	$counter++;
}
@mysqli_commit($dbh);
@mysqli_autocommit($dbh, true);

DUPX_Log::info("ERRORS FOUND:\t{$dbquery_errs}");
DUPX_Log::info("TABLES DROPPED:\t{$drop_log}");
DUPX_Log::info("QUERIES RAN:\t{$dbquery_rows}\n");

$dbtable_count = 0;
if ($result = mysqli_query($dbh, "SHOW TABLES")) {
	while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
		$table_rows = DUPX_DB::countTableRows($dbh, $row[0]);
		$dbtable_rows += $table_rows;
		DUPX_Log::info("{$row[0]}: ({$table_rows})");
		$dbtable_count++;
	}
	@mysqli_free_result($result);
}

if ($dbtable_count == 0) {
	DUPX_Log::error("No tables where created during step 2 of the install.  Please review the <a href='installer-log.txt' target='install_log'>installer-log.txt</a> file for
		ERROR messages.  You may have to manually run the installer-data.sql with a tool like phpmyadmin to validate the data input.  If you have enabled compatibility mode
		during the package creation process then the database server version your using may not be compatible with this script.\n");
}


//DATA CLEANUP: Perform Transient Cache Cleanup
//Remove all duplicator entries and record this one since this is a new install.
$dbdelete_count = 0;
@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}duplicator_packages`");
$dbdelete_count1 = @mysqli_affected_rows($dbh) or 0;
@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')");
$dbdelete_count2 = @mysqli_affected_rows($dbh) or 0;
$dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2));
DUPX_Log::info("\nRemoved '{$dbdelete_count}' cache/transient rows");
//Reset Duplicator Options
foreach ($GLOBALS['FW_OPTS_DELETE'] as $value) {
	mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` = '{$value}'");
}

@mysqli_close($dbh);

//FINAL RESULTS
$profile_end	= DUPX_U::getMicrotime();
$ajax2_end		= DUPX_U::getMicrotime();
$ajax1_sum		= DUPX_U::elapsedTime($ajax2_end, $ajax2_start);
DUPX_Log::info("\nCREATE/INSTALL RUNTIME: " . DUPX_U::elapsedTime($profile_end, $profile_start));
DUPX_Log::info('STEP-2 COMPLETE @ ' . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}");

$JSON['pass'] = 1;
$JSON['table_count'] = $dbtable_count;
$JSON['table_rows']  = $dbtable_rows;
$JSON['query_errs']  = $dbquery_errs;
echo json_encode($JSON);
error_reporting($ajax1_error_level);
die('');
?>