<?php
const ROOT = 'PluXml/';
$URLS = array(
'' => array(
'https://github.com/pluxml/PluXml/archive/5.6.zip'
),
ROOT.'plugins' => array(
'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=kzUploader&download',
'https://www.echecs-annonay.fr/kazimentou/index.php?plugin=tinyMCE&download',
'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=captchaImage&download',
'https://kazimentou.fr/pluxml-plugins2/index.php?plugin=kzMailCommentAlert&download'
),
ROOT.'themes' => array(
'https://kazimentou.fr/divers/PluXml/echecs.zip',
'http://ressources.pluxml.org/?telechargement/MDE3OS4wMTkuMTA4LnRoZW1lLXBsdXh6ZXJvL3B1YmxpYy9hcmNoaXZlLnppcHx0aGVtZS1wbHV4emVyb3x6aXAqYzA4ZTYy'
)
);
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;
const L_TOO_MUCH_FILES= 7;
const L_FOLDER = 8;
$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",
"The folder %s must have only the ". __FILE__ ." script",
"Folder"
),
'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",
"Le dossier %s doit contenir uniquement le script ".__FILE__,
"Dossier"
),
'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",
"The folder %s must have only this PHP script",
"Targeta"
),
'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",
"The folder %s must have only this PHP script",
"Folder"
)
);
define('PUBLIC_NETWORK', filter_input(
INPUT_SERVER, 'SERVER_ADDR', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE
));
const PATTERN = '{*,.htaccess,.git*}';
const HOMEPAGE = '/install.php';
define('WORKDIR', __DIR__ );
define('REPORTFILE', WORKDIR.'/'.basename(__FILE__, '.php').'.json');
define('REPORT_URL', preg_replace('@\.php(?:\?[^/]*)?$@', '.json', $_SERVER['PHP_SELF']));
define('NEW_LOCATION', rtrim(dirname($_SERVER['PHP_SELF']), '/').HOMEPAGE);
const ID_PATTERN = 'U%02d';
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);
}
function error($msg) {
header('Content-type: text/plain;charset=utf-8');
echo $msg;
}
$dashboard = array(
'begin' => false,
'urls' => array(),
'end' => false,
'msgId' => 0
);
function report() {
global $dashboard;
$fp = fopen(REPORTFILE, 'w');
fwrite($fp, json_encode($dashboard));
fclose($fp);
}
function progressbar($resource, $total_download, $partiel_download, $total_upload, $partiel_upload) {
global $dashboard;
$key = curl_getinfo($resource, CURLINFO_PRIVATE);
if(
array_key_exists($key, $dashboard['urls']) and (
$partiel_download - $dashboard['urls'][$key]['partiel'] > 8192 or
$partiel_download == $total_download
)
) {
$dashboard['urls'][$key]['total'] = $total_download;
$dashboard['urls'][$key]['partiel'] = $partiel_download;
$dashboard['msgId']++;
report();
}
}
function unzip($filename, $target) {
if(!empty($filename)) {
$zip = new ZipArchive();
if($zip->open($filename) === true) {
$target = trim($target, '/ \\');
$tt = WORKDIR;
if(!empty($target)) { $tt .= "/$target"; }
$zip->extractTo($tt);
$root = $zip->getNameIndex(0);
$zip->close();
unlink($filename);
$root = substr($root, 0, strpos($root, '/'));
$newName = preg_replace('@-?[\d.]*$@', '', $root);
if($newName != $root) { rename("$tt/$root", "$tt/$newName"); }
return true;
} else {
return false;
}
}
}
function install($URLS, &$dashboard) {
$offset_time = filemtime(__FILE__);
$dashboard['begin'] = time() - $offset_time;
$chs = array();
$fps = array();
$filenames = array();
$n = 0;
$mh = curl_multi_init();
foreach($URLS as $target=>$urls_list) {
$filenames[$target] = array();
foreach($urls_list as $url) {
$fn = tempnam(sys_get_temp_dir(), 'KZX');
$filenames[$target][] = $fn;
$fps[$n] = fopen($fn, 'w');
$key = sprintf(ID_PATTERN, $n);
$dashboard['urls'][$key] = array( 'total' => 0, 'partiel' =>0 );
$chs[$n] = curl_init($url);
curl_setopt_array($chs[$n], array(
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HEADER => false,
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
CURLOPT_NOPROGRESS => false,
CURLOPT_PROGRESSFUNCTION => 'progressbar',
CURLOPT_FILE => $fps[$n],
CURLOPT_PRIVATE => $key
));
curl_multi_add_handle($mh, $chs[$n]);
$n++;
}
}
report();
$active = true;
while($active) {
usleep(200000);
$cme = curl_multi_exec($mh, $active);
}
for($i=0; $i<$n; $i++) {
curl_multi_remove_handle($mh, $chs[$i]);
curl_close($chs[$i]);
fclose($fps[$i]);
}
curl_multi_close($mh);
foreach(array_keys($dashboard['urls']) as $key) {
if($dashboard['urls'][$key]['total'] == 0) {
$dashboard['urls'][$key]['total'] = $dashboard['urls'][$key]['partiel'];
}
}
foreach($filenames as $target=>$fileslist) {
foreach($fileslist as $filename1) {
unzip($filename1, $target);
unlink($filename1);
}
}
$sources = glob(WORKDIR.'/'.ROOT.PATTERN, GLOB_BRACE + GLOB_NOESCAPE);
$offset = strlen(WORKDIR.'/'.ROOT) - 1;
foreach($sources as $src) {
rename($src, WORKDIR.substr($src, $offset));
}
rmdir(WORKDIR.'/'.ROOT);
$dashboard['end'] = time() - $offset_time;
report();
}
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Expires: Fri, 14 Jul 2000 12:00:00 GMT');
header('Pragma: no-cache');
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'); }
$missing_libs = array();
if(!function_exists('curl_init')) { $missing_libs[] = ' - Curl'; }
if(!class_exists('ZipArchive')) { $missing_libs[] = ' - ZipArchive'; }
if(!function_exists('json_encode')) { $missing_libs[] = ' - Json'; }
if(!function_exists('filter_has_var')) { $missing_libs[] = ' - Filter'; }
if(!empty($missing_libs)) {
error(i18n(L_LIB).implode("\n", $missing_libs));
} elseif(!is_writable(__DIR__)) {
error(i18n(L_UNWRITABLE, __DIR__));
} elseif(filter_has_var(INPUT_GET, 'install')) {
install($URLS, $dashboard);
} elseif(!empty($_GET) or !empty($_POST)) {
die;
} else {
if(
file_exists(__DIR__ . HOMEPAGE) and
time() - filemtime(REPORTFILE) < 300
) {
header('Location: '.NEW_LOCATION);
if(PUBLIC_NETWORK) { unlink(__FILE__); }
exit;
}
$sources = glob(WORKDIR.'/'.PATTERN, GLOB_BRACE + GLOB_NOESCAPE);
if(count($sources) != 1 or $sources[0] != __FILE__) {
error(i18n(L_TOO_MUCH_FILES, __DIR__));
print_r($sources);
exit;
}
?>
<!DOCTYPE html>
<html lang="fr"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>kzInstall-2.0 by Kazimentou.fr</title>
<link rel="shortcut icon" href="https://kazimentou.fr/favicon.ico">
<style type="text/css">
* { margin: 0; padding: 0; }
body {background-color:
.container { max-width: 50rem; margin: 0 auto; padding: 0.3rem 0.8rem; background-color:
.container ul { padding-left: 1rem; }
.container li p { display: flex; margin-bottom: 0; }
.container progress { width: 100%; height: 0.5rem; }
.container li p span:first-of-type { flex-grow: 1; margin-right: 1rem; overflow-x: hidden; }
.container li p span:last-of-type { width: 6rem; text-align: right; background-color:
.container li p span.done:last-of-type { background-color: green; color:
iframe { display: none; }
</style>
</head><body>
<div class="container">
<ul class="folders">
<?php
$idCount = 0;
foreach($URLS as $target=>$urls_list) {
$caption = i18n(L_FOLDER, '', true);
echo <<< EOT
<li>
<h2>$caption : /$target</h2>
<ul>\n
EOT;
foreach($urls_list as $url) {
$id = sprintf(ID_PATTERN, $idCount);
echo <<< EOT
<li>
<p><span>$url</span> <span id="size-$id">0</span></p>
<progress id="prg-$id" value="0" max="100" />
</li>\n
EOT;
$idCount++;
}
echo <<< EOT
</ul>
</li>\n
EOT;
}
?>
</ul>
</div>
<iframe src="<?php echo $_SERVER['PHP_SELF']; ?>?install" height="10" width="100%">Votre navigateur ne gère pas les balises iframe</iframe>
<script type="text/javascript">
'use script';
var failures = 5;
const xhr = new XMLHttpRequest();
var interval1 = null;
xhr.onreadystatechange = function(event) {
if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200) {
if(this.responseText.trim().length == 0) {
failures--;
if(failures <= 0) {
clearInterval(interval1);
alert('Error on server');
}
} else {
const datas = JSON.parse(this.responseText);
if(datas != false) {
for(var url in datas.urls) {
const total = datas.urls[url].total;
const partiel = datas.urls[url].partiel;
if(total > 0 || partiel > 0) {
const value = (total > 0) ? total : partiel;
const sizeEl = document.getElementById('size-' + url)
sizeEl.textContent = Number.parseFloat(value / 1024.0).toFixed(1) + ' Ko';
if(total == partiel) {
sizeEl.classList.add('done');
}
document.getElementById('prg-' + url).value = (total > 0) ? parseInt(100.0 * partiel / total) : 25;
console.log('msg #' + datas.msgId);
}
}
if(datas.end !== false) {
clearInterval(interval1);
alert('Downloaded in ' + (datas.end - datas.begin) + 's');
const timer1 = setTimeout("window.location.href='<?php echo NEW_LOCATION; ?>'", 2000);
}
} else {
failures--;
if(failures <= 0) {
alert('No downloading');
return;
}
}
}
}
}
}
interval1 = setInterval(function() {
xhr.open('GET', "<?php echo REPORT_URL; ?>", true);
xhr.send(null);
}, 1000);
</script>
</body></html>
<?php
}
?>