3 // module inclu dans la description de l'outil en page de configuration
5 if (!defined("_ECRIRE_INC_VERSION")) return; // securiser
6 include_spip('inc/actions');
7 include_spip('inc/distant');
8 include_spip('inc/presentation');
9 if(version_compare(PHP_VERSION
, '5.0.0', '>='))
10 include_spip('outils/maj_auto_php5'); else { function cs_svn17($dir) { return false; } }
12 define('_MAJ_SVN_FILE', 'file:///home/svn/repository/spip-zone/');
13 define('_MAJ_SVN_DEBUT', 'svn://zone.spip.org/spip-zone/');
14 define('_MAJ_SVN_TRAC', 'svn://trac.rezo.net/spip-zone/'); // ancienne URL
15 define('_MAJ_ZONE', 'http://zone.spip.org/trac/spip-zone/');
16 define('_MAJ_LOG_DEBUT', _MAJ_ZONE
.'log/');
17 define('_MAJ_LOG_FIN', '?format=changelog');
18 define('_MAJ_ZIP', 'http://files.spip.org/spip-zone/');
19 define('_MAJ_ECRAN_SECU', _MAJ_ZONE
.'browser/_core_/securite/ecran_securite.php?format=txt');
22 if(!function_exists('info_maj_spip')) {
23 include_spip('inc/plugin');
24 if(!function_exists('spip_version_compare')) {
25 function spip_version_compare($v1,$v2,$op) { return version_compare($v1,$v2,$op); }
27 function info_maj_spip(){
28 if (!autoriser('webmestre')) return "";
29 // derniere version de SPIP
30 $maj = $GLOBALS['meta']['info_maj_spip'];
32 $maj = explode('|',$maj);
33 // c'est une ancienne notif, on a fait la maj depuis !
34 if ($GLOBALS['spip_version_branche']!==array_shift($maj)) {
35 // compat_maj_spip(true);
38 // derniere version de SPIP 2.?.?
39 $maj = implode('|',$maj);
40 if (strncmp($maj,"<a",2)==0) $maj = extraire_attribut ($maj, 'title');
41 $lien = "http://www.spip.net/".$GLOBALS['spip_lang']."_download";
42 $maj = _T('couteau:maj_rev_ok',array('revision'=>$maj, 'url'=>$lien, 'zip'=>''));
43 // derniere version de SPIP 2.0.?
44 include_spip('lib/maj_auto/distant_mise_a_jour');
45 if(function_exists('info_maj_cache')) {
46 list(,,$rev) = preg_split('/\D+/', $GLOBALS['spip_version_branche']);
47 $nom = _DIR_CACHE_XML
. _VERSIONS_LISTE
;
48 $page = info_maj_cache($nom, 'spip', !file_exists($nom) ?
'' : file_get_contents($nom));
49 preg_match_all(',/SPIP\D+2\D+0(\D+(\d+))?.*?[.]zip",i', $page, $m, PREG_SET_ORDER
);
51 foreach ($m as $v) if ($v[2]>$rev && $v[2]>$page) $page = $v[2];
53 $lien = "http://files.spip.org/spip/archives/SPIP-v2-0-$page.zip"; // 'http://files.spip.org/spip/archives/#SPIP-v2-0-'.$page;
54 $maj = _T('couteau:maj_rev_ok',array('revision'=>'2.0.'.$page, 'url'=>$lien, 'zip'=>'')) . '<br/>' . $maj;
58 return preg_replace(',\[([^[]+)->\],', '$1', $maj);
60 function compat_maj_spip($forcer=false) {
61 include_spip('lib/maj_auto/distant_mise_a_jour');
62 if(function_exists('genie_mise_a_jour_dist') && $forcer) return genie_mise_a_jour_dist(0);
66 function maj_auto_action_rapide() {
67 global $spip_version_affichee, $spip_version_base;
68 $arg_chargeur = $spip_version_base>=15828?
'url_zip_plugin2':'url_zip_plugin'; // eq. SPIP >= 2.1.2
70 $timeout = ini_get('max_execution_time');
71 $timeout = $timeout?
min(30,floor($timeout/2)):10;
72 $style = 'style="padding:0.4em;"';
73 // verification des mises a jour de SPIP>=2.1
74 include_spip('inc/presentation');
75 list($m1,$m2) = preg_split('/\D+/', $GLOBALS['spip_version_branche']);
76 $html1 = (function_exists('info_maj_spip') && ($html1=info_maj_spip()))
77 ?
"<fieldset><legend $style>"._T('couteauprive:help2', array('version'=>'SPIP '.$spip_version_affichee)).'</legend>'.propre("\n|{{{$html1}}}|")
78 .(preg_match(",$m1\.$m2\.\d+,",$html1)?
'<p>'._T('couteau:maj_spip').'</p>':'').'</fieldset>'
80 // verification de l'ecran de securite
81 if(defined('_ECRAN_SECURITE')) {
82 $maj = maj_auto_rev_distante(_MAJ_ECRAN_SECU
,false,",(\d+\.\d+(\.\d+)?),",0,true);
83 if($maj{0}!="-" && _ECRAN_SECURITE
!=$maj) {
84 include_spip('inc/description_outil');
85 $html1 .= "\n<fieldset><legend $style>"._T('couteauprive:help2', array('version'=>_T('couteauprive:ecran_securite:nom').' '._ECRAN_SECURITE
)).'</legend>'
86 . description_outil_liens(_T("couteauprive:ecran_maj_ko2", array("n"=>"<span style=\"color:red; font-weight:bold;\">$maj</span>"))).'</fieldset>';
89 // verification des plugins
90 include_spip('inc/plugin');
91 $plugins_actifs = array_values(liste_chemin_plugin_actifs());
92 // liste des extensions dispo sous SPIP 2.1
93 $plugins_extensions = defined('_SPIP20100')?
array_values(liste_chemin_plugin_actifs(_DIR_EXTENSIONS
)):array();
94 // tous, mais les actifs d'abord...
95 $plugins = array_unique(array_merge($plugins_actifs, $plugins_extensions, liste_plugin_files()));
96 $html_actifs = $html_inactifs = $html_extensions = array();
97 foreach ($plugins as $p) /*if(preg_match(',^auto/,', $p))*/ {
98 $actif = in_array($p, $plugins_actifs, true);
99 $extension = in_array($p, $plugins_extensions, true);
100 $auto = preg_match(',^auto/,', $p);
101 $infos = plugin_get_infos_maj($p, $stop=time()-$time>$timeout, $extension?_DIR_EXTENSIONS
:_DIR_PLUGINS
);
102 $maj_lib = $checked = '';
104 $maj_lib = '<span class="cs_relancer">'.'Temps serveur écoulé : [poursuivre->#].'.'</span>';
105 elseif($infos['maj_dispo']) {
106 $maj_lib = _T('couteau:maj_rev_ok',
107 array('revision' => $infos['rev_rss'], 'url'=>$infos['url_origine'], 'zip'=>$infos['zip_trac']));
108 $checked = " class='maj_checked'"; }
109 elseif($infos['rev_rss']>0 && $infos['rev_local'])
110 $maj_lib = _T('couteau:maj'.($infos['svn']?
'_svn':'_ok'),
111 array('zip'=>$infos['zip_trac'], 'url'=>$infos['url_origine']));
113 $maj_lib = _T('couteau:maj_rev_ko', array('url'=>$infos['url_origine']));
114 $checked = " class='maj_checked'"; }
115 elseif($infos['rev_local'] && $infos['rev_rss']<=0)
116 $maj_lib = _T('couteau:maj_rev_ko', array('url'=>$infos['url_origine']));
117 // eventuels liens morts
118 $maj_lib = preg_replace(',\[([^[]+)->\],', '$1', $maj_lib);
119 $nom = preg_replace(",[\n\r]+,",' ',$infos['nom']). ' (v' .$infos['version'] . ')' . ($maj_lib?
"\n_ {{".$maj_lib.'}}':'');
120 $rev = $infos['rev_local']?
_T('couteau:maj_rev', array('revision' => $infos['rev_local'])):'';
121 if(strlen($infos['commit'])) $rev .= (strlen($rev)?
'<br/>':'') . cs_date_court($infos['commit']);
122 if($infos['svn']) $rev .= '<br/>SVN';
123 if(!strlen($rev)) $rev = ' ';
124 $zip_log = (strlen($infos['zip_log']) && $infos['zip_log']!=$infos['zip_trac'])
125 ?
"<label><input type='radio' value='$infos[zip_log]'$checked name='$arg_chargeur'/>[->$infos[zip_log]]</label>":'';
127 if($auto && !$stop) $bouton = strlen($infos['zip_trac'])
128 ?
"<input type='radio' value='$infos[zip_trac]'$checked name='$arg_chargeur'/>"
129 :'<center style="margin-top:0.6em;font-weight:bold;"><acronym title="'._T('couteau:maj_zip_ko').'">?</acronym></center>';
130 if(strlen($zip_log)) {
132 $nom .= "\n_ "._T('couteau:maj_verif') . "\n_ $zip_log\n_ {$bouton}[->$infos[zip_trac]]<label>";
135 $
{$actif?
'html_actifs':($extension?
'html_extensions':'html_inactifs')}[] = "|$bouton|$nom|$rev|";
138 $sep = " class='cs_hidden'> (...)</span>}}|<|<|\n";
139 $html1 = "\n<div $style id='maj_auto_div'>$html1<fieldset><legend $style>"
140 . _T('couteau:maj_liste').'</legend>'
142 (count($html_actifs)?
"\n|{{" . _T('couteau:plug_actifs') . "<span id='maj_1'" . $sep . join("\n",$html_actifs) . "\n" : '')
143 . (count($html_extensions)?
"\n|{{" . _T('plugins_liste_extensions') . "<span id='maj_2'". $sep . join("\n",$html_extensions) . "\n" : '')
144 . (count($html_inactifs)?
"\n|{{" . _T('couteau:plug_inactifs') . "<span id='maj_3'". $sep . join("\n",$html_inactifs) . "\n" : '')
146 . "<div style='text-align: right;'><input class='fondo' type='submit' value=\""
147 . attribut_html(_T('couteau:maj_maj'))
148 . '" /><p><i>'._T('couteau:maj_verif2').'</i></p></div></fieldset></div>'
150 jQuery(document).ready(function() {
151 var ch = jQuery('#maj_auto_div .maj_checked');
152 var re = jQuery('.cs_relancer a');
153 if(ch.length) ch[0].checked = true;
155 jQuery('#maj_auto_div :submit').parent().remove();
156 jQuery('#maj_auto_div :radio').attr('disabled','disabled');
158 if(!jQuery('#maj_auto_div :radio:checked').length && jQuery('#maj_auto_div :radio').length)
159 jQuery('#maj_auto_div :radio:first')[0].checked = true;
160 re.click(function() {
161 cs_href_click(jQuery('#maj_auto')[0], true);
164 jQuery('#maj_auto_div thead').click( function() {
165 jQuery(this).next().toggleClass('cs_hidden');
166 span = jQuery('span', this);
167 cs_EcrireCookie(span[0].id, '+'+span[0].className, dixans);
168 span.toggleClass('cs_hidden');
169 // annulation du clic
171 }).each(maj_lire_cookie);
173 function maj_lire_cookie(i,e){
174 jQuery(this).attr('style', 'cursor:pointer;')
175 var span = jQuery('span', this);
176 var c = cs_LireCookie(span[0].id);
177 if(c!==null && c.match('cs_hidden')) {
178 jQuery(this).next().addClass('cs_hidden');
179 span.removeClass('cs_hidden');
184 $html2 = "\n<div class='cs_sobre'><input class='cs_sobre' type='submit' value=\"["
185 . attribut_html(_T('couteau:maj_actu')) . ']" /></div>';
187 // premier formulaire non ajax, lancant directement charger_plugin
188 return redirige_action_post('charger_plugin', '', 'admin_couteau_suisse', "cmd=descrip&outil=maj_auto#cs_infos", $html1)
189 // second formulaire ajax : lien d'actualisation forcee
190 . ajax_action_auteur('action_rapide', 'maj_auto_forcer', 'admin_couteau_suisse', "arg=maj_auto|description_outil&cmd=descrip#cs_action_rapide", $html2);
193 // renvoie le pattern present dans la page distante
194 // si le pattern est NULL, renvoie un simple 'is_file_exists'
195 function maj_auto_rev_distante($url, $timeout=false, $pattern=NULL, $lastmodified=0, $force=false) {
196 $force |
= in_array(_request('var_mode'), array('calcul', 'recalcul'));
197 // pour la version distante, on regarde toutes les 24h00 (meme en cas d'echec)
198 $maj_ = isset($GLOBALS['meta']['tweaks_maj_auto'])?
unserialize($GLOBALS['meta']['tweaks_maj_auto']):array();
199 if(!isset($maj_[$url_=md5($url)])) $maj_[$url_] = array(0, false);
200 $maj = &$maj_[$url_];
201 // prendre le cache si svn.revision n'est pas modifie recemment, si les 24h ne sont pas ecoulee, et si on ne force pas
202 if (!$force && $maj[1]!==false && ($lastmodified<$maj[0]) && (time()-$maj[0] < 24*3600))
207 $distant = $maj[1] = ($pattern!==NULL)
208 ?
(($distant = recuperer_page($url))
209 ?
(preg_match($pattern, $distant, $regs)?
$regs[1]:'-2')
211 :strlen(recuperer_page($url, false, true, 0));
213 ecrire_meta('tweaks_maj_auto', serialize($maj_));
219 function plugin_get_infos_maj($p, $timeout=false, $DIR_PLUGINS=_DIR_PLUGINS
) {
220 if(defined('_SPIP20100')) {
221 $get_infos = charger_fonction('get_infos','plugins');
222 $infos = $get_infos($p, false, $DIR_PLUGINS);
223 } else $infos = plugin_get_infos($p);
224 // fichier svn.revision fourni par SPIP
225 $ok = lire_fichier($svn_rev = $DIR_PLUGINS.$p.'/svn.revision', $svn);
226 $lastmodified = @file_exists
($svn_rev)?@filemtime
($svn_rev):0;
227 if($ok && preg_match(',<origine>(.+)</origine>,', $svn, $regs)) {
228 $url_origine = str_replace(array(_MAJ_SVN_FILE
, _MAJ_SVN_DEBUT
), _MAJ_LOG_DEBUT
, $regs[1]);
229 // prise en compte du recent demenagement de la Zone...
230 $url_origine = preg_replace(',/_plugins_/_(?:stable|dev|test)_/,','/_plugins_/', $url_origine);
231 } else $url_origine = '';
232 $infos['commit'] = ($ok && preg_match(',<commit>(.+)</commit>,', $svn, $regs))?
$regs[1]:'';
233 $rev_local = (strlen($svn) && preg_match(',<revision>(.+)</revision>,', $svn, $regs))
234 ?
intval($regs[1]):version_svn_courante2($DIR_PLUGINS.$p);
235 if($infos['svn'] = is_array($rev_local) ||
$rev_local<0) {
236 // systeme SVN en place
237 if (is_array($rev_local)) // version SVN >= 1.7 ?
238 list($rev_local, $url_origine) = $rev_local;
239 // version SVN anterieure
240 elseif (lire_fichier($DIR_PLUGINS.$p.'/.svn/entries', $svn)
241 && preg_match(',(?:'.preg_quote(_MAJ_SVN_TRAC
).'|'.preg_quote(_MAJ_SVN_DEBUT
).')[^\n\r]+,ms', $svn, $regs))
242 $url_origine = $regs[0];
243 $url_origine = str_replace(array(_MAJ_SVN_TRAC
,_MAJ_SVN_DEBUT
), _MAJ_LOG_DEBUT
, $url_origine);
244 // prise en compte du recent demenagement de la Zone...
245 $url_origine = preg_replace(',/_plugins_/_(?:stable|dev|test)_/,','/_plugins_/', $url_origine);
246 //$infos['zip_trac'] = 'SVN';
248 $infos['url_origine'] = strlen($url_origine)?
$url_origine._MAJ_LOG_FIN
:'';
249 $infos['rev_local'] = abs($rev_local);
250 $infos['rev_rss'] = intval(maj_auto_rev_distante($infos['url_origine'], $timeout, ', \[(\d+)\],', $lastmodified));
251 $infos['maj_dispo'] = $infos['rev_rss']>0 && $infos['rev_local']>0 && $infos['rev_rss']>$infos['rev_local'];
253 $infos['zip_log'] = $infos['zip_trac'] = '';
254 $p2 = preg_match(',^auto/(.*)$,', $p, $regs)?
$regs[1]:'';
256 // supposition du nom d'archive sur files.spip.org
257 if(intval(maj_auto_rev_distante($f = _MAJ_ZIP
.$p2.'.zip', $timeout))) $infos['zip_trac'] = $f;
258 // nom de l'archive recemment installee par chargeur
259 if(lire_fichier(sous_repertoire(_DIR_CACHE
, 'chargeur').$p2.'/install.log', $log)
260 && preg_match(',[\n\r]source: *([^\n\r]+),msi', $log, $regs)
261 && intval(maj_auto_rev_distante($regs[1], $timeout)))
262 $infos['zip_log'] = $regs[1];
263 // au final on prend le bon
264 if(!$infos['zip_trac']) $infos['zip_trac'] = $infos['zip_log'];
269 // fonction {$outil}_{$arg}_action() appelee par action/action_rapide.php
270 function maj_auto_maj_auto_forcer_action() {
271 // forcer la lecture de la derniere version de SPIP
272 if(function_exists('compat_maj_spip')) compat_maj_spip(true); // pour SPIP < 2.1
273 elseif($cron = charger_fonction('mise_a_jour', 'genie')) $cron(0);
274 // forcer la lecture des revisions distantes de plugins
275 ecrire_meta('tweaks_maj_auto', serialize(array()));
279 function version_svn_courante2($dir) {
280 // recherche de la base de donnee
281 if(!$db = @file_exists
($dir2 = realpath($dir . '/.svn/wc.db'))) {
282 // version <1.7 de Subversion (reconnue par SPIP)
283 if(@file_exists
($dir.'/.svn/entries')) return version_svn_courante($dir);
284 // trunk et extensions
285 $db = @file_exists
($dir2 = realpath($dir . '/../.svn/wc.db'));
288 $db = @file_exists
($dir2 = realpath($dir . '/../../.svn/wc.db'));
289 if($db) $b = basename(dirname($dir)).'/'.basename($dir);
290 } else $b = basename($dir);
292 // version 1.7 de Subversion
293 return cs_svn17($dir2);