Commit 6f550b92 authored by Pierre's avatar Pierre

-> spip 3.2 ?

parent 721b05b0
<?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
*/
/**
* Auteur(s) autorise(s) a proceder aux mises a jour : '1:2:3'
*
* @note En tete, sinon defini trop tard !
*/
define('_SPIP_LOADER_UPDATE_AUTEURS', '1:242');
/**
* Branche installee par defaut.
*
* Au choix parmi la liste des branches déclarées ('dev', '3.2', '3.1', ...)
* @see lister_branches_proposees()
*/
define('_DEFAUT_BRANCHE_MAJ', '3.2');
/**
* Liste des branches possibles
* (avec l’adresse du zip et la version minimale de PHP)
*
* @param string|null $branche
* Pour retourner l’info d’une branche spécifique
* @return array|false
* Descriptif des branches, ou d’une seule branche
*/
function lister_branches_proposees($branche = null) {
$branches = array(
'dev' => array(
'zip' => 'spip/dev/SPIP-svn.zip',
'php' => '5.4.0',
),
'3.2' => array(
'zip' => 'spip/stable/spip-3.2.zip',
'php' => '5.4.0',
),
'3.1' => array(
'zip' => 'spip/stable/spip-3.1.zip',
'php' => '5.1.0',
),
'3.0' => array(
'zip' => 'spip/stable/spip-3.0.zip',
'php' => '5.1.0',
),
'2.1' => array(
'zip' => 'spip/stable/spip-2.1.zip',
'php' => '4.0.8',
),
);
if (!is_null($branche)) {
return isset($branches[$branche]) ? $branches[$branche] : false;
}
return $branches;
}
/**
* Version de SPIP Loader
*
* Historique
* ----------
* - 2.1 : introduction du parametre d'URL chemin
* - 2.2 : introduction du parametre d'URL dest
* - 2.3 : introduction du parametre d'URL range
* - 2.4 : redirection par meta refresh au lieu de header Location
* - 2.5 : affichage de la version à installer, de la version déjà installée (si elle existe),
* - compatibilite PHP, loader obsolete
* - 2.5.10 : on télécharge maintenant SPIP 3.2
* - 2.5.11 : coquille empechant des mises à jour
* - 2.6.0 : déclaration simplifiée des branches / zips + sélecteur de branche
* - 3.0.0 : le SPIP loader analyse et déplace les fichiers obsolètes dans un répertoire 'fichiers_obsoletes_{date}'
* pour les répertoires appartenant à SPIP (ecrire, prive, plugins-dist, squelettes-dist).
* /!\ si vous avez ajouté des plugins dans plugins-dist, ils seront aussi déplacés !!
* - 3.0.1 : le sélecteur choisit par défaut la branche actuel du SPIP déjà installé, s’il la connait.
* - 3.0.2 : Un répertoire obsolète n’est pas déplacé s’il contient un fichier '.spip_loader_keep'
*/
define('_SPIP_LOADER_VERSION', '3.0.2');
/**
* Notre branche de destination par défaut
*
* - ignoré si la constante _CHEMIN_FICHIER_ZIP est forcée
* - ignoré si un SPIP est déjà installé (tentera de rester sur la même branche par défaut)
*/
$notre_branche = lister_branches_proposees(_DEFAUT_BRANCHE_MAJ);
if (!$notre_branche) {
die("Mauvaise définition de la constante _DEFAUT_BRANCHE_MAJ. <code>Branche " . _DEFAUT_BRANCHE_MAJ . " inconnue</code>");
}
if (!defined('_CHEMIN_FICHIER_ZIP')) {
/**
* Chemin du zip installé par défaut
*
* Si la constante _CHEMIN_FICHIER_ZIP est déjà définie,
* alors le zip défini sera utilisé.
*
* Sinon, on prend par défaut le zip de la branche installée par défaut.
*/
define('_CHEMIN_FICHIER_ZIP', $notre_branche['zip']);
} else {
// éviter d’afficher le sélecteur de branche dans ces cas là .
define('_CHEMIN_FICHIER_ZIP_FORCEE', true);
}
# repertoires d'installation
define('_DIR_BASE', './');
define('_DIR_PLUGINS', _DIR_BASE . 'plugins/');
# adresse du depot
define('_URL_SPIP_DEPOT', 'https://files.spip.net/');
# Adresse des librairies necessaires a spip_loader
# (pclzip et fichiers de langue)
define('_URL_LOADER_DL', 'https://www.spip.net/spip-dev/INSTALL/');
# telecharger a travers un proxy
define('_URL_LOADER_PROXY', '');
# surcharger le script
define('_NOM_PAQUET_ZIP', 'spip');
// par defaut le morceau de path a enlever est le nom : spip
define('_REMOVE_PATH_ZIP', _NOM_PAQUET_ZIP);
define('_SPIP_LOADER_PLUGIN_RETOUR', 'ecrire/?exec=admin_plugin&voir=tous');
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
define('_SPIP_LOADER_EXTRA', '');
define('_DEST_PAQUET_ZIP', '');
define('_PCL_ZIP_SIZE', 249587);
define('_PCL_ZIP_RANGE', 200);
/**
* Le SPIP Loader ne place pas dans le répertoire obsolète
* un répertoire qui contiendrait un fichier avec ce nom.
*/
define('_SPIP_LOADER_KEEP', '.spip_loader_keep');
#######################################################################
# langues disponibles
$langues = array (
'ar' => "&#1593;&#1585;&#1576;&#1610;",
'ast' => "asturianu",
'br' => "brezhoneg",
'ca' => "catal&#224;",
'cs' => "&#269;e&#353;tina",
'de' => "Deutsch",
'en' => "English",
'eo' => "Esperanto",
'es' => "Espa&#241;ol",
'eu' => "euskara",
'fa' => "&#1601;&#1575;&#1585;&#1587;&#1609;",
'fr' => "fran&#231;ais",
'fr_tu' => "fran&#231;ais copain",
'gl' => "galego",
'hr' => "hrvatski",
'id' => "Indonesia",
'it' => "italiano",
'km' => "Cambodian",
'lb' => "L&euml;tzebuergesch",
'nap' => "napulitano",
'nl' => "Nederlands",
'oc_lnc' => "&ograve;c lengadocian",
'oc_ni' => "&ograve;c ni&ccedil;ard",
'pt_br' => "Portugu&#234;s do Brasil",
'ro' => "rom&#226;n&#259;",
'sk' => "sloven&#269;ina", // (Slovakia)
'sv' => "svenska",
'tr' => "T&#252;rk&#231;e",
'wa' => "walon",
'zh_tw' => "&#21488;&#28771;&#20013;&#25991;", // chinois taiwan (ecr. traditionnelle)
);
// Url du fichier archivelist permettant de créer les zips de spip
define('_URL_ARCHIVELIST', 'https://core.spip.org/projects/spip/repository/raw/archivelist.txt');
// Url du fichier spip_loader permettant de tester sa version distante
define('_URL_SPIP_LOADER', _URL_LOADER_DL . 'spip_loader.php');
//
// Renvoie un tableau des versions SPIP dont l'index correspond à au chemin du fichier zip tel
// qu'utilisé par spip_loader
//
function lister_versions_spip() {
$versions = array();
// Récupération du fichier archivelist.txt du core
$archivelist = recuperer_page(_URL_ARCHIVELIST);
$contenu = explode("\n", $archivelist);
// on supprime les retours chariot
$contenu = array_filter($contenu, 'trim');
// on supprime les lignes vides
$contenu = array_filter($contenu);
if ($contenu) {
// On lit le fichier ligne par ligne et on
foreach ($contenu as $ligne) {
if (substr($ligne, 0, 1) != '#') {
// C'est une ligne de definition d'un paquet :
$parametres = explode(';', $ligne);
// - et on extrait la version de spip du chemin svn
$arbo_svn = rtrim($parametres[0], '/');
$version = str_replace('spip-', '', basename($arbo_svn));
// - on separe calcul le nom complet du zip
$chemin = 'spip/' . $parametres[1] . '.zip';
// - on determine l'état de l'archive (stable, dev, archives)
$etat = substr($parametres[1], 0, strpos($parametres[1], '/'));
// Ajout au tableau des versions
$versions[$chemin] = array(
'version' => $version,
'etat' => $etat);
}
}
}
return $versions;
}
function branche_spip($version) {
if ($version == 'spip') {
return 'dev';
}
$v = explode('.', $version);
$branche = $v[0] . '.' . (isset($v[1]) ? $v[1] : '0');
return $branche;
}
// faut il mettre à jour le spip_loader ?
function spip_loader_necessite_maj() {
return version_compare(_SPIP_LOADER_VERSION, spip_loader_recupere_version(), '<');
}
// trouver le numéro de version du dernier spip_loader
function spip_loader_recupere_version() {
static $version = null;
if (is_null($version)) {
$version = false;
$spip_loader = recuperer_page(_URL_SPIP_LOADER);
if (preg_match("/define\('_SPIP_LOADER_VERSION', '([0-9.]*)'\)/", $spip_loader, $m)) {
$version = $m[1];
}
}
return $version;
}
//
// Traduction des textes de SPIP
//
function _TT($code, $args = array()) {
global $lang;
$code = str_replace('tradloader:', '', $code);
$text = $GLOBALS['i18n_tradloader_'.$lang][$code];
while (list($name, $value) = @each($args)) {
$text = str_replace("@$name@", $value, $text);
}
return $text;
}
//
// Ecrire un fichier de maniere un peu sure
//
function ecrire_fichierT($fichier, $contenu) {
$fp = @fopen($fichier, 'wb');
$s = @fputs($fp, $contenu, $a = strlen($contenu));
$ok = ($s == $a);
@fclose($fp);
if (!$ok) {
@unlink($fichier);
}
return $ok;
}
function mkdir_recursif($chemin, $chmod) {
$dirs = explode('/', $chemin);
$d = array_shift($dirs);
foreach ($dirs as $dir) {
$d = "$d/$dir";
if (!is_dir($d)) {
mkdir($d, $chmod);
}
}
return is_dir($chemin);
}
function 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_recursif($d, $chmod)) {
die("impossible de creer $d");
}
}
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();
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 regler_langue_navigateurT() {
$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 menu_languesT($lang, $script = '', $hidden = array()) {
$r = '';
if (preg_match(',action=([a-z_]+),', $script, $m)) {
$r .= "<input type='hidden' name='action' value='".$m[1]."' />";
$script .= '&amp;';
} else {
$script .= '?';
}
foreach ($hidden as $k => $v) {
if ($v and $k!='etape') {
$script .= "$k=$v&amp;";
}
}
$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 sélecteur de menu pour choisir le zip (la branche) à utiliser.
*
* @param array $active Chemin du paquet à télécharger actuellement sélectionné
* @param string $version_installee Version de SPIP actuellement installée
* @return string
*/
function menu_branches($active, $version_installee) {
$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 (lister_branches_proposees() as $branche => $desc) {
if ($branche == 'dev' or !$version_installee or version_compare(branche_spip($version_installee), $branche, '<=')) {
$select .= '<option value="' . $desc['zip'] . '"' . ($active == $desc['zip'] ? ' selected="selected"' : '') . '>'
. 'SPIP ' . $branche
. "</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 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');
@rmdir('test');
return $ok;
}
//
// Demarre une transaction HTTP (s'arrete a la fin des entetes)
// retourne un descripteur de fichier
//
function 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 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) = 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 telecharger_langue($lang, $droits) {
$fichier = 'tradloader_'.$lang.'.php';
$GLOBALS['idx_lang'] = 'i18n_tradloader_'.$lang;
if (!file_exists(_DIR_BASE.$fichier)) {
$contenu = recuperer_page(_URL_LOADER_DL.$fichier.".txt");
if ($contenu and $droits) {
ecrire_fichierT(_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 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 = regler_langue_navigateurT();
}
# 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 telecharger_langue($lang, $droits) ? $lang : false;
}
function debut_html($corps = '', $hidden = array()) {
global $lang, $spip_lang_dir, $spip_lang_right, $version_installee;
if ($version_installee) {
$titre = _TT('tradloader:titre_maj', array('paquet'=>strtoupper(_NOM_PAQUET_ZIP)));
} else {
$titre = _TT('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";
}