<?php
/*
 * kzInstall.php is designed by J.P. Pourrez (https://kazimentou.fr)
 * version 2018-02-04 - Updated 2018-02-06
 * */

# NAME is the home folder at the final step. Setup it as you wish but don't leave empty'.
const NAME = 'PluXml';

# List every URL for downloading and folders as targets.
# The NAME folder, as describe after is the root for each target.
$URLS = array(
	'' => array(
		# 'http://telechargements.pluxml.org/download.php'
		'https://github.com/pluxml/PluXml/archive/5.6.zip'
	),
	'PluXml/plugins' => array(
		'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=kzUploader&download',
		'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=tinyMCE&download',
		'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=captchaImage&download',
		'http://repo.warriordudimanche.net/ZIPFILES/mailCommentAlert.zip'
	),
	'PluXml/themes'	=> array(
		'https://kazimentou.fr/divers/PluXml/echecs.zip'
	)
);

const L_URL =			0;
const L_ZIP =			1;
const L_EXIT =			2;
const L_LIB =			3;
const L_BAD_ZIP =		4;
const L_FAIL =			5;
const L_UNWRITABLE =	6;
$all_langs = array(
	'en' => array(
		"Downloading from %s",
		"Unzipping to folder : %s\n",
		"Please, press the F5 key within 60 seconds for reaching %s",
		"The following libraries are required :",
		"Bad Zip archive",
		"Downloading for %s fails",
		"The folder %s is unwritable"
	),
	'fr' => array(
		"Téléchargement depuis %s",
		"Déployement dans le dossier : %s\n",
		"Vous avez 60 secondes pour appuyer sur la touche F5 pour accéder à %s",
		"Les bibliothèques suivantes sont nécessaires :",
		"Archive Zip incorrecte",
		"Échec au téléchargement depuis %s",
		"Aucun droit en écriture pour le dossier %s"
	),
	'es' => array(
		"descargando desde %s",
		"descomprimir en la carpeta : %s\n",
		"Por favor, presione la tecla F5 dentro de 60 segundos para llegar a %s",
		"Se requieren las siguientes bibliotecas :",
		"mal archivo zip",
		"La descarga de %s falla",
		"No permiso de escritura para la carpeta %s"
	),
	'de' => array(
		"Herunterladen von %s",
		"Entpacken in Ordner : %s\n",
		"Drücken Sie die Taste F5 innerhalb von 60 Sekunden, um %s zu erreichen",
		"Die folgenden Bibliotheken sind erforderlich :",
		"schlechtes Zip-Archiv",
		"Das Herunterladen für %s schlägt fehl",
		"Keine Schreibberechtigung für den %s-Ordner"
	)
);

define('PUBLIC_NETWORK', filter_input(
	INPUT_SERVER, 'SERVER_ADDR', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE
));

const WIDTH = 100;

function i18n($text, $value=false, $return=false) {
	global $all_langs;
	if($return) { return sprintf($all_langs[LANG][$text], $value); }
	printf($all_langs[LANG][$text]."\n", $value);
}

/* recursive rmdir */
function rrmdir($dir, $drop=true) {
	if(is_dir($dir)) {
		$entries = array_diff(scandir($dir), array('.','..'));
		foreach($entries as $entry) {
			$fullpath = "$dir/$entry";
			if(is_dir($fullpath)) {
				rrmdir($fullpath);
				rmdir($fullpath);
			} else {
				unlink($fullpath);
			}
		}
		if($drop) { rmdir($dir); }
	}
}

function progressbar($resource, $total_download, $partiel_download, $total_upload, $partiel_upload) {
	static $previous = 0;
	if($total_download >0) {
		$total = WIDTH;
		$partiel = round($total * $partiel_download / $total_download);
		if($previous != $partiel) {
			$percent = round(100.0 * $partiel_download / $total_download);
			if($previous > $partiel) {
				echo str_repeat('·', $partiel);
			} else {
				echo str_repeat('·', ($partiel - $previous));
			}
			$previous = $partiel;
		}
	}
}

