File "spip_loader.php"
Full path: /home/argothem/www/organecyberpresse/spip_loader.php
File size: 43.19 KB
MIME-type: text/x-php
Charset: 8 bit
<?php
/**
* SPIP Loader recupere et installe SPIP
*
* Configuration
* -------------
* Pour les mises a jour effectuees avec ce script,
* toutes les constantes ci-dessous peuvent etre surchargees
* dans config/mes_options.php
*/
if (file_exists('spip_loader_config.php')) {
include_once('spip_loader_config.php');
}
/**
* Auteur(s) autorise(s) a proceder aux mises a jour : '1:2:3'
*
* @note En tete, sinon defini trop tard !
*/
if (!defined('_SPIP_LOADER_UPDATE_AUTEURS')) {
define('_SPIP_LOADER_UPDATE_AUTEURS', '1');
}
/**
* Version de SPIP Loader
*
* Historique
* ----------
* - [...]
* - 3.0.10 : Compat PHP 7.4 & 8
* - 4.0.0 : Utilisation dun fichier spip_loader_list.json
* On ne rend disponible que les dernires versions maintenues.
* - 4.1.0 : Si notre SPIP install actuel nest plus une version maintenue, on demande explicitement la branche
* - 4.1.1 : Tolrance php < 5.4 du spip_loader !
* - 4.2.0 : Mise en cache pour 10mn de spip_loader_list.json
* - 4.3.0 : Correction pour retrouver l'analyse et dplacement des fichiers obsoltes
* SL Ncessite PHP 5.2 minimum (faut pas pousser... dsol les vieux SPIP 3.1...)
* - 4.3.1 : Toutes les fonctions du loader son prfixes par SL.
* On fait un tour au dballage fini, 100% pour avoir tout le temps libre pour dplacer les fichiers et vrifier les superflus.
* - 4.3.2 : Compat PHP de SPIP 4.0
* - 4.3.3 : SPIP 4.0 par dfaut
*
* - 5.0.0 : Version 2 de lapi JSON qui inclut la branche par dfaut et les requirements php.
* - 5.0.1 : Montrer une erreur si on ne peut pas crire la mise jour de Spip Loader, invalider les caches fichiers du loader sur une mise jour.
* - 5.1.0 : Automatisation de la gnration du fichier spip_loader_list.json
* - 5.1.1 : Migration vers la 5.2.0
*/
define('_SPIP_LOADER_VERSION', '5.1.1');
define('_SPIP_LOADER_API', 2);
# Adresse des librairies necessaires a spip_loader
# (pclzip et fichiers de langue)
if (!defined('_URL_LOADER_DL')) {
define('_URL_LOADER_DL', 'https://get.spip.net/');
}
// Url des versions proposes
if (!defined('_URL_SPIP_LOADER_LIST')) {
define('_URL_SPIP_LOADER_LIST', 'https://www.spip.net/spip_loader.api');
}
// Url du fichier spip_loader permettant de tester sa version distante
if (!defined('_URL_SPIP_LOADER')) {
define('_URL_SPIP_LOADER', _URL_LOADER_DL . 'spip_loader.php');
}
# telecharger a travers un proxy
if (!defined('_URL_LOADER_PROXY')) {
define('_URL_LOADER_PROXY', '');
}
# repertoires d'installation
if (!defined('_DIR_BASE')) {
define('_DIR_BASE', './');
}
function SL_error_handler($exception) {
$content = $exception->getMessage();
$version = _SPIP_LOADER_VERSION;
echo <<<EOS
<html>
<head>
<title>Error</title>
</head>
<body>
<style>
:root { --color: #F02364; --padding: 1em 2em; }
body{ display: grid; justify-content: center; align-content: center; height:100%; }
.page { min-width: 25em; }
.error { border: 3px solid var(--color); padding: var(--padding); font-weight: bold;}
h1 { font-size: 1.25em; }
</style>
<div class="page">
<span class="loader">SPIP Loader $version</span>
<div class="error">
<h1>Error</h1>
<p>$content</p>
</div>
</div>
</body>
</html>
EOS;
}
set_exception_handler('SL_error_handler');
/**
* Notre branche de destination par dfaut
*
* - ignor si la constante _CHEMIN_FICHIER_ZIP est force
* - ignor si un SPIP est dj install (tentera de rester sur la mme branche par dfaut)
*/
$notre_branche = SL_determiner_branche_par_defaut();
if (!defined('_CHEMIN_FICHIER_ZIP')) {
/**
* Chemin du zip install par dfaut
*
* Si la constante _CHEMIN_FICHIER_ZIP est dj dfinie,
* alors le zip dfini sera utilis.
*
* Sinon, on prend par dfaut le zip de la branche installe par dfaut.
*/
if (!$notre_branche) {
define('_CHEMIN_FICHIER_ZIP', '');
} else {
define('_CHEMIN_FICHIER_ZIP', $notre_branche['zip']);
}
} else {
// viter dafficher le slecteur de branche dans ces cas l.
define('_CHEMIN_FICHIER_ZIP_FORCEE', true);
}
if (!defined('_DIR_PLUGINS')) {
define('_DIR_PLUGINS', _DIR_BASE . 'plugins/');
}
# adresse du depot
if (!defined('_URL_SPIP_DEPOT')) {
define('_URL_SPIP_DEPOT', 'https://files.spip.net/');
}
# surcharger le script
if (!defined('_NOM_PAQUET_ZIP')) {
define('_NOM_PAQUET_ZIP', 'spip');
}
// par defaut le morceau de path a enlever est le nom : '' (anciennement 'spip/')
if (!defined('_REMOVE_PATH_ZIP')) {
define('_REMOVE_PATH_ZIP', '');
}
if (!defined('_SPIP_LOADER_PLUGIN_RETOUR')) {
define('_SPIP_LOADER_PLUGIN_RETOUR', 'ecrire/?exec=admin_plugin&voir=tous');
}
if (!defined('_SPIP_LOADER_SCRIPT')) {
define('_SPIP_LOADER_SCRIPT', 'spip_loader.php');
}
// "habillage" optionnel
// liste separee par virgules de fichiers inclus dans spip_loader
// charges a la racine comme spip_loader.php et pclzip.php
// selon l'extension: include .php , .css et .js dans le <head> genere par spip_loader
if (!defined('_SPIP_LOADER_EXTRA')) {
define('_SPIP_LOADER_EXTRA', '');
}
if (!defined('_DEST_PAQUET_ZIP')) {
define('_DEST_PAQUET_ZIP', '');
}
if (!defined('_PCL_ZIP_SIZE')) {
define('_PCL_ZIP_SIZE', 249587);
}
if (!defined('_PCL_ZIP_RANGE')) {
define('_PCL_ZIP_RANGE', 200);
}
/**
* Le SPIP Loader ne place pas dans le rpertoire obsolte
* un rpertoire qui contiendrait un fichier avec ce nom.
*/
if (!defined('_SPIP_LOADER_KEEP')) {
define('_SPIP_LOADER_KEEP', '.spip_loader_keep');
}
#######################################################################
# langues disponibles
$langues = array (
'ar' => "عربي",
'ast' => "asturianu",
'br' => "brezhoneg",
'ca' => "català",
'cs' => "čeština",
'de' => "Deutsch",
'en' => "English",
'eo' => "Esperanto",
'es' => "Español",
'eu' => "euskara",
'fa' => "فارسى",
'fr' => "français",
'fr_tu' => "français copain",
'gl' => "galego",
'hr' => "hrvatski",
'id' => "Indonesia",
'it' => "italiano",
'km' => "Cambodian",
'lb' => "Lëtzebuergesch",
'nap' => "napulitano",
'nl' => "Nederlands",
'oc_lnc' => "òc lengadocian",
'oc_ni' => "òc niçard",
'pt_br' => "Português do Brasil",
'ro' => "română",
'sk' => "slovenčina", // (Slovakia)
'sv' => "svenska",
'tr' => "Türkçe",
'wa' => "walon",
'zh_tw' => "台灣中文", // chinois taiwan (ecr. traditionnelle)
);
/**
* Liste des versions possibles
* (avec ladresse du zip et la version minimale de PHP)
*
* @param string|null $branch
* Pour retourner linfo dune branche spcifique
* @return array|false
* Descriptif des branches, ou dune seule branche
*/
function SL_lister_branches_proposees($branch = null) {
static $branches = null;
if ($branches === null) {
$liste = SL_lister_versions_spip();
$branches = array_column($liste['versions'], null, 'branche');
}
if (!is_null($branch)) {
return isset($branches[$branch]) ? $branches[$branch] : false;
}
return $branches;
}
/**
* Dtermine quelle est la branche par dfaut utiliser.
*
* @return sting|false
* nom de la branche par dfaut, ou false
*/
function SL_determiner_branche_par_defaut() {
static $default = null;
if ($default === null) {
$branches = SL_lister_branches_proposees();
$liste = SL_lister_versions_spip();
$branch = $liste['default_branch'];
$default = isset($branches[$branch]) ? $branches[$branch] : false;
}
return $default;
}
/**
* Renvoie une dfinition des versions SPIP
*
* Tableau
* - defaut_branch => version
* - versions => [ chemin => [ description de la version ]]
*
* @return array
*/
function SL_lister_versions_spip() {
// Rcupration du fichier spip_loader_list.json
$filename = 'spip_loader_list.json';
$ttl = 10 * 60; // 10mn
$local_spip_loader_list = _DIR_BASE . $filename;
if (
!file_exists($local_spip_loader_list)
or (time() - filemtime($local_spip_loader_list) > $ttl)
) {
$contenu = SL_recuperer_page(_URL_SPIP_LOADER_LIST);
if ($contenu) {
if (! @file_put_contents($local_spip_loader_list, $contenu)) {
throw new \Exception("Impossible dcrire le fichier " . $filename);
}
SL_spip_clear_opcode_cache($local_spip_loader_list);
} else {
throw new \Exception("Impossible dcrire le fichier " . $filename);
}
}
$liste = file_get_contents($local_spip_loader_list);
if (!$liste) {
throw new \Exception("Impossible de lire le fichier $filename");
}
$liste = json_decode($liste, true);
if (!is_array($liste)) {
throw new \Exception("Impossible de dcoder le fichier $filename");
}
$api = $liste['api'];
if (!$api or $api !== _SPIP_LOADER_API) {
return [
'default_branch' => null,
'versions' => [],
];
}
$php = !empty($liste['requirements']['php']) ? $liste['requirements']['php'] : array();
$versions = array();
foreach ($liste['versions'] as $version => $path) {
$branch = SL_getBranchNameFromTag($version);
$php_min = !empty($php[$branch]) ? $php[$branch] : (!empty($php['master']) ? $php['master'] : null);
$versions[$path] = array(
'version' => $version,
'branche' => ($version === 'dev' ? 'dev' : $branch),
'etat' => ($version === 'master' ? 'dev' : 'stable'),
'zip' => $path,
'php_min' => $php_min,
);
}
return [
'default_branch' => !empty($liste['default_branch']) ? $liste['default_branch'] : null,
'versions' => $versions,
];
}
function SL_getBranchNameFromTag($tag) {
if (!$tag) {
return "";
}
if ($tag[0] === 'v') {
$tag = substr($tag, 1);
}
$b = explode('.', $tag);
$branch = array();
$branch[] = array_shift($b);
$branch[] = array_shift($b);
$branch = implode('.', $branch);
return $branch;
}
function SL_branche_spip($version) {
if (in_array($version, array('master', 'dev'))) {
return 'dev';
}
$v = explode('.', $version);
$branche = $v[0] . '.' . (isset($v[1]) ? $v[1] : '0');
return $branche;
}
// faut il mettre jour le spip_loader ?
function SL_necessite_maj() {
return version_compare(_SPIP_LOADER_VERSION, SL_recupere_version(), '<');
}
// trouver le numro de version du dernier spip_loader
function SL_recupere_version() {
static $version = null;
if (is_null($version)) {
$version = false;
$url_version = str_replace('spip_loader.php', 'version', _URL_SPIP_LOADER);
$spip_loader = trim(SL_recuperer_page($url_version));
if (preg_match('/^([0-9.]*)$/', $spip_loader, $m)) {
$version = $m[1];
}
}
return $version;
}
//
// Traduction des textes de SPIP
//
function SL_T($code, $args = array()) {
global $lang;
$code = str_replace('tradloader:', '', $code);
$text = $GLOBALS['i18n_tradloader_'.$lang][$code];
foreach ($args as $name => $value) {
$text = str_replace("@$name@", $value, $text);
}
return $text;
}
function SL_move_all($src, $dest) {
global $chmod;
$dest = rtrim($dest, '/');
if ($dh = opendir($src)) {
while (($file = readdir($dh)) !== false) {
if (in_array($file, array('.', '..'))) {
continue;
}
$s = "$src/$file";
$d = "$dest/$file";
if (is_dir($s)) {
if (!is_dir($d)) {
if (!mkdir($d, $chmod, true)) {
die("impossible de creer $d");
}
}
SL_move_all($s, $d);
rmdir($s);
// verifier qu'on en a pas oublie (arrive parfois il semblerait ...)
// si cela arrive, on fait un clearstatcache, et on recommence un move all...
if (is_dir($s)) {
clearstatcache();
SL_move_all($s, $d);
rmdir($s);
}
} else {
if (is_file($s)) {
rename($s, $d);
}
}
}
// liberer le pointeur sinon windows ne permet pas le rmdir eventuel
closedir($dh);
}
}
function SL_regler_langue_navigateur() {
$accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
if (is_array($accept_langs)) {
foreach ($accept_langs as $s) {
if (preg_match('#^([a-z]{2,3})(-[a-z]{2,3})?(;q=[0-9.]+)?$#i', trim($s), $r)) {
$lang = strtolower($r[1]);
if (isset($GLOBALS['langues'][$lang])) {
return $lang;
}
}
}
}
return false;
}
function SL_menu_langues($lang, $script = '', $hidden = array()) {
$r = '';
if (preg_match(',action=([a-z_]+),', $script, $m)) {
$r .= "<input type='hidden' name='action' value='".$m[1]."' />";
$script .= '&';
} else {
$script .= '?';
}
foreach ($hidden as $k => $v) {
if ($v and $k!='etape') {
$script .= "$k=$v&";
}
}
$r .= '<select name="lang"
onchange="window.location=\''.$script.'lang=\'+this.value;">';
foreach ($GLOBALS['langues'] as $l => $nom) {
$r .= '<option value="'.$l.'"' . ($l == $lang ? ' selected="selected"' : '')
. '>'.$nom."</option>\n";
}
$r .= '</select> <noscript><div><input type="submit" name="ok" value="ok" /></div></noscript>';
return $r;
}
/**
* Affiche un slecteur de menu pour choisir le zip (la branche) utiliser.
*
* @param array $active Chemin du paquet tlcharger actuellement slectionn
* @param string $version_installee Version de SPIP actuellement installe
* @return string
*/
function SL_menu_branches($active, $version_installee, $presente) {
$select = '';
if (!defined('_CHEMIN_FICHIER_ZIP_FORCEE')) {
$script = _DIR_BASE . _SPIP_LOADER_SCRIPT . '?';
$select .= "<div style='float:" . $GLOBALS['spip_lang_right'] . "'>";
$select .= '<select name="chemin" onchange="window.location=\'' . $script . 'chemin=\'+this.value;">';
foreach (SL_lister_branches_proposees() as $branche => $desc) {
if ($branche == 'dev' or !$version_installee or version_compare(SL_branche_spip($version_installee), $branche, '<=')) {
$_active = ($active == $desc['zip']) && ($presente);
$select .= '<option value="' . $desc['zip'] . '"' . ($_active ? ' selected="selected"' : '') . '>'
. 'SPIP ' . $branche
. "</option>\n";
}
}
if (!$presente) {
$select .= '<option value="" selected="selected">'
. 'Slectionnez...'
. "</option>\n";
}
$select .= '</select> <noscript><div><input type="submit" name="ok" value="ok" /></div></noscript>';
$select .= '</div>';
}
return $select;
}
//
// Gestion des droits d'acces
//
function SL_tester_repertoire() {
global $chmod;
$ok = false;
$self = basename($_SERVER['PHP_SELF']);
$uid = @fileowner('.');
$uid2 = @fileowner($self);
$gid = @filegroup('.');
$gid2 = @filegroup($self);
$perms = @fileperms($self);
// Comparer l'appartenance d'un fichier cree par PHP
// avec celle du script et du repertoire courant
@rmdir('test');
@unlink('test'); // effacer au cas ou
@touch('test');
if ($uid > 0 && $uid == $uid2 && @fileowner('test') == $uid) {
$chmod = 0700;
} else {
if ($gid > 0 && $gid == $gid2 && @filegroup('test') == $gid) {
$chmod = 0770;
} else {
$chmod = 0777;
}
}
// Appliquer de plus les droits d'acces du script
if ($perms > 0) {
$perms = ($perms & 0777) | (($perms & 0444) >> 2);
$chmod |= $perms;
}
@unlink('test');
// Verifier que les valeurs sont correctes
@mkdir('test', $chmod);
@chmod('test', $chmod);
$ok = (is_dir('test') && is_writable('test')) ? $chmod : false;
@rmdir('test');
return $ok;
}
// creer repertoire
function SL_creer_repertoires_plugins($chmod) {
// crer les rpertoires plugins/auto et lib
if (!is_dir('plugins')) {
@mkdir('plugins', $chmod);
}
if (!is_dir('plugins/auto')) {
@mkdir('plugins/auto', $chmod);
}
if (!is_dir('lib')) {
@mkdir('lib', $chmod);
}
return 'cretion des repertoires tentee';
}
//
// Demarre une transaction HTTP (s'arrete a la fin des entetes)
// retourne un descripteur de fichier
//
function SL_init_http($get, $url, $refuse_gz = false) {
//global $http_proxy;
$fopen = false;
if (!preg_match(",^http://,i", _URL_LOADER_PROXY)) {
$http_proxy = '';
} else {
$http_proxy = _URL_LOADER_PROXY;
}
$t = @parse_url($url);
$host = $t['host'];
if ($t['scheme'] == 'http') {
$scheme = 'http';
$scheme_fsock = '';
} else {
$scheme = $t['scheme'];
$scheme_fsock = $scheme.'://';
}
if (!isset($t['port']) or !($port = $t['port'])) {
$port = 80;
}
$query = isset($t['query']) ? $t['query'] : '';
if (!isset($t['path']) or !($path = $t['path'])) {
$path = "/";
}
if ($http_proxy) {
$t2 = @parse_url($http_proxy);
$proxy_host = $t2['host'];
$proxy_user = $t2['user'];
$proxy_pass = $t2['pass'];
if (!($proxy_port = $t2['port'])) {
$proxy_port = 80;
}
$f = @fsockopen($proxy_host, $proxy_port);
} else {
$f = @fsockopen($scheme_fsock.$host, $port);
}
if ($f) {
if ($http_proxy) {
fputs(
$f,
"$get $scheme://$host" . (($port != 80) ? ":$port" : "") .
$path . ($query ? "?$query" : "") . " HTTP/1.0\r\n"
);
} else {
fputs($f, "$get $path" . ($query ? "?$query" : "") . " HTTP/1.0\r\n");
}
$version_affichee = isset($GLOBALS['spip_version_affichee'])?$GLOBALS['spip_version_affichee']:"xx";
fputs($f, "Host: $host\r\n");
fputs($f, "User-Agent: SPIP-$version_affichee (https://www.spip.net/)\r\n");
// Proxy authentifiant
if (isset($proxy_user) and $proxy_user) {
fputs($f, "Proxy-Authorization: Basic "
. base64_encode($proxy_user . ":" . $proxy_pass) . "\r\n");
}
} elseif (!$http_proxy) {
// fallback : fopen
$f = @fopen($url, "rb");
$fopen = true;
} else {
// echec total
$f = false;
}
return array($f, $fopen);
}
//
// Recupere une page sur le net
// et au besoin l'encode dans le charset local
//
// options : get_headers si on veut recuperer les entetes
function SL_recuperer_page($url) {
// Accepter les URLs au format feed:// ou qui ont oublie le http://
$url = preg_replace(',^feed://,i', 'http://', $url);
if (!preg_match(',^[a-z]+://,i', $url)) {
$url = 'http://'.$url;
}
// dix tentatives maximum en cas d'entetes 301...
for ($i = 0; $i < 10; $i++) {
list($f, $fopen) = SL_init_http('GET', $url);
// si on a utilise fopen() - passer a la suite
if ($fopen) {
break;
} else {
// Fin des entetes envoyees par SPIP
fputs($f, "\r\n");
// Reponse du serveur distant
$s = trim(fgets($f, 16384));
if (preg_match(',^HTTP/[0-9]+\.[0-9]+ ([0-9]+),', $s, $r)) {
$status = $r[1];
} else {
return;
}
// Entetes HTTP de la page
$headers = '';
while ($s = trim(fgets($f, 16384))) {
$headers .= $s."\n";
if (preg_match(',^Location: (.*),i', $s, $r)) {
$location = $r[1];
}
if (preg_match(",^Content-Encoding: .*gzip,i", $s)) {
$gz = true;
}
}
if ($status >= 300 and $status < 400 and $location) {
$url = $location;
} elseif ($status != 200) {
return;
} else {
break; # ici on est content
}
fclose($f);
$f = false;
}
}
// Contenu de la page
if (!$f) {
return false;
}
$result = '';
while (!feof($f)) {
$result .= fread($f, 16384);
}
fclose($f);
// Decompresser le flux
if (isset($_GET['gz']) and $gz = $_GET['gz']) {
$result = gzinflate(substr($result, 10));
}
return $result;
}
function SL_telecharger_langue($lang, $droits) {
$fichier = 'tradloader_'.$lang.'.php';
$GLOBALS['idx_lang'] = 'i18n_tradloader_'.$lang;
if (!file_exists(_DIR_BASE.$fichier)) {
$contenu = SL_recuperer_page(_URL_LOADER_DL.$fichier);
if ($contenu and $droits) {
file_put_contents(_DIR_BASE . $fichier, $contenu);
include(_DIR_BASE.$fichier);
return true;
} elseif ($contenu and !$droits) {
eval('?'.'>'.$contenu);
return true;
} else {
return false;
}
} else {
include(_DIR_BASE.$fichier);
return true;
}
}
function SL_selectionner_langue($droits) {
global $langues; # langues dispo
$lang = '';
if (isset($_COOKIE['spip_lang_ecrire'])) {
$lang = $_COOKIE['spip_lang_ecrire'];
}
if (isset($_REQUEST['lang'])) {
$lang = $_REQUEST['lang'];
}
# reglage par defaut selon les preferences du brouteur
if (!$lang or !isset($langues[$lang])) {
$lang = SL_regler_langue_navigateur();
}
# valeur par defaut
if (!isset($langues[$lang])) {
$lang = 'fr';
}
# memoriser dans un cookie pour l'etape d'apres *et* pour l'install
setcookie('spip_lang_ecrire', $lang);
# RTL
if ($lang == 'ar' or $lang == 'he' or $lang == 'fa') {
$GLOBALS['spip_lang_right']='left';
$GLOBALS['spip_lang_dir']='rtl';
} else {
$GLOBALS['spip_lang_right']='right';
$GLOBALS['spip_lang_dir']='ltr';
}
# code de retour = capacite a telecharger le fichier de langue
$GLOBALS['idx_lang'] = 'i18n_tradloader_'.$lang;
return SL_telecharger_langue($lang, $droits) ? $lang : false;
}
function SL_debut_html($corps = '', $hidden = array()) {
global $lang, $spip_lang_dir, $spip_lang_right, $version_installee;
if ($version_installee) {
$titre = SL_T('tradloader:titre_maj', array('paquet'=>strtoupper(_NOM_PAQUET_ZIP)));
} else {
$titre = SL_T('tradloader:titre', array('paquet'=>strtoupper(_NOM_PAQUET_ZIP)));
}
$css = $js = '';
foreach (explode(',', _SPIP_LOADER_EXTRA) as $fil) {
switch (strrchr($fil, '.')) {
case '.css':
$css .= '
<!-- css pour tuning optionnel, au premier chargement, il manquera si pas droits ... -->
<link rel="stylesheet" href="' . basename($fil) . '" type="text/css" media="all" />';
break;
case '.js':
$js .= '
<!-- js pour tuning optionnel, au premier chargement, il manquera... -->
<script src="' . basename($fil) . '" type="text/javascript"></script>';
break;
}
}
$hid = '';
foreach ($hidden as $k => $v) {
$hid .= "<input type='hidden' name='$k' value='$v' />\n";
}
$script = _DIR_BASE . _SPIP_LOADER_SCRIPT;
echo
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
<html 'xml:lang=$lang' dir='$spip_lang_dir'>
<head>
<title>$titre</title>
<meta http-equiv='Expires' content='0' />
<meta http-equiv='cache-control' content='no-cache,no-store' />
<meta http-equiv='pragma' content='no-cache' />
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<style type='text/css'>
body {
font-family:Verdana, Geneva, sans-serif;
font-size:.9em;
color: #222;
background-color: #f8f7f3;
}
#main {
margin:5em auto;
padding:3em 2em;
background-color:#fff;
border-radius:2em;
box-shadow: 0 0 20px #666;
width:34em;
}
a {
color: #E86519;
}
a:hover {
color:#FF9900;
}
h1 {
color:#5F4267;
display:inline;
font-size:1.6em;
}
h2 {
font-weigth: normal;
font-size: 1.2em;
}
div {
line-height:140%;
}
div.progression {
margin-top:2em;
font-weight:bold;
font-size:1.4em;
text-align:center;
}
.bar {border:1px solid #aaa;}
.bar div {background:#aaa;height:1em;}
.version {background:#eee;margin:1em 0;padding:.5em;}
.version-courante {color:#888;}
.erreur {border-left:4px solid #f00; padding:1em 1em 1em 2em; background:#FCD4D4;}
.info {border-left:4px solid #FFA54A; padding:1em 1em 1em 2em; background:#FFEED9; margin:1em 0;}
</style>$css$js
</head>
<body>
<div id='main'>
<form action='" . $script . "' method='get'>" .
"<div style='float:$spip_lang_right'>" .
SL_menu_langues($lang, $script, $hidden) .
"</div>
<div>
<h1>" . $titre . "</h1>". $corps .
$hid .
"</div></form>";
}
function SL_fin_html()
{
global $taux;
echo ($taux ? '
<div id="taux" style="display:none">'.$taux.'</div>' : '') .
'
<p style="text-align:right;font-size:x-small;">spip_loader '
. _SPIP_LOADER_VERSION
.'</p>
</div>
</body>
</html>
';
// forcer l'envoi du buffer par tous les moyens !
echo(str_repeat("<br />\r\n", 256));
while (@ob_get_level()) {
@ob_flush();
@flush();
@ob_end_flush();
}
}
function SL_nettoyer_racine($fichier) {
@unlink($fichier);
@unlink(_DIR_BASE.'pclzip.php');
@unlink(_DIR_BASE.'spip_loader_list.json');
@unlink(_DIR_BASE.'svn.revision');
$d = opendir(_DIR_BASE);
while (false !== ($f = readdir($d))) {
if (preg_match('/^tradloader_(.+).php$/', $f)) {
@unlink(_DIR_BASE.$f);
}
}
closedir($d);
return true;
}
/**
* Dplace les fichiers qui sont en trop entre le contenu du zip et le rpertoire destination.
*
* @param array $content Liste des fichiers issus de pclZip
* @param string $dir Rpertoire o ils ont t copis.
*/
function SL_nettoyer_superflus($content, $dir) {
global $chmod;
$diff = SL_comparer_contenus($content, $dir);
if ($diff) {
@mkdir($old = _DIR_BASE . 'fichiers_obsoletes_' . date('Ymd_His'), $chmod);
if (!is_dir($old)) {
return false;
}
$old .= '/';
foreach ($diff as $file => $isDir) {
$root = $isDir ? $file : dirname($file);
if (!is_dir($old . $root)) {
mkdir($old . $root, $chmod, true);
}
if ($isDir) {
SL_move_all(_DIR_BASE . $root, $old . $root);
rmdir(_DIR_BASE . $root);
} else {
rename(_DIR_BASE . $file, $old . $file);
}
}
}
}
/**
* Retourne la liste des fichiers/rpertoires en trop entre le zip et la destination,
* pour certains rpertoires seulement.
*
* @param array $content Fichiers contenus dans le zip
* @param string $dir Rpertoire ou le zip a t dzipp
*/
function SL_comparer_contenus($content, $dir) {
// On se considre dans SPIP et on vrifie seulement ces rpertoires
$repertoires_suivis = array(
'ecrire',
'prive',
'plugins-dist',
'squelettes-dist',
'extensions', // spip 2.1 hum.
);
$contenus_source_suivis = SL_lister_contenus_zip_suivis($content, $repertoires_suivis);
$diff = SL_lister_contenus_superflus($contenus_source_suivis, $dir, $repertoires_suivis);
return $diff;
}
/**
* Retourne la liste des fichiers/rpertoires suivis du zip
*
* @param array $content Fichiers contenus dans le zip
* @param array $repertoires_suivis Rpertoires que l'on vrifie (on ne s'occupe pas des autres)
* @return array chemin => isDir ?
*/
function SL_lister_contenus_zip_suivis($content, $repertoires_suivis) {
// avant le zip contenait un dossier "spip/"... (c'est tout la racine maintenant)
$base = _REMOVE_PATH_ZIP;
if ($base && $content[0]['filename'] !== $base) {
return false;
}
$len = strlen($base);
// Liste des contenus sources (chemin => isdir?)
$contenus_source = array();
foreach ($content as $c) {
$fichier = substr($c['filename'], $len);
$root = explode('/', $fichier, 2);
$root = reset($root);
if (!in_array($root, $repertoires_suivis)) {
continue;
}
$contenus_source[$fichier] = $c['folder'];
}
// certains zips n'indiquent pas les rpertoires ; on les ajoute...
// on ne conserve pas le / final du coup...
foreach ($contenus_source as $fichier => $isDir) {
if (!$isDir) {
$_dir = dirname($fichier);
if ($_dir === '.' or isset($contenus_source[$_dir])) {
continue;
}
do {
$contenus_source[$_dir] = true;
$_dir = dirname($_dir);
} while ($_dir && $_dir !== '.');
}
}
return $contenus_source;
}
/**
* Liste les contenus en trop dans certains rpertoires, en fonction dune liste de fichiers
*
* Un rpertoire superflu, mais contenant un fichier .spip_loader_keep est conserv,
* c'est dire quil ne sera pas retourn dans cette liste de fichiers/rpertoire obsoltes.
*
* @param array $contenus_source liste(chemin => isDir?)
* @param string $dir Chemin du rpertoire tester
* @param array|null $repertoires_suivis Liste de rpertoires uniquement parcourrir si dfini.
* @return array liste(chemin => isDir?) des fichiers/rpertoire en trop.
*/
function SL_lister_contenus_superflus($contenus_source, $dir, $repertoires_suivis) {
$iterator = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS);
$iterator = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$iterator = new RegexIterator($iterator, '#^' . $dir . '(' . implode('|', $repertoires_suivis) . ')(/|$)#');
$superflus = new SL_SuperflusFilterIterator($iterator, $contenus_source, $dir);
$liste = array();
$ignoreLen = strlen($dir);
foreach ($superflus as $file) {
$liste[ substr($file->getPathname(), $ignoreLen) ] = $file->isDir();
}
return $liste;
}
/**
* Iterateur des dossiers et fichiers superflus...
* Note: utiliser CallbackFilterIterator quand PHP >= 5.4 pour SL.
*/
class SL_SuperflusFilterIterator extends FilterIterator
{
private $contenus_source;
private $ignoreLen;
private $ignoreDirs = array();
public function __construct($iterator, $contenus_source, $dir) {
parent::__construct($iterator);
$this->contenus_source = $contenus_source;
$this->ignoreLen = strlen($dir);
}
#[\ReturnTypeWillChange]
public function accept() {
$file = $this->getInnerIterator()->current();
if ($this->isAcceptedFile($file)) {
return false;
}
// on tente de ne pas mettre les fichiers et dossiers d'un dossier dj ignor...
// ne fonctionne que si l'iterateur en entre est bien tri (::SELF_FIRST)
if ($file->isDir()) {
$this->ignoreDirs[] = $file->getPathname();
}
$parent = $file->getPath();
if (in_array($parent, $this->ignoreDirs)) {
return false;
}
return true;
}
private function isAcceptedFile($file) {
if ($file->getFileName() === '.ok') {
return true;
}
$path = substr($file->getPathname(), $this->ignoreLen);
if ($file->isDir()) {
if (isset($this->contenus_source[$path])) {
return true;
}
// ne pas rendre obsolte si un fichier de conservation est prsent.
if (file_exists($file->getPathname() . '/' . _SPIP_LOADER_KEEP)) {
return true;
}
return false;
}
if (isset($this->contenus_source[$path])) {
return true;
}
return false;
}
}
// un essai pour parer le probleme incomprehensible des fichiers pourris
function SL_touchCallBack($p_event, &$p_header)
{
// bien extrait ?
if ($p_header['status'] == 'ok') {
// allez, on touche le fichier, le @ est pour les serveurs sous Windows qui ne comprennent pas touch()
@touch($p_header['filename']);
}
return 1;
}
function SL_microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function SL_verifie_zlib_ok()
{
global $taux;
if (!function_exists("gzopen") and !function_exists("gzopen64")) {
return false;
}
if (!file_exists($f = _DIR_BASE . 'pclzip.php')) {
$taux = SL_microtime_float();
$contenu = SL_recuperer_page(_URL_LOADER_DL . 'pclzip.php');
if ($contenu) {
file_put_contents($f, $contenu);
}
$taux = _PCL_ZIP_SIZE / (SL_microtime_float() - $taux);
}
include $f;
$necessaire = array();
foreach (explode(',', _SPIP_LOADER_EXTRA) as $fil) {
$necessaire[$fil] = strrchr($fil, '.') === '.php';
}
foreach ($necessaire as $fil => $php) {
if (!file_exists($f = _DIR_BASE . basename($fil))) {
$contenu = SL_recuperer_page(_URL_LOADER_DL . $fil);
if ($contenu) {
file_put_contents($f, $contenu);
}
}
if ($php) {
include $f;
}
}
return true;
}
function SL_reinstalle() {
if (!defined('_SPIP_LOADER_UPDATE_AUTEURS')) {
define('_SPIP_LOADER_UPDATE_AUTEURS', '1');
}
if (!isset($GLOBALS['auteur_session']['statut']) or
$GLOBALS['auteur_session']['statut'] != '0minirezo' or
!in_array($GLOBALS['auteur_session']['id_auteur'], explode(':', _SPIP_LOADER_UPDATE_AUTEURS))) {
include_spip('inc/headers');
include_spip('inc/minipres');
http_status('403');
echo install_debut_html(_T('info_acces_interdit'));
echo "<div style='text-align: center'>\n";
echo _T('ecrire:avis_non_acces_page');
echo '<br /><a href="' . parametre_url(generer_url_public('login'), 'url', 'spip_loader.php') . '">' . _T('public:lien_connecter') . '</a>';
echo "\n</div>";
echo install_fin_html();
exit;
}
}
function SL_spip_deballe_paquet($paquet, $fichier, $dest, $range) {
global $chmod;
// le repertoire temporaire est invariant pour permettre la reprise
@mkdir($tmp = _DIR_BASE.'zip_'.md5($fichier), $chmod);
$ok = is_dir($tmp);
$zip = new PclZip($fichier);
$content = $zip->listContent();
$max_index = count($content);
$start_index = isset($_REQUEST['start']) ? intval($_REQUEST['start']) : 0;
$ended = isset($_REQUEST['ended']) ? true : false;
if (!$range) {
$range = _PCL_ZIP_RANGE;
}
$end_index = min($start_index + $range, $max_index);
if (!$ended && $start_index < $max_index) {
$ok &= (bool) $zip->extractByIndex(
"$start_index-$end_index",
PCLZIP_OPT_PATH,
$tmp,
PCLZIP_OPT_SET_CHMOD,
$chmod,
PCLZIP_OPT_REPLACE_NEWER,
PCLZIP_OPT_REMOVE_PATH,
_REMOVE_PATH_ZIP,
PCLZIP_CB_POST_EXTRACT,
'SL_touchCallBack'
);
}
if (!$ok or $zip->error_code < 0) {
SL_debut_html();
echo SL_T('tradloader:donnees_incorrectes', array('erreur' => $zip->errorInfo()));
SL_fin_html();
} else {
// si l'extraction n'est pas finie, relancer
$url = _DIR_BASE . _SPIP_LOADER_SCRIPT
. (strpos(_SPIP_LOADER_SCRIPT, '?') ? '&' : '?')
. "etape=fichier&chemin=$paquet&dest=$dest&range=$range";
if (!$ended && $start_index < $max_index) {
$progres = $start_index/$max_index;
SL_spip_redirige_boucle($url . "&start=$end_index", $progres);
} elseif (!$ended) {
// on a fait le dernier tour, afficher 100% et relancer pour les dplacements et nettoyages
SL_spip_redirige_boucle($url . "&ended=1", 1);
}
if ($dest) {
@mkdir(_DIR_PLUGINS, $chmod);
$dir = _DIR_PLUGINS . $dest;
$url = _DIR_BASE . _SPIP_LOADER_PLUGIN_RETOUR;
} else {
$dir = _DIR_BASE;
$url = _DIR_BASE . _SPIP_LOADER_URL_RETOUR;
}
SL_move_all($tmp, $dir);
rmdir($tmp);
SL_nettoyer_superflus($content, $dir);
SL_nettoyer_racine($fichier);
header("Location: $url");
}
}
function SL_spip_redirige_boucle($url, $progres = ''){
//@apache_setenv('no-gzip', 1); // provoque page blanche chez certains hebergeurs donc ne pas utiliser
@ini_set('zlib.output_compression', '0'); // pour permettre l'affichage au fur et a mesure
@ini_set('output_buffering', 'off');
@ini_set('implicit_flush', 1);
@ob_implicit_flush(1);
$corps = '<meta http-equiv="refresh" content="0;'.$url.'">';
if ($progres) {
$corps .="<div class='progression'>".round($progres*100)."%</div>
<div class='bar'><div style='width:".round($progres*100)."%'></div></div>
";
}
SL_debut_html($corps);
SL_fin_html();
exit;
}
function SL_spip_presente_deballe($fichier, $paquet, $dest, $range) {
global $version_installee;
$nom = (_DEST_PAQUET_ZIP == '') ?
SL_T('tradloader:ce_repertoire') :
(SL_T('tradloader:du_repertoire').
' <tt>'._DEST_PAQUET_ZIP.'</tt>');
$hidden = array(
'chemin' => $paquet,
'dest' => $dest,
'range' => $range,
'etape' => file_exists($fichier) ? 'fichier' : 'charger'
);
// Version propose l'installation par dfaut
$versions_spip = SL_lister_versions_spip();
$versions_spip = $versions_spip['versions'];
$version_future = '';
if (isset( $versions_spip[$paquet])) {
$version_future = $versions_spip[$paquet]['version'];
if ($versions_spip[$paquet]['etat'] == 'dev') {
$version_future .= '-dev';
}
}
$version_future_affichee = 'SPIP ' . $version_future;
// notre branche est elle maintenue ? si non, on demande slectionner une autre branche
// ou on na demand dj un spip spcifique...
// ou on na pas de spip install !
if (
!empty($_REQUEST['chemin'])
or false !== strpos($version_installee, '-dev')
or !$version_installee
) {
$presente = true;
} else {
$ma_branche = SL_getBranchNameFromTag($version_installee);
$branches = SL_lister_branches_proposees();
$presente = $ma_branche && isset($branches[$ma_branche]);
if (!$presente) {
$version_future_affichee = 'Slectionnez';
}
}
if ($version_installee) {
// Mise jour
$bloc_courant =
'<div class="version-courante">'
. SL_T('tradloader:titre_version_courante')
. '<strong>'. 'SPIP ' . $version_installee .'</strong>'
. '</div>';
$bouton = SL_T('tradloader:bouton_suivant_maj');
} else {
// Installation nue
$bloc_courant = '';
$bouton = SL_T('tradloader:bouton_suivant');
}
// Dtection d'une incompatibilit avec la version de PHP installe
$php_incompatible = false;
if (isset($versions_spip[$paquet]['version'])) {
$branche_future = SL_branche_spip($versions_spip[$paquet]['version']);
$version_php_installee = phpversion();
$version_php_spip = SL_lister_branches_proposees($branche_future);
$version_php_spip = $version_php_spip['php_min'];
$php_incompatible = version_compare($version_php_spip, $version_php_installee, '>');
}
if ($php_incompatible) {
$bouton =
'<div class="erreur">'
. SL_T('tradloader:echec_php', array('php1' => $version_php_installee, 'php2' => $version_php_spip))
. '</div>';
} elseif (version_compare($version_installee, $version_future, '>') and ($version_future !== 'dev')) {
// pargnons un downgrade aux personnes tourdies
$bouton =
"<div style='text-align:".$GLOBALS['spip_lang_right']."'>"
. '<input type="submit" disabled="disabled" value="' . $bouton . '" />'
. '</div>';
} elseif (!$presente) {
// Forcer avoir une branche si la notre nexiste plus
$bouton =
"<div style='text-align:".$GLOBALS['spip_lang_right']."'>"
. '<input type="submit" disabled="disabled" value="' . $bouton . '" />'
. '</div>';
} else {
$bouton =
"<div style='text-align:".$GLOBALS['spip_lang_right']."'>"
. '<input type="submit" value="' . $bouton . '" />'
. '</div>';
}
// Construction du corps
if ($versions_spip) {
$corps =
SL_T('tradloader:texte_intro', array('paquet'=>strtoupper(_NOM_PAQUET_ZIP),'dest'=> $nom))
. '<div class="version">'
. $bloc_courant
. '<div class="version-future">'
. SL_T('tradloader:titre_version_future')
. '<strong>'. $version_future_affichee. '</strong>'
. SL_menu_branches($paquet, $version_installee, $presente)
. '</div>'
. '</div>'
. $bouton;
} else {
$corps =
'<div class="version">'
. $bloc_courant
. '<div class="version-future">'
. 'Aucune version propose ?<br><i>Probablement quune mise jour de SPIP Loader simpose !</i>'
. '</div>'
. '</div>';
}
if (SL_necessite_maj()) {
$corps .=
"<div class='info'><a href='" . _URL_SPIP_LOADER . "'>"
. SL_T('tradloader:spip_loader_maj', array('version' => SL_recupere_version()))
. "</a>"
. "<div style='margin-top:1rem;text-align:".$GLOBALS['spip_lang_right']."'>"
. "<input type='submit' name='spip_loader_update' value='".SL_T('tradloader:bouton_suivant_maj')."' />"
. "</div></div>";
}
SL_debut_html($corps, $hidden);
SL_fin_html();
}
function SL_spip_recupere_paquet($paquet, $fichier, $dest, $range)
{
$contenu = SL_recuperer_page(_URL_SPIP_DEPOT . $paquet);
if (!($contenu and file_put_contents($fichier, $contenu))) {
SL_debut_html();
echo SL_T('tradloader:echec_chargement'), "$paquet, $fichier, $range" ;
SL_fin_html();
} else {
// Passer a l'etape suivante (desarchivage)
$sep = strpos(_SPIP_LOADER_SCRIPT, '?') ? '&' : '?';
header("Location: "._DIR_BASE._SPIP_LOADER_SCRIPT.$sep."etape=fichier&chemin=$paquet&dest=$dest&range=$range");
}
}
function SL_spip_deballe($paquet, $etape, $dest, $range)
{
$fichier = _DIR_BASE . basename($paquet);
if ($etape == 'fichier' and file_exists($fichier)) {
// etape finale: deploiement de l'archive
SL_spip_deballe_paquet($paquet, $fichier, $dest, $range);
} elseif ($etape == 'charger') {
// etape intermediaire: charger l'archive
SL_spip_recupere_paquet($paquet, $fichier, $dest, $range);
} else {
// etape intiale, afficher la page de presentation
SL_spip_presente_deballe($fichier, $paquet, $dest, $range);
}
}
/**
* Invalidates a PHP file from any active opcode caches.
*
* If the opcode cache does not support the invalidation of individual files,
* the entire cache will be flushed.
* kudo : http://cgit.drupalcode.org/drupal/commit/?id=be97f50
*
* @param string $filepath
* The absolute path of the PHP file to invalidate.
*/
function SL_spip_clear_opcode_cache($filepath) {
clearstatcache(true, $filepath);
// Zend OPcache
if (function_exists('opcache_invalidate')) {
$invalidate = @opcache_invalidate($filepath, true);
// si l'invalidation a echoue lever un flag
if (!$invalidate and !defined('_spip_attend_invalidation_opcode_cache')) {
define('_spip_attend_invalidation_opcode_cache',true);
}
} elseif (!defined('_spip_attend_invalidation_opcode_cache')) {
// n'agira que si opcache est effectivement actif (il semble qu'on a pas toujours la fonction opcache_invalidate)
define('_spip_attend_invalidation_opcode_cache',true);
}
// APC.
if (function_exists('apc_delete_file')) {
// apc_delete_file() throws a PHP warning in case the specified file was
// not compiled yet.
// @see http://php.net/apc-delete-file
@apc_delete_file($filepath);
}
}
///////////////////////////////////////////////
// debut du process
//
error_reporting(E_ALL ^ E_NOTICE);
// PHP >= 5.3 rale si cette init est absente du php.ini et consorts
// On force a defaut de savoir anticiper l'erreur (il doit y avoir mieux)
if (function_exists('date_default_timezone_set')) {
date_default_timezone_set('Europe/Paris');
}
$GLOBALS['taux'] = 0; // calcul eventuel du taux de transfert+dezippage
// En cas de reinstallation, verifier que le demandeur a les droits avant tout
// definir _FILE_CONNECT a autre chose que machin.php si on veut pas
$version_installee = '';
if (@file_exists('ecrire/inc_version.php')) {
define('_SPIP_LOADER_URL_RETOUR', "ecrire/?exec=accueil");
include_once 'ecrire/inc_version.php';
$version_installee = $GLOBALS['spip_version_branche'];
if ((defined('_FILE_CONNECT') and
_FILE_CONNECT and
strpos(_FILE_CONNECT, '.php')) or
defined('_SITES_ADMIN_MUTUALISATION')) {
SL_reinstalle();
}
} else {
define('_SPIP_LOADER_URL_RETOUR', "ecrire/?exec=install");
// _DIR_TMP nexiste pas encore
if (!defined('PCLZIP_TEMPORARY_DIR')) {
define('PCLZIP_TEMPORARY_DIR', '');
}
}
$droits = SL_tester_repertoire();
$GLOBALS['lang'] = SL_selectionner_langue($droits);
if (!$GLOBALS['lang']) {
//on ne peut pas telecharger
$GLOBALS['lang'] = 'fr'; //francais par defaut
$GLOBALS['i18n_tradloader_fr']['titre'] = 'Téléchargement de SPIP';
$GLOBALS['i18n_tradloader_fr']['echec_chargement'] = '<h4>Le chargement a échoué.'.
' Veuillez réessayer, ou utiliser l\'installation manuelle.</h4>';
SL_debut_html();
echo SL_T('tradloader:echec_chargement');
SL_fin_html();
} elseif (!$droits) {
//on ne peut pas ecrire
SL_debut_html();
$q = $_SERVER['QUERY_STRING'];
echo SL_T(
'tradloader:texte_preliminaire',
array(
'paquet' => strtoupper(_NOM_PAQUET_ZIP),
'href' => ('spip_loader.php' . ($q ? "?$q" : '')),
'chmod' => sprintf('%04o', $chmod)
)
);
SL_fin_html();
} elseif (!SL_verifie_zlib_ok()) {
// on ne peut pas decompresser
throw new Exception('Fonctions zip non disponibles');
} else {
//Update himself
if (!empty($_REQUEST['spip_loader_update'])) {
$spip_loader = SL_recuperer_page(_URL_SPIP_LOADER);
if (defined('_SPIP_LOADER_UPDATE_AUTEURS')) {
$spip_loader = preg_replace(
"/(define\(['\"]_SPIP_LOADER_UPDATE_AUTEURS['\"],).*/",
"$1'" . _SPIP_LOADER_UPDATE_AUTEURS . "');",
$spip_loader
);
}
if (! @file_put_contents(_SPIP_LOADER_SCRIPT, $spip_loader)) {
throw new Exception("Impossible dcrire le nouveau fichier de SPIP Loader.");
}
SL_spip_clear_opcode_cache(_SPIP_LOADER_SCRIPT);
SL_spip_redirige_boucle('spip_loader.php/index.php');
}
// y a tout ce qu'il faut pour que cela marche
$dest = '';
$paquet = _CHEMIN_FICHIER_ZIP;
if (isset($_REQUEST['dest']) and preg_match('/^[\w_.-]+$/', $_REQUEST['dest'])) {
$dest = $_REQUEST['dest'];
}
if (isset($_REQUEST['chemin']) and $_REQUEST['chemin']) {
$paquet = urldecode($_REQUEST['chemin']);
} elseif ($version_installee and !defined('_CHEMIN_FICHIER_ZIP_FORCEE')) {
if ($branche = SL_lister_branches_proposees(SL_branche_spip($version_installee))) {
$paquet = $branche['zip'];
} elseif ((strpos($version_installee, '-dev') !== false) and $branche = SL_lister_branches_proposees('dev')) {
$paquet = $branche['zip'];
} else {
// cette branche nest plus maintenue...
}
}
if ($paquet and ((strpos($paquet, '../') !== false) or ($paquet and substr($paquet, -4, 4) !== '.zip'))) {
throw new Exception("chemin incorrect $paquet");
} else {
SL_spip_deballe(
$paquet,
(isset($_REQUEST['etape']) ? $_REQUEST['etape'] : ''),
$dest,
intval(isset($_REQUEST['range']) ? $_REQUEST['range'] : 0)
);
SL_creer_repertoires_plugins($droits);
}
}