3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2011 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
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 \***************************************************************************/
15 * Ce fichier est extrait du plugin charge : action charger decompresser
17 * Auteur : bertrand@toggg.com
18 * © 2007 - Distribue sous licence LGPL
22 if (!defined('_ECRIRE_INC_VERSION')) return;
24 include_spip('inc/plugin');
25 include_spip('inc/actions');
27 // http://doc.spip.org/@formulaire_charger_plugin
28 function formulaire_charger_plugin($retour='') {
29 global $spip_lang_left, $spip_lang_right;
31 include_spip('inc/filtres');
32 include_spip('inc/presentation');
34 // Si defini comme non-existant
39 if (_DIR_PLUGINS_AUTO
) {
40 if (!@is_dir
(_DIR_PLUGINS_AUTO
)
41 OR !is_writeable(_DIR_PLUGINS_AUTO
)) {
42 $auto = _T('plugin_info_automatique1')."\n"
43 .'<ol class="spip"><li>'._T('plugin_info_automatique2',array('rep'=>joli_repertoire(_DIR_PLUGINS_AUTO
))).'</li>'
44 .'<li>'._T('plugin_info_automatique3').aide("install0")."</li></ol>"
45 ."\n<p>"._T('plugin_info_automatique_lib')."</p>";
49 $auto = interface_plugins_auto($retour);
53 $message = _T('plugin_info_automatique_ftp',array('rep'=>joli_repertoire(_DIR_PLUGINS
)));
54 if (!@is_dir
(_DIR_PLUGINS
))
55 $message .= " — "._T('plugin_info_automatique_creer');
57 return debut_cadre_trait_couleur("spip-pack-24.png", true, "", _T('plugin_titre_automatique_ajouter'))
58 . "<h3>"._T('plugin_titre_automatique')."</h3>"
59 . "<p>".$message."</p>\n"
61 . fin_cadre_trait_couleur(true);
66 // http://doc.spip.org/@interface_plugins_auto
67 function interface_plugins_auto($retour) {
69 $res = "<div class='verdana2'>";
72 $res .= "<div>$retour</div>\n";
75 $liste = liste_plugins_distants();
77 $message .= '<div class="explication">'._T('plugin_zip_adresse')
78 . '<br />'._T('plugin_info_automatique_exemples').'<ul class="spip">';
80 $les_urls = array('http://plugins.spip.net/rss-+-selection-2-1-+','http://www.spip-contrib.net/?page=rss-plugins-spip-2-1');
81 if (isset($GLOBALS['chargeur_urls_rss']) AND is_array($GLOBALS['chargeur_urls_rss']))
82 $les_urls = array_merge($les_urls,$GLOBALS['chargeur_urls_rss']);
83 foreach($les_urls as $url)
84 $message .= "<li><a href='$url' onclick=\"jQuery('#url_zip_plugin2').attr('value',jQuery(this).html()).focus();return false;\">"
87 $message .= "</ul></div>";
90 $form .= "<ul><li class='editer_url_zip_plugin2 obligatoire'>";
92 $form .= "<label for='url_zip_plugin2'>"._T('plugin_zip_adresse_champ')."</label>";
95 <input type='text' class='text' id='url_zip_plugin2' name='url_zip_plugin2' value='' size='40' />";
96 $form .= "</li></ul>";
97 $form .= "<div class='boutons' id='loadrss'><input type='submit' value='"
98 . _T('bouton_valider')
101 $form = redirige_action_post('charger_plugin',
102 '', // arg = 'plugins' / 'lib', a priori
107 $res .= "<div class='formulaire_spip formulaire_editer'>";
115 $res .= afficher_liste_listes_plugins();
118 $res .= afficher_liste_plugins_distants($liste);
126 jQuery('.plugins li.item a[rel=info]').click(function(){
127 var li = jQuery(this).parents('li').eq(0);
128 if (!jQuery('div.details',li).html()) {
129 jQuery('div.details',li).prepend(ajax_image_searching).load(
130 jQuery(this).attr('href').replace(/admin_plugin|plugins|charger_plugin/, 'info_plugin_distant'), {}, function(){
136 if (jQuery('div.details',li).toggle().is(':visible'))
139 li.removeClass('on');
150 function afficher_liste_plugins_distants($liste){
152 if (!$liste) return "";
157 $afficher_plugin_distant = charger_fonction('afficher_plugin_distant','plugins');
159 foreach ($liste as $url => $info) {
161 $titre = strtoupper(trim(typo(translitteration(unicode2charset(html2unicode($titre))))));
162 $menu[$titre] = $afficher_plugin_distant($url_page, $url, $info, _request('plugin')==$url);
167 "<h3>"._T('plugins_compte',array('count' => count($menu)))."</h3>"
168 . '<p>'._T('plugin_info_automatique_select',array('rep'=>joli_repertoire(_DIR_PLUGINS_AUTO
))).'</p>'
169 . "<ul class='liste-items plugins distants'>".join("\n",$menu)."</ul>";
174 // http://doc.spip.org/@chargeur_charger_zip
175 function chargeur_charger_zip($quoi = array())
180 if (is_scalar($quoi)) {
181 $quoi = array('zip' => $quoi);
183 if (isset($quoi['depot']) ||
isset($quoi['nom'])) {
184 $quoi['zip'] = $quoi['depot'] . $quoi['nom'] . '.zip';
186 foreach (array( 'remove' => 'spip',
189 'cache_cache' => null,
192 'root_extract' => false, # extraire a la racine de dest ?
193 'tmp' => sous_repertoire(_DIR_CACHE
, 'chargeur')
196 isset($quoi[$opt]) ||
($quoi[$opt] = $def);
200 # destination finale des fichiers
201 switch($quoi['arg']) {
203 $quoi['dest'] = _DIR_RACINE
.'lib/';
206 $quoi['dest'] = _DIR_PLUGINS_AUTO
;
214 if (!@file_exists
($fichier = $quoi['fichier']))
217 include_spip('inc/pclzip');
218 $zip = new PclZip($fichier);
219 $list = $zip->listContent();
221 // on cherche la plus longue racine commune a tous les fichiers
223 foreach($list as $n) {
225 foreach(explode('/', $n['filename']) as $n => $x) {
228 $sofar = join('/',$p);
229 $paths[$n][$sofar]++
;
232 $max_n = min($n,$max_n);
235 $total = $paths[0][''];
237 while (isset($paths[$i])
238 AND count($paths[$i]) <= 1
239 AND array_values($paths[$i]) == array($total))
243 ?
array_pop(array_keys($paths[$i-1])).'/'
246 $quoi['remove'] = $racine;
248 if (!strlen($nom = basename($racine)))
249 $nom = basename($fichier, '.zip');
251 $dir_export = $quoi['root_extract']
253 : $quoi['dest'] . $nom.'/';
255 $tmpname = $quoi['tmp'].$nom.'/';
257 // On extrait, mais dans tmp/ si on ne veut pas vraiment le faire
264 PCLZIP_OPT_SET_CHMOD
, _SPIP_CHMOD
,
265 PCLZIP_OPT_REPLACE_NEWER
,
266 PCLZIP_OPT_REMOVE_PATH
, $quoi['remove']
268 if ($zip->error_code
< 0) {
269 spip_log('charger_decompresser erreur zip ' . $zip->error_code
.
270 ' pour paquet: ' . $quoi['zip']);
271 return //$zip->error_code
272 $zip->errorName(true);
276 * desactive pour l'instant
279 if (!$quoi['cache_cache']) {
280 chargeur_montre_tout($quoi);
282 if ($quoi['rename']) {
283 chargeur_rename($quoi);
286 chargeur_edit($dir_export, $quoi['edit']);
289 if ($quoi['plugin']) {
290 chargeur_activer_plugin($quoi['plugin']);
294 spip_log('charger_decompresser OK pour paquet: ' . $quoi['zip']);
298 $size = $compressed_size = 0;
299 $removex = ',^'.preg_quote($quoi['remove'], ',').',';
300 foreach ($list as $a => $f) {
302 $compressed_size +
= $f['compressed_size'];
303 $list[$a] = preg_replace($removex,'',$f['filename']);
306 // Indiquer par un fichier install.log
307 // a la racine que c'est chargeur qui a installe ce plugin
308 ecrire_fichier($tmpname.'/install.log',
309 "installation: charger_plugin\n"
310 ."date: ".gmdate('Y-m-d\TH:i:s\Z', time())."\n"
311 ."source: ".$quoi['zip']."\n"
319 'compressed_size' => $compressed_size,
320 'dirname' => $dir_export,
321 'tmpname' => $tmpname
325 // pas de fichiers caches et preg_files() les ignore (*sigh*)
326 // http://doc.spip.org/@chargeur_montre_tout
327 function chargeur_montre_tout($quoi)
329 # echo($quoi['dest']);
330 if (!($d = @opendir
($quoi['dest']))) {
333 while (($f = readdir($d)) !== false) {
334 if ($f == '.' ||
$f == '..' ||
$f[0] != '.') {
337 rename($quoi['dest'] . '/' . $f, $quoi['dest'] . '/'. substr($f, 1));
341 // renommer des morceaux
342 // http://doc.spip.org/@chargeur_edit
343 function chargeur_edit($dir, $edit)
345 if (!($d = @opendir
($dir))) {
348 while (($f = readdir($d)) !== false) {
349 if ($f == '.' ||
$f == '..') {
352 if (is_dir($f = $dir . '/' . $f)) {
353 chargeur_edit($f, $edit);
355 $contenu = file_get_contents($f);
356 if (($change = preg_replace(
357 array_keys($edit), array_values($edit), $contenu)) == $contenu) {
360 $fw = fopen($f, 'w');
361 fwrite($fw, $change);
366 // renommer des morceaux
367 // http://doc.spip.org/@chargeur_rename
368 function chargeur_rename($quoi)
371 preg_files() est deficiante pour les fichiers caches, ca aurait pu etre bien pourtant ...
374 foreach ($quoi['rename'] as $old => $new) {
375 !is_writable($file = $quoi['dest'] . '/' . $old) ||
376 rename($file, $quoi['dest'] . '/'. $new);
380 // juste activer le plugin du repertoire $plugin
381 // http://doc.spip.org/@chargeur_activer_plugin
382 function chargeur_activer_plugin($plugin)
384 spip_log('charger_decompresser activer plugin: ' . $plugin);
385 include_spip('inc/plugin');
386 ecrire_plugin_actifs(array($plugin), false, 'ajoute');
390 // http://doc.spip.org/@liste_fichiers_pclzip
391 function liste_fichiers_pclzip($status) {
392 $list = $status['files'];
394 $ret = '<b>'._T('plugin_zip_content',array('taille'=>taille_en_octets($status['size']), 'rep'=>$status['dirname'])).'</b>';
396 $l .= "<ul style='font-size:x-small;'>\n";
397 foreach ($list as $f) {
398 if (basename($f) == 'svn.revision')
399 lire_fichier($status['tmpname'].'/'.$f,$svn);
400 if ($joli = preg_replace(',^(.*/)([^/]+/?)$,', '<span style="visibility:hidden">\1</span>\2', $f)) {
401 if (!$vu[dirname($f.'x')]++
)
402 $l .= "<li>".$f."</li>\n";
404 $l .= "<li>".$joli."</li>\n";
409 include_spip('inc/filtres');
410 if (preg_match(',<revision>([^<]+)<,', $svn, $t))
411 $rev = '<div>revision '.$t[1].'</div>';
412 if (preg_match(',<commit>([^<]+),', $svn, $t))
413 $date = '<div>' . affdate($t[1]) .'</div>';
415 return $ret . $rev . $date . $l;
418 // Attention on ne sait pas ce que vaut cette URL
419 // http://doc.spip.org/@essaie_ajouter_liste_plugins
420 function essaie_ajouter_liste_plugins($url) {
421 if (!preg_match(',^https?://[^.]+\.[^.]+.*/.*[^/]$,', $url))
424 include_spip('inc/distant');
425 if (!$rss = recuperer_page($url)
426 OR !preg_match(',<item,i', $rss))
429 $liste = chercher_enclosures_zip($rss,true);
433 // Ici c'est bon, on conserve l'url dans spip_meta
434 // et une copie du flux analise dans tmp/
435 ecrire_fichier(_DIR_TMP
.'syndic_plug_'.md5($url).'.txt', serialize($liste));
436 $syndic_plug = @unserialize
($GLOBALS['meta']['syndic_plug']);
437 $syndic_plug[$url] = count($liste);
438 ecrire_meta('syndic_plug', serialize($syndic_plug));
441 // Recherche les enclosures de type zip dans un flux rss ou atom
442 // les renvoie sous forme de tableau url => titre
443 // si $desc on ramene aussi le descriptif du paquet desc
444 // http://doc.spip.org/@chercher_enclosures_zip
445 function chercher_enclosures_zip($rss, $desc = '') {
447 include_spip('inc/syndic');
448 foreach(analyser_backend($rss) as $item){
449 if ($item['enclosures']
450 AND $zips = extraire_balises($item['enclosures'], 'a')){
451 if ($img = extraire_balise($item['descriptif'], 'img')
452 AND $src = extraire_attribut($img, 'src')) {
453 $item['icon'] = $src;
455 foreach ($zips as $zip)
456 if (extraire_attribut($zip, 'type') == 'application/zip') {
457 if ($url = extraire_attribut($zip, 'href')) {
458 $liste[$url] = array($item['titre'], $item['url']);
459 if ($desc===true OR $desc == $url)
460 $liste[$url][] = $item;
465 spip_log(count($liste).' enclosures au format zip');
470 // Renvoie la liste des plugins distants (accessibles a travers
471 // l'une des listes de plugins)
472 // Si on passe desc = un url, ramener le descriptif de ce paquet
473 // http://doc.spip.org/@liste_plugins_distants
474 function liste_plugins_distants($desc = false) {
475 // TODO une liste multilingue a telecharger
478 if (is_array($flux = @unserialize
($GLOBALS['meta']['syndic_plug']))) {
480 foreach ($flux as $url => $c) {
481 if (file_exists($cache=_DIR_TMP
.'syndic_plug_'.md5($url).'.txt')
482 AND lire_fichier($cache, $rss))
483 $liste = array_merge(unserialize($rss),$liste);
490 // http://doc.spip.org/@afficher_liste_listes_plugins
491 function afficher_liste_listes_plugins() {
492 if (!is_array($flux = @unserialize
($GLOBALS['meta']['syndic_plug'])))
496 $ret = '<h3>'._T('plugin_info_automatique_liste').'</h3><ul class="liste-items">';
497 //$ret .= '<li>'._T('plugin_info_automatique_liste_officielle').'</li>';
498 foreach ($flux as $url => $c) {
499 $a = '<div class="actions">[<a href="'.parametre_url(
500 generer_action_auteur('charger_plugin', 'supprimer_flux'),'supprimer_flux', $url).'">'._T('lien_supprimer').'</a>]</div>';
501 $time = @filemtime
(_DIR_TMP
.'syndic_plug_'.md5($url).'.txt');
502 $ret .= '<li class="item">'.inserer_attribut(PtoBR(propre("[->$url]")),'title',$url).' ('._T('plugins_compte',array('count' => $c)).') '
503 .($time?
"<div class='small'>" . _T('info_derniere_syndication').' '.affdate(date('Y-m-d H:i:s',$time)) ."</div>":'')
508 $ret .= '<div style="text-align:'.$GLOBALS['spip_lang_right'].'"><a href="'.parametre_url(
509 generer_action_auteur('charger_plugin', 'update_flux'),'update_flux', 'oui').'">'._T('plugin_info_automatique_liste_update').'</a></div>';
515 // Si le chargement auto est autorise, un bouton
516 // sinon on donne l'url du zip
517 // http://doc.spip.org/@bouton_telechargement_plugin
518 function bouton_telechargement_plugin($url, $rep) {
519 // essayer de creer le repertoire lib/ si on en a le droit
520 if (($rep == 'lib') AND !is_dir(_DIR_RACINE
. 'lib'))
521 sous_repertoire(_DIR_RACINE
. 'lib','',false,true);
524 is_dir(_DIR_RACINE
. 'lib'):
525 (_DIR_PLUGINS_AUTO
AND @is_dir
(_DIR_PLUGINS_AUTO
))
527 $bouton = redirige_action_post('charger_plugin',
528 $rep, // arg = 'lib' ou 'plugins'
531 "<input type='hidden' name='url_zip_plugin' value='$url' />"
532 ."<input type='submit' name='ok' value='"._T('bouton_telecharger')."' />",
534 else if ($rep == 'lib'){
535 $bouton = "<div class='info_todo'>"._T('plugin_info_automatique1_lib')."\n"
536 .'<ol><li>'._T('plugin_info_automatique2',array('rep'=>joli_repertoire(_DIR_RACINE
. 'lib/'))).'</li>'
537 .'<li>'._T('plugin_info_automatique3').aide("install0")."</li></ol></div>";
540 return _T('plugin_info_telecharger',array('url'=>$url,'rep'=>$rep.'/')).$bouton;