/* Must return a filename. */
function download($url) {
	$filename = tempnam(sys_get_temp_dir(), 'KZX');
	$fp = fopen($filename, 'w');
	$curl_params = array(
		CURLOPT_URL					=> $url,
		CURLOPT_FILE				=> $fp,
		CURLOPT_FOLLOWLOCATION		=> true,
		CURLOPT_HEADER				=> false,
		CURLOPT_USERAGENT			=> $_SERVER['HTTP_USER_AGENT'],
		CURLOPT_BUFFERSIZE			=> 65536
	);
	if(!PUBLIC_NETWORK) {
		$curl_params[CURLOPT_NOPROGRESS] = false;
		$curl_params[CURLOPT_PROGRESSFUNCTION] = 'progressbar';
	}
	$ch = curl_init();
	curl_setopt_array($ch, $curl_params);
	i18n(L_URL, $url);
	if(curl_exec($ch)) {
		curl_close($ch);
		fclose($fp);
		echo "\n";
		return $filename;
	}
	i18n(L_FAIL);
	return false;
}

function unzip($filename, $target) {
	if(!empty($filename)) {
		$zip = new ZipArchive();
		if($zip->open($filename) === true) {
			$target = trim($target, '/ \\');
			i18n(L_ZIP, $target);
			$tt = WORKDIR;
			if(!empty($target)) { $tt .= "/$target"; }
			$zip->extractTo($tt);
			$root = $zip->getNameIndex(0);
			$zip->close();
			unlink($filename); # Clean up !

			# At Github, $root change on every release.
			$root = substr($root, 0, strpos($root, '/'));
			$newName = preg_replace('@-?[\d.]*$@', '', $root); # for release from Github
			if($newName != $root) { rename("$tt/$root", "$tt/$newName"); }
			return true;
		} else {
			i18n(L_BAD_ZIP);
			return false;
		}
	}
}

function deploy(&$URLS) {
	if(!is_dir(WORKDIR)) {
		mkdir(WORKDIR);
	} else {
		rrmdir(WORKDIR, false);
	}
	foreach($URLS as $target=>$urls_list) {
		foreach($urls_list as $url) { unzip(download($url), $target); }
	}

	# final step
	if(!empty(NAME)) {
		# Look for the 1st folder in WORKDIR
		$dirs = glob(WORKDIR.'/*', GLOB_ONLYDIR + GLOB_NOESCAPE);
		if(count($dirs) > 0) {
			$to = $dirs[0];
			$tt = __DIR__ .'/'.NAME;
			if(file_exists($tt)) {
				$tu = "$tt.bak";
				if(file_exists($tu)) { rrmdir($tu); }
				rename($tt, $tu);
			}
			rename($to, $tt);
			touch($tt);
			# }
			rrmdir(WORKDIR);
			sleep(2);
			$hr = str_repeat('─', WIDTH - 2);
			echo "┌{$hr}┐\n│";
			echo str_pad(i18n(L_EXIT, NAME, true), WIDTH, ' ', STR_PAD_BOTH);
			echo "│\n└{$hr}┘";
		}
	}
}
/* =========== main ========== */
if(!empty(NAME) and
	file_exists(__DIR__ . '/' . NAME) and
	(time() - filemtime(__DIR__ . '/' . NAME) < 60)
) {
	# If a fresh install, jump to NAME
	header('Location: '.dirname($_SERVER['REQUEST_URI']).'/'. NAME);
	# Auto-destruction if not in private range
	if(PUBLIC_NETWORK) { unlink(__FILE__); }
} else {
	if(!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
		foreach(explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $accept_lang) {
			$lg = substr($accept_lang, 0, 2);
			if(array_key_exists($lg, $all_langs)) {
				define('LANG', $lg);
				break;
			}
		}
	}
	if(!defined('LANG')) { define('LANG', 'en'); }

	# Progress bar don't run in public networks
	if(true or !PUBLIC_NETWORK) {
		ob_implicit_flush();
		ob_end_clean();
	}

	header('Expires: Sun, 01 Jan 2000 12:00:00 GMT');
	header('Cache-Control: no-store, no-cache, must-revalidate');
	header('Cache-Control: post-check=0, pre-check=0', FALSE);
	header('Pragma: no-cache');
	header('Content-Type: text/plain; charset=utf-8');

	$missing_libs = array();
	if(!function_exists('curl_init'))	{ $missing_libs[] = ' - Curl'; }
	if(!class_exists('ZipArchive'))		{ $missing_libs[] = ' - ZipArchive'; }

	if(!empty($missing_libs)) {
		i18n(L_LIB);
		echo implode("\n", $missing_libs)."\n";
	} elseif(!is_writable(__DIR__)) {
		i18n(L_UNWRITABLE, __DIR__);
	} else {
		# New install
		define('WORKDIR', __DIR__ .'/THIS-IS-MY-PRIVATE-GARDEN'); # Must start with '/'
		deploy($URLS);
	}
}
?>