source: spip-zone/_plugins_/pcltar/inc/charger_plugin.php @ 103864

Last change on this file since 103864 was 103864, checked in by spip.franck@…, 3 years ago

En finir une fois pour toutes avec spip-contrib, pour mettre à la place contrib.spip

File size: 15.6 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2010                                                *
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/*
15 * Ce fichier est extrait du plugin charge : action charger decompresser
16 *
17 * Auteur : bertrand@toggg.com
18 * © 2007 - Distribue sous licence LGPL
19 *
20 */
21
22if (!defined("_ECRIRE_INC_VERSION")) return;
23
24include_spip('inc/plugin');
25include_spip('inc/actions');
26
27// http://doc.spip.org/@formulaire_charger_plugin
28function formulaire_charger_plugin($retour='') {
29        global $spip_lang_left, $spip_lang_right;
30
31        include_spip('inc/filtres');
32        include_spip('inc/actions');
33        include_spip('inc/presentation');
34
35        // Si defini comme non-existant
36        if (!_DIR_PLUGINS)
37                return '';
38
39        $auto = '';
40        if (_DIR_PLUGINS_AUTO) {
41                if (!@is_dir(_DIR_PLUGINS_AUTO)
42                OR !is_writeable(_DIR_PLUGINS_AUTO)) {
43                  $auto = _T('plugin_info_automatique1')."\n"
44                        .'<ol class="spip"><li>'._T('plugin_info_automatique2',array('rep'=>joli_repertoire(_DIR_PLUGINS_AUTO))).'</li>'
45                        .'<li>'._T('plugin_info_automatique3').aide("install0")."</li></ol>"
46                  ."\n<p>"._T('plugin_info_automatique_lib')."</p>";
47                }
48
49                if (!$auto)
50                        $auto = interface_plugins_auto($retour);
51
52        }
53
54        $message = _T('plugin_info_automatique_ftp',array('rep'=>joli_repertoire(_DIR_PLUGINS)));
55        if (!@is_dir(_DIR_PLUGINS))
56                $message .= " &mdash; "._T('plugin_info_automatique_creer');
57
58        return debut_cadre_trait_couleur("spip-pack-24.png", true, "", _T('plugin_titre_automatique_ajouter'))
59                . "<h3>"._T('plugin_titre_automatique')."</h3>"
60                . "<p>".$message."</p>\n"
61                . $auto
62                . fin_cadre_trait_couleur(true);
63
64}
65
66
67// http://doc.spip.org/@interface_plugins_auto
68function interface_plugins_auto($retour) {
69
70        $res = "<div class='verdana2'>";
71
72        if ($retour) {
73                $res .= "<div>$retour</div>\n";
74        }
75
76        $liste = liste_plugins_distants();
77
78        $message .= '<div class="explication">'._T('plugin_zip_adresse')
79  . '<br />'._T('plugin_info_automatique_exemples').'<ul class="spip">';
80
81        $les_urls = array('http://plugins.spip.net/rss-+-selection-2-1-+','https://contrib.spip.net/?page=rss-plugins-spip-2-1');
82        if (isset($GLOBALS['chargeur_urls_rss']) AND is_array($GLOBALS['chargeur_urls_rss']))
83                $les_urls = array_merge($les_urls,$GLOBALS['chargeur_urls_rss']);
84        foreach($les_urls as $url)
85                $message .= "<li><a href='$url' onclick=\"jQuery('#url_zip_plugin2').attr('value',jQuery(this).html()).focus();return false;\">"
86                .$url
87                ."</a></li>";
88        $message .= "</ul></div>";
89
90        $form = "";
91        $form .= "<ul><li class='editer_url_zip_plugin2 obligatoire'>";
92
93        $form .= "<label for='url_zip_plugin2'>"._T('plugin_zip_adresse_champ')."</label>";
94        $form .= $message;
95        $form .= "
96        <input type='text' class='text' id='url_zip_plugin2' name='url_zip_plugin2' value='' size='40' />";
97        $form .= "</li></ul>";
98        $form .=        "<div class='boutons' id='loadrss'><input type='submit' value='"
99                . _T('bouton_valider')
100                .  "'/>\n"
101                .  "</div>\n";
102        $form = redirige_action_post('charger_plugin',
103                                '', // arg = 'plugins' / 'lib', a priori
104                                '',
105                                '',
106                                $form);
107
108        $res .= "<div class='formulaire_spip formulaire_editer'>";
109
110        $res .= $form;
111        $res .= "</div>\n";
112
113
114        $res .= "</div>\n";
115
116        $res .= afficher_liste_listes_plugins();
117
118        if ($liste) {
119                $res .= afficher_liste_plugins_distants($liste);
120
121                $menu = array();
122                $compte = 0;
123
124                $res .=
125                http_script("
126        jQuery(function(){
127                jQuery('.plugins li.item a[rel=info]').click(function(){
128                        var li = jQuery(this).parents('li').eq(0);
129                        if (!jQuery('div.details',li).html()) {
130                                jQuery('div.details',li).prepend(ajax_image_searching).load(
131                                        jQuery(this).attr('href').replace(/admin_plugin|plugins|charger_plugin/, 'info_plugin_distant'), {}, function(){
132                                                li.addClass('on');
133                                        }
134                                );
135                        }
136                        else {
137                                if (jQuery('div.details',li).toggle().is(':visible'))
138                                        li.addClass('on');
139                                else
140                                        li.removeClass('on');
141                        }
142                        return false;
143                });
144        });
145        ");
146
147        }
148        return $res;
149}
150
151function afficher_liste_plugins_distants($liste){
152        $res = "";
153        if (!$liste) return "";
154
155        $menu = array();
156        $compte = 0;
157
158        $afficher_plugin_distant = charger_fonction('afficher_plugin_distant','plugins');
159        $url_page = self();
160        foreach ($liste as $url => $info) {
161                $titre = $info[0];
162                $titre = strtoupper(trim(typo(translitteration(unicode2charset(html2unicode($titre))))));
163                $menu[$titre] = $afficher_plugin_distant($url_page, $url, $info, _request('plugin')==$url);
164        }
165        ksort($menu);
166
167        $res .=
168                "<h3>"._T('plugins_compte',array('count' => count($menu)))."</h3>"
169          . '<p>'._T('plugin_info_automatique_select',array('rep'=>joli_repertoire(_DIR_PLUGINS_AUTO))).'</p>'
170                . "<ul class='liste-items plugins distants'>".join("\n",$menu)."</ul>";
171
172        return $res;
173}
174
175// http://doc.spip.org/@chargeur_charger_zip
176function chargeur_charger_zip($quoi = array())
177{
178        if (!$quoi) {
179                return true;
180        }
181        if (is_scalar($quoi)) {
182                $quoi = array('zip' => $quoi);
183        }
184        if (isset($quoi['depot']) || isset($quoi['nom'])) {
185                $quoi['archive'] = $quoi['depot'] . $quoi['nom'] . '.'.$quoi['type'];
186        }
187        foreach (array( 'remove' => 'spip',
188                                        'arg' => 'lib',
189                                        'plugin' => null,
190                                        'cache_cache' => null,
191                                        'rename' => array(),
192                                        'edit' => array(),
193                                        'root_extract' => false, # extraire a la racine de dest ?
194                                        'tmp' => sous_repertoire(_DIR_CACHE, 'chargeur')
195                                )
196                                as $opt=>$def) {
197                isset($quoi[$opt]) || ($quoi[$opt] = $def);
198        }
199
200
201        # destination finale des fichiers
202        switch($quoi['arg']) {
203                case 'lib':
204                        $quoi['dest'] = _DIR_RACINE.'lib/';
205                        break;
206                case 'plugins':
207                        $quoi['dest'] = _DIR_PLUGINS_AUTO;
208                        break;
209                default:
210                        $quoi['dest'] = '';
211                        break;
212        }
213
214
215        if (!@file_exists($fichier = $quoi['fichier']))
216                return 0;
217
218        if($quoi['type'] === 'zip'){
219                include_spip('inc/pclzip');
220                $zip = new PclZip($fichier);
221                $list = $zip->listContent();
222        }else{
223                include_spip('inc/pcltar');
224                $list = PclTarList($fichier);
225        }
226
227        // on cherche la plus longue racine commune a tous les fichiers
228        foreach($list as $n) {
229                $p = array();
230                foreach(explode('/', $n['filename']) as $n => $x) {
231                        $sofar = join('/',$p);
232                        $paths[$n][$sofar]++;
233                        $p[] = $x;
234                }
235        }
236
237        $total = $paths[0][''];
238        $i = 0;
239        while (isset($paths[$i])
240        AND count($paths[$i]) <= 1
241        AND array_values($paths[$i]) == array($total))
242                $i++;
243
244        $racine = $i
245                ? array_pop(array_keys($paths[$i-1])).'/'
246                : '';
247
248        $quoi['remove'] = $racine;
249
250        if (!strlen($nom = basename($racine)))
251                $nom = basename($fichier, '.zip');
252
253        $dir_export = $quoi['root_extract']
254                ? $quoi['dest']
255                : $quoi['dest'] . $nom.'/';
256
257        $tmpname = $quoi['tmp'].$nom.'/';
258
259        // On extrait, mais dans tmp/ si on ne veut pas vraiment le faire
260        if($quoi['type'] === 'zip'){
261                $ok = $zip->extract(
262                        PCLZIP_OPT_PATH,
263                                $quoi['extract']
264                                        ? $dir_export
265                                        : $tmpname
266                        ,
267                        PCLZIP_OPT_SET_CHMOD, _SPIP_CHMOD,
268                        PCLZIP_OPT_REPLACE_NEWER,
269                        PCLZIP_OPT_REMOVE_PATH, $quoi['remove']
270                );
271                if ($zip->error_code < 0) {
272                        spip_log('charger_decompresser erreur zip ' . $zip->error_code .
273                                ' pour paquet: ' . $quoi['archive']);
274                        return //$zip->error_code
275                                $zip->errorName(true);
276                }
277        }else{
278                $ok = PclTarExtract($fichier,
279                        $quoi['extract']
280                                        ? $dir_export
281                                        : $tmpname,
282                        $quoi['remove']
283                );
284                if ($ok == 0) {
285                        spip_log('charger_decompresser erreur tar ' . PclErrorString() .
286                                ' pour paquet: ' . $quoi['archive']);
287                        return PclErrorString();
288                }
289        }
290
291/*
292 * desactive pour l'instant
293 *
294 *
295                if (!$quoi['cache_cache']) {
296                        chargeur_montre_tout($quoi);
297                }
298                if ($quoi['rename']) {
299                        chargeur_rename($quoi);
300                }
301                if ($quoi['edit']) {
302                        chargeur_edit($dir_export, $quoi['edit']);
303                }
304
305                if ($quoi['plugin']) {
306                        chargeur_activer_plugin($quoi['plugin']);
307                }
308*/
309
310        spip_log('charger_decompresser OK pour paquet: ' . $quoi['zip']);
311
312
313
314        $size = $compressed_size = 0;
315        $removex = ',^'.preg_quote($quoi['remove'], ',').',';
316        foreach ($list as $a => $f) {
317                $size += $f['size'];
318                $compressed_size += $f['compressed_size'];
319                $list[$a] = preg_replace($removex,'',$f['filename']);
320        }
321
322        // Indiquer par un fichier install.log
323        // a la racine que c'est chargeur qui a installe ce plugin
324        ecrire_fichier($tmpname.'/install.log',
325                "installation: charger_plugin\n"
326                ."date: ".gmdate('Y-m-d\TH:i:s\Z', time())."\n"
327                ."source: ".$quoi['zip']."\n"
328        );
329
330
331
332        return array(
333                'files' => $list,
334                'size' => $size,
335                'compressed_size' => $compressed_size,
336                'dirname' => $dir_export,
337                'tmpname' => $tmpname
338        );
339}
340
341// pas de fichiers caches et preg_files() les ignore (*sigh*)
342// http://doc.spip.org/@chargeur_montre_tout
343function chargeur_montre_tout($quoi)
344{
345        # echo($quoi['dest']);
346        if (!($d = @opendir($quoi['dest']))) {
347                return;
348        }
349        while (($f = readdir($d)) !== false) {
350                if ($f == '.' || $f == '..' || $f[0] != '.') {
351                        continue;
352                }
353                rename($quoi['dest'] . '/' . $f, $quoi['dest'] . '/'. substr($f, 1));
354        }
355}
356
357// renommer des morceaux
358// http://doc.spip.org/@chargeur_edit
359function chargeur_edit($dir, $edit)
360{
361        if (!($d = @opendir($dir))) {
362                return;
363        }
364        while (($f = readdir($d)) !== false) {
365                if ($f == '.' || $f == '..') {
366                        continue;
367                }
368                if (is_dir($f = $dir . '/' . $f)) {
369                        chargeur_edit($f, $edit);
370                }
371                $contenu =      file_get_contents($f);
372                if (($change = preg_replace(
373                                array_keys($edit), array_values($edit), $contenu)) == $contenu) {
374                        continue;
375                }
376                $fw = fopen($f, 'w');
377                fwrite($fw, $change);
378                fclose($fw);
379        }
380}
381
382// renommer des morceaux
383// http://doc.spip.org/@chargeur_rename
384function chargeur_rename($quoi)
385{
386/*
387 preg_files() est deficiante pour les fichiers caches, ca aurait pu etre bien pourtant ...
388*/
389        spip_log($quoi);
390        foreach ($quoi['rename'] as $old => $new) {
391                !is_writable($file = $quoi['dest'] . '/' . $old) ||
392                        rename($file, $quoi['dest'] . '/'. $new);
393        }
394}
395
396// juste activer le plugin du repertoire $plugin
397// http://doc.spip.org/@chargeur_activer_plugin
398function chargeur_activer_plugin($plugin)
399{
400        spip_log('charger_decompresser activer plugin: ' . $plugin);
401        include_spip('inc/plugin');
402        ecrire_plugin_actifs(array($plugin), false, 'ajoute');
403}
404
405
406// http://doc.spip.org/@liste_fichiers_pclzip
407function liste_fichiers_pclzip($status) {
408        $list = $status['files'];
409
410        $ret = '<b>'._T('plugin_zip_content',array('taille'=>taille_en_octets($status['size']), 'rep'=>$status['dirname'])).'</b>';
411
412        $l .= "<ul style='font-size:x-small;'>\n";
413        foreach ($list as $f) {
414                if (basename($f) == 'svn.revision')
415                        lire_fichier($status['tmpname'].'/'.$f,$svn);
416                if ($joli = preg_replace(',^(.*/)([^/]+/?)$,', '<span style="visibility:hidden">\1</span>\2', $f)) {
417                        if (!$vu[dirname($f.'x')]++)
418                                $l .= "<li>".$f."</li>\n";
419                        else
420                                $l .= "<li>".$joli."</li>\n";
421                }
422        }
423        $l .= "</ul>\n";
424
425        include_spip('inc/filtres');
426        if (preg_match(',<revision>([^<]+)<,', $svn, $t))
427                $rev = '<div>revision '.$t[1].'</div>';
428        if (preg_match(',<commit>([^<]+),', $svn, $t))
429                $date = '<div>' . affdate($t[1]) .'</div>';
430
431        return $ret . $rev . $date . $l;
432}
433
434// Attention on ne sait pas ce que vaut cette URL
435// http://doc.spip.org/@essaie_ajouter_liste_plugins
436function essaie_ajouter_liste_plugins($url) {
437        if (!preg_match(',^https?://[^.]+\.[^.]+.*/.*[^/]$,', $url))
438                return;
439
440        include_spip('inc/distant');
441        if (!$rss = recuperer_page($url)
442        OR !preg_match(',<item,i', $rss))
443                return;
444
445        $liste = chercher_enclosures_zip($rss,true);
446        if (!$liste)
447                return;
448
449        // Ici c'est bon, on conserve l'url dans spip_meta
450        // et une copie du flux analise dans tmp/
451        ecrire_fichier(_DIR_TMP.'syndic_plug_'.md5($url).'.txt', serialize($liste));
452        $syndic_plug = @unserialize($GLOBALS['meta']['syndic_plug']);
453        $syndic_plug[$url] = count($liste);
454        ecrire_meta('syndic_plug', serialize($syndic_plug));
455}
456
457// Recherche les enclosures de type zip dans un flux rss ou atom
458// les renvoie sous forme de tableau url => titre
459// si $desc on ramene aussi le descriptif du paquet desc
460// http://doc.spip.org/@chercher_enclosures_zip
461function chercher_enclosures_zip($rss, $desc = '') {
462        $liste = array();
463        include_spip('inc/syndic');
464        foreach(analyser_backend($rss) as $item){
465                if ($item['enclosures']
466                AND $zips = extraire_balises($item['enclosures'], 'a')){
467                        if ($img = extraire_balise($item['descriptif'], 'img')
468                          AND $src = extraire_attribut($img, 'src')) {
469                                $item['icon'] = $src;
470                        }
471                        foreach ($zips as $zip)
472                                if (extraire_attribut($zip, 'type') == 'application/zip') {
473                                        if ($url = extraire_attribut($zip, 'href')) {
474                                                $liste[$url] = array($item['titre'], $item['url']);
475                                                if ($desc===true OR $desc == $url)
476                                                        $liste[$url][] = $item;
477                                        }
478                                }
479                }
480        }
481        spip_log(count($liste).' enclosures au format zip');
482        return $liste;
483}
484
485
486// Renvoie la liste des plugins distants (accessibles a travers
487// l'une des listes de plugins)
488// Si on passe desc = un url, ramener le descriptif de ce paquet
489// http://doc.spip.org/@liste_plugins_distants
490function liste_plugins_distants($desc = false) {
491        // TODO une liste multilingue a telecharger
492        $liste = array();
493
494        if (is_array($flux = @unserialize($GLOBALS['meta']['syndic_plug']))) {
495
496                foreach ($flux as $url => $c) {
497                        if (file_exists($cache=_DIR_TMP.'syndic_plug_'.md5($url).'.txt')
498                        AND lire_fichier($cache, $rss))
499                                $liste = array_merge(unserialize($rss),$liste);
500                }
501        }
502
503        return $liste;
504}
505
506// http://doc.spip.org/@afficher_liste_listes_plugins
507function afficher_liste_listes_plugins() {
508        if (!is_array($flux = @unserialize($GLOBALS['meta']['syndic_plug'])))
509                return '';
510
511        if (count($flux)){
512                $ret = '<h3>'._T('plugin_info_automatique_liste').'</h3><ul class="liste-items">';
513                        //$ret .= '<li>'._T('plugin_info_automatique_liste_officielle').'</li>';
514                foreach ($flux as $url => $c) {
515                        $a = '<div class="actions">[<a href="'.parametre_url(
516                                generer_action_auteur('charger_plugin', 'supprimer_flux'),'supprimer_flux', $url).'">'._T('lien_supprimer').'</a>]</div>';
517                        $time = @filemtime(_DIR_TMP.'syndic_plug_'.md5($url).'.txt');
518                        $ret .= '<li class="item">'.inserer_attribut(PtoBR(propre("[->$url]")),'title',$url).' ('._T('plugins_compte',array('count' => $c)).') '
519                                                        .($time?"<div class='small'>" . _T('info_derniere_syndication').' '.affdate(date('Y-m-d H:i:s',$time)) ."</div>":'')
520                                                        . $a .'</li>';
521                }
522                $ret .= '</ul>';
523
524                $ret .= '<div style="text-align:'.$GLOBALS['spip_lang_right'].'"><a href="'.parametre_url(
525                                                                                  generer_action_auteur('charger_plugin', 'update_flux'),'update_flux', 'oui').'">'._T('plugin_info_automatique_liste_update').'</a></div>';
526        }
527
528        return $ret;
529}
530
531// Si le chargement auto est autorise, un bouton
532// sinon on donne l'url du zip
533// http://doc.spip.org/@bouton_telechargement_plugin
534function bouton_telechargement_plugin($url, $rep) {
535        // essayer de creer le repertoire lib/ si on en a le droit
536        if (($rep == 'lib') AND !is_dir(_DIR_RACINE . 'lib'))
537                sous_repertoire(_DIR_RACINE . 'lib','',false,true);
538
539        if (($rep == 'lib')?
540                        is_dir(_DIR_RACINE . 'lib'):
541                        (_DIR_PLUGINS_AUTO AND @is_dir(_DIR_PLUGINS_AUTO))
542                )
543                $bouton = redirige_action_post('charger_plugin',
544                        $rep, // arg = 'lib' ou 'plugins'
545                        '',
546                        '',
547                        "<input type='hidden' name='url_zip_plugin' value='$url' />"
548                        ."<input type='submit' name='ok' value='"._T('bouton_telecharger')."' />",
549                        'class="noajax"');
550        else if ($rep == 'lib'){
551                $bouton = "<div class='info_todo'>"._T('plugin_info_automatique1_lib')."\n"
552                .'<ol><li>'._T('plugin_info_automatique2',array('rep'=>joli_repertoire(_DIR_RACINE . 'lib/'))).'</li>'
553                .'<li>'._T('plugin_info_automatique3').aide("install0")."</li></ol></div>";
554        }
555
556        return _T('plugin_info_telecharger',array('url'=>$url,'rep'=>$rep.'/')).$bouton;
557
558}
559
560?>
Note: See TracBrowser for help on using the repository browser.