[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / genie / mise_a_jour.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Vérification en tâche de fond des différentes mise à jour.
15 *
16 * @package SPIP\Core\Genie\Mise_a_jour
17 */
18
19 if (!defined('_ECRIRE_INC_VERSION')) {
20 return;
21 }
22
23 /**
24 * Verifier si une mise a jour est disponible
25 *
26 * @param int $t
27 * @return int
28 */
29 function genie_mise_a_jour_dist($t) {
30 include_spip('inc/meta');
31 $maj = info_maj('spip', 'SPIP', $GLOBALS['spip_version_branche']);
32 ecrire_meta('info_maj_spip', $maj ? ($GLOBALS['spip_version_branche'] . "|$maj") : "", 'non');
33
34 mise_a_jour_ecran_securite();
35
36 spip_log("Verification version SPIP : " . ($maj ? $maj : "version a jour"), "verifie_maj");
37
38 return 1;
39 }
40
41 // TODO : fournir une URL sur spip.net pour maitriser la diffusion d'une nouvelle version de l'ecran via l'update auto
42 // ex : http://www.spip.net/auto-update/ecran_securite.php
43 define('_URL_ECRAN_SECURITE', 'https://zone.spip.org/trac/spip-zone/browser/_core_/securite/ecran_securite.php?format=txt');
44 define('_VERSIONS_SERVEUR', 'https://files.spip.net/');
45 define('_VERSIONS_LISTE', 'archives.xml');
46
47 /**
48 * Mise a jour automatisee de l'ecran de securite
49 * On se base sur le filemtime de l'ecran source avec un en-tete if_modified_since
50 * Mais on fournit aussi le md5 de notre ecran actuel et la version branche de SPIP
51 * Cela peut permettre de diffuser un ecran different selon la version de SPIP si besoin
52 * ou de ne repondre une 304 que si le md5 est bon
53 */
54 function mise_a_jour_ecran_securite() {
55 // TODO : url https avec verification du certificat
56 return;
57
58 // si l'ecran n'est pas deja present ou pas updatable, sortir
59 if (!_URL_ECRAN_SECURITE
60 or !file_exists($filename = _DIR_ETC . "ecran_securite.php")
61 or !is_writable($filename)
62 or !$last_modified = filemtime($filename)
63 or !$md5 = md5_file($filename)
64 ) {
65 return false;
66 }
67
68 include_spip('inc/distant');
69 $tmp_file = _DIR_TMP . "ecran_securite.php";
70 $url = parametre_url(_URL_ECRAN_SECURITE, "md5", $md5);
71 $url = parametre_url($url, "vspip", $GLOBALS['spip_version_branche']);
72 $res = recuperer_url($url, array(
73 'if_modified_since' => $last_modified,
74 'file' => $tmp_file
75 ));
76
77 // si il y a une version plus recente que l'on a recu correctement
78 if ($res['status'] == 200
79 and $res['length']
80 and $tmp_file = $res['file']
81 ) {
82
83 if ($md5 !== md5_file($tmp_file)) {
84 // on essaye de l'inclure pour verifier que ca ne fait pas erreur fatale
85 include_once $tmp_file;
86 // ok, on le copie a la place de l'ecran existant
87 // en backupant l'ecran avant, au cas ou
88 @copy($filename, $filename . "-bck-" . date('Y-m-d-His', $last_modified));
89 @rename($tmp_file, $filename);
90 } else {
91 @unlink($tmp_file);
92 }
93 }
94 }
95
96 /**
97 * Vérifier si une nouvelle version de SPIP est disponible
98 *
99 * Repérer aussi si cette version est une version majeure de SPIP.
100 *
101 * @param string $dir
102 * @param string $file
103 * @param string $version
104 * La version reçue ici est sous la forme x.y.z
105 * On la transforme par la suite pour avoir des integer ($maj, $min, $rev)
106 * et ainsi pouvoir mieux les comparer
107 *
108 * @return string
109 */
110 function info_maj($dir, $file, $version) {
111 include_spip('inc/plugin');
112
113 list($maj, $min, $rev) = preg_split('/\D+/', $version);
114
115 $nom = _DIR_CACHE_XML . _VERSIONS_LISTE;
116 $page = !file_exists($nom) ? '' : file_get_contents($nom);
117 $page = info_maj_cache($nom, $dir, $page);
118
119 // reperer toutes les versions de numero majeur superieur ou egal
120 // (a revoir quand on arrivera a SPIP V10 ...)
121 $p = substr("0123456789", intval($maj));
122 $p = ',/' . $file . '\D+([' . $p . ']+)\D+(\d+)(\D+(\d+))?.*?[.]zip",i';
123 preg_match_all($p, $page, $m, PREG_SET_ORDER);
124 $page = $page_majeure = '';
125
126 // branche en cours d'utilisation
127 $branche = implode('.', array_slice(explode('.', $version, 3), 0, 2));
128
129 foreach ($m as $v) {
130 $v = array_pad($v, 5, 0);
131 list(, $maj2, $min2, , $rev2) = $v;
132 $branche_maj = $maj2 . '.' . $min2;
133 $version_maj = $maj2 . '.' . $min2 . '.' . $rev2;
134 // d'abord les mises à jour de la même branche
135 if ((spip_version_compare($version, $version_maj, '<'))
136 and (spip_version_compare($page, $version_maj, '<'))
137 and spip_version_compare($branche, $branche_maj, '=')
138 ) {
139 $page = $version_maj;
140 }
141 // puis les mises à jours majeures
142 if ((spip_version_compare($version, $version_maj, '<'))
143 and (spip_version_compare($page, $version_maj, '<'))
144 and spip_version_compare($branche, $branche_maj, '<')
145 ) {
146 $page_majeure = $version_maj;
147 }
148 }
149 if (!$page and !$page_majeure) {
150 return "";
151 }
152
153 $message = $page ? _T('nouvelle_version_spip', array('version' => $page)) . ($page_majeure ? ' | ' : '') : '';
154 $message .= $page_majeure ? _T('nouvelle_version_spip_majeure', array('version' => $page_majeure)) : '';
155
156 return "<a class='info_maj_spip' href='https://www.spip.net/fr_update' title='$page'>" . $message . '</a>';
157 }
158
159 /**
160 * Vérifie que la liste $page des versions dans le fichier $nom est à jour.
161 *
162 * Ce fichier rajoute dans ce fichier l'aléa éphémère courant;
163 * on teste la nouveauté par If-Modified-Since,
164 * et seulement quand celui-ci a changé pour limiter les accès HTTP.
165 * Si le fichier n'a pas été modifié, on garde l'ancienne version.
166 *
167 * @see info_maj()
168 *
169 * @param string $nom
170 * Nom du fichier contenant les infos de mise à jour.
171 * @param string $dir
172 * @param string $page
173 * @return string
174 * Contenu du fichier de cache de l'info de maj de SPIP.
175 */
176 function info_maj_cache($nom, $dir, $page = '') {
177 include_spip('inc/acces');
178 $alea_ephemere = charger_aleas();
179 $re = '<archives id="a' . $alea_ephemere . '">';
180 if (preg_match("/$re/", $page)) {
181 return $page;
182 }
183
184 $url = _VERSIONS_SERVEUR . $dir . '/' . _VERSIONS_LISTE;
185 $a = file_exists($nom) ? filemtime($nom) : '';
186 include_spip('inc/distant');
187 $res = recuperer_url_cache($url, array('if_modified_since' => $a));
188 // Si rien de neuf (ou inaccessible), garder l'ancienne
189 if ($res) {
190 $page = $res['page'] ? $res['page'] : $page;
191 }
192 // Placer l'indicateur de fraicheur
193 $page = preg_replace('/^<archives.*?>/', $re, $page);
194 sous_repertoire(_DIR_CACHE_XML);
195 ecrire_fichier($nom, $page);
196
197 return $page;
198 }