From f0488ae6100cdefb8cae462af7b748d9dfb36e26 Mon Sep 17 00:00:00 2001 From: Fil <fil@rezo.net> Date: Fri, 20 Jul 2007 05:14:23 +0000 Subject: [PATCH] integration du chargeur/activateur de toggg, permet d'installer des plugins en trois clics --- .gitattributes | 2 + ecrire/action/charger_plugin.php | 103 ++++++++++ ecrire/exec/admin_plugin.php | 54 ++++-- ecrire/inc/boutons.php | 6 +- ecrire/inc/charger_plugin.php | 312 +++++++++++++++++++++++++++++++ ecrire/inc/commencer_page.php | 25 +-- ecrire/inc/plugin.php | 9 +- 7 files changed, 478 insertions(+), 33 deletions(-) create mode 100644 ecrire/action/charger_plugin.php create mode 100644 ecrire/inc/charger_plugin.php diff --git a/.gitattributes b/.gitattributes index e74b6b09fa..6737ffe1f4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -347,6 +347,7 @@ dist/vignettes/zip.png -text dist/win_width.htc -text ecrire/action/acceder_document.php -text ecrire/action/activer_plugins.php -text +ecrire/action/charger_plugin.php -text ecrire/action/configurer.php -text ecrire/action/configurer_relayeur.php -text ecrire/action/converser.php -text @@ -541,6 +542,7 @@ ecrire/inc/article_select.php -text ecrire/inc/auteur_infos.php -text ecrire/inc/autoriser.php -text ecrire/inc/boutons.php -text +ecrire/inc/charger_plugin.php -text ecrire/inc/chercher_logo.php -text ecrire/inc/chercher_rubrique.php -text ecrire/inc/class.JavaScriptPacker.php -text diff --git a/ecrire/action/charger_plugin.php b/ecrire/action/charger_plugin.php new file mode 100644 index 0000000000..1ff949e6e9 --- /dev/null +++ b/ecrire/action/charger_plugin.php @@ -0,0 +1,103 @@ +<?php + +/***************************************************************************\ + * SPIP, Systeme de publication pour l'internet * + * * + * Copyright (c) 2001-2007 * + * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * + * * + * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * + * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * +\***************************************************************************/ + + +/* + * Ce fichier est extrait du plugin charge : action charger decompresser + * + * Auteur : bertrand@toggg.com + * © 2007 - Distribue sous licence LGPL + * + */ + +if (!defined("_ECRIRE_INC_VERSION")) return; + +function action_charger_plugin_dist() { + include_spip('inc/minipres'); + include_spip('inc/charger_plugin'); + + // droits : il faut avoir le droit de choisir les plugins, + // mais aussi d'en ajouter -- a voir + include_spip('inc/autoriser'); + if (!autoriser('configurer', 'plugins') + OR !autoriser('webmestre')) { + echo minipres(); + exit; + } + + if (!preg_match(',^(https?|ftp)://.*\.zip,', + $zip = _request('url_zip_plugin2')) + AND !preg_match(',^(https?|ftp)://.*\.zip,', + $zip = _request('url_zip_plugin'))) + { + include_spip('inc/headers'); + redirige_par_entete(generer_url_ecrire('admin_plugin')); + } + + # destination des fichiers + $dest = _DIR_PLUGINS_AUTO; + + # eliminer plugins/ du chemin indique + $remove = 'plugins'; + + $status = chargeur_charger_zip( + array( + 'zip' => $zip, + 'remove' => $remove, + 'dest' => $dest, + 'keep' => false // conserver le .zip ? + ) + ); + + if (is_array($status)) { + $retour = _L('Plugin chargé'); + $texte = '<p>'._L('Le fichier '.$zip.' a été téléchargé et installé').'</p>'; + $texte .= liste_fichiers_pclzip($status); + $texte .= _L("<h2 style='text-align:center;'>Vous pouvez maintenant l'activer.</h2>"); + } else if ($status < 0) { + $retour = _T('erreur'); + $texte = _L("echec pclzip : erreur ").$status; + } else if ($status == 0) { + $retour = _T('erreur'); + $texte = _L('erreur : impossible de charger '.$zip); + } + + include_spip('exec/install'); // pour bouton_suivant() + echo minipres($retour, + generer_form_ecrire('admin_plugin&plug='.$status['dirname'], $texte . bouton_suivant()) + ); + exit; + + + // 0 = rien, pas charge + // liste de fichiers = retour gagnant + // < 0 = erreur pclzip + // ----- Error codes + // -1 : Unable to open file in binary write mode + // -2 : Unable to open file in binary read mode + // -3 : Invalid parameters + // -4 : File does not exist + // -5 : Filename is too long (max. 255) + // -6 : Not a valid zip file + // -7 : Invalid extracted file size + // -8 : Unable to create directory + // -9 : Invalid archive extension + // -10 : Invalid archive format + // -11 : Unable to delete file (unlink) + // -12 : Unable to rename file (rename) + // -13 : Invalid header checksum + // -14 : Invalid archive size + +# redirige_par_entete($url_retour); +} + +?> diff --git a/ecrire/exec/admin_plugin.php b/ecrire/exec/admin_plugin.php index 6e40c28c43..b6169cddd3 100644 --- a/ecrire/exec/admin_plugin.php +++ b/ecrire/exec/admin_plugin.php @@ -20,8 +20,7 @@ include_spip('inc/actions'); include_spip('inc/securiser_action'); // http://doc.spip.org/@exec_admin_plugin_dist -function exec_admin_plugin_dist() { - global $spip_lang_right; +function exec_admin_plugin_dist($retour='') { if (!autoriser('configurer', 'plugins')) { include_spip('inc/minipres'); @@ -36,7 +35,9 @@ function exec_admin_plugin_dist() { echo "<br/><br/><br/>"; echo gros_titre(_T('icone_admin_plugin'),'',false); - // barre_onglets("configuration", "plugin"); // a creer dynamiquement en fonction des plugin charges qui utilisent une page admin ? + + + // barre_onglets("configuration", "plugin"); // a creer dynamiquement en fonction des plugin charges qui utilisent une page admin ? // cfg echo debut_gauche('plugin',true); echo debut_boite_info(true); @@ -52,32 +53,55 @@ function exec_admin_plugin_dist() { // on fait l'installation ici, cela permet aux scripts d'install de faire des affichages ... installe_plugins(); - echo debut_droite('plugin',true); - if (isset($GLOBALS['meta']['plugin_erreur_activation'])){ - echo $GLOBALS['meta']['plugin_erreur_activation']; - effacer_meta('plugin_erreur_activation'); - } + echo debut_droite('plugin', true); - echo debut_cadre_trait_couleur('',true,'',_T('plugins_liste'),'liste_plugins'); + + echo debut_cadre_trait_couleur('',true,'',_T('plugins_liste'), + 'liste_plugins'); echo _T('texte_presente_plugin'); $lpf = liste_plugin_files(); $lcpa = liste_chemin_plugin_actifs(); - $sub = "\n<div style='text-align:$spip_lang_right'>" + + $sub = "\n<div style='text-align:".$GLOBALS['spip_lang_right']."'>" . "<input type='submit' value='"._T('bouton_valider')."' class='fondo' />" . "</div>"; - $corps = $sub - . affiche_arbre_plugins($lpf, $lcpa) - . "\n<br />" - . $sub; + + // S'il y a plus de 10 plugins pas installes, les signaler a part ; + // mais on affiche tous les plugins mis a la racine + if (count($lpf) - count($lcpa) > 9 + AND _request('afficher_tous_plugins') != 'oui') { + $lcpaffiche = array(); + foreach ($lpf as $f) + if (!strpos($f, '/') OR in_array($f, $lcpa)) + $lcpaffiche[] = $f; + $corps = "<p>"._L(count($lcpa).' plugins activés.')."</p>\n" + . "<p><a href='". parametre_url(self(),'afficher_tous_plugins', 'oui') ."'>"._L(count($lpf).' plugins disponibles.')."</a></p>\n" + . affiche_arbre_plugins($lcpaffiche, $lcpa); + + } else { + $corps = + "<p>"._L(count($lcpa).' plugins activés')."</p>\n" + . "<p>"._L(count($lpf).' plugins disponibles.')."</p>\n" + . (count($lpf)>20 ? $sub : '') + . affiche_arbre_plugins($lpf, $lcpa); + } + + + $corps .= "\n<br />" . $sub; echo redirige_action_auteur('activer_plugins','activer','admin_plugin','', $corps, " method='post'"); + if (include_spip('inc/charger_plugin')) { + echo formulaire_charger_plugin($retour); + } + echo fin_cadre_trait_couleur(true); echo fin_gauche(), fin_page(); + } // http://doc.spip.org/@tree_open_close_dir @@ -172,7 +196,7 @@ function affiche_arbre_plugins($liste_plugins,$liste_plugins_actifs){ var prefix = jQuery(this).parent().prev().attr('name'); if (!jQuery(this).siblings('div.info').html()) { jQuery(this).siblings('div.info').prepend(ajax_image_searching).load( - jQuery(this).attr('href').replace(/admin_plugin/, 'info_plugin'), {}, + jQuery(this).attr('href').replace(/admin_plugin|plugins/, 'info_plugin'), {}, function() { document.location = '#' + prefix; } diff --git a/ecrire/inc/boutons.php b/ecrire/inc/boutons.php index e75e5d3f05..67161a92ad 100644 --- a/ecrire/inc/boutons.php +++ b/ecrire/inc/boutons.php @@ -197,10 +197,10 @@ function definir_barre_boutons() { new Bouton("cache-24.gif", "onglet_vider_cache"); } - if (@file_exists(_DIR_PLUGINS) + if (/*@file_exists(_DIR_PLUGINS) AND is_dir(_DIR_PLUGINS) - AND autoriser('configurer', 'admin_plugins') - ) { + AND */ + autoriser('configurer', 'admin_plugin')) { $sousmenu['admin_plugin']= new Bouton("plugin-24.gif", "icone_admin_plugin"); } diff --git a/ecrire/inc/charger_plugin.php b/ecrire/inc/charger_plugin.php new file mode 100644 index 0000000000..efad6948b6 --- /dev/null +++ b/ecrire/inc/charger_plugin.php @@ -0,0 +1,312 @@ +<?php + +/***************************************************************************\ + * SPIP, Systeme de publication pour l'internet * + * * + * Copyright (c) 2001-2007 * + * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * + * * + * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * + * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * +\***************************************************************************/ + + +/* + * Ce fichier est extrait du plugin charge : action charger decompresser + * + * Auteur : bertrand@toggg.com + * © 2007 - Distribue sous licence LGPL + * + */ + +if (!defined("_ECRIRE_INC_VERSION")) return; + + +# l'adresse du repertoire de telechargement et de decompactage des plugins +#define('_DIR_PLUGINS_AUTO', _DIR_PLUGINS.'auto/'); +define('_DIR_PLUGINS_AUTO', _DIR_PLUGINS); + +include_spip('inc/plugin'); + + +function formulaire_charger_plugin($retour='') { + global $spip_lang_left, $spip_lang_right; + + include_spip('inc/filtres'); + include_spip('inc/actions'); + include_spip('inc/presentation'); + + + $message = _L("Vous pouvez installer des plugins dans le répertoire <code>".joli_repertoire(_DIR_PLUGINS)."</code>."); + + + if (!is_dir(_DIR_PLUGINS_AUTO) + OR !is_writeable(_DIR_PLUGINS_AUTO)) { + $erreur = _L("Pour permettre l'installation automatique des plugins, veuillez créer le répertoire <code>".joli_repertoire(_DIR_PLUGINS_AUTO)."</code> et vérifier que le serveur est autorisé à y écrire.").aide("droits"); + } + + + if ($erreur) { + return debut_cadre_trait_couleur("spip-pack-24.png", true, "", _L('Ajouter des plugins')) + . "<p>".$message."</p>\n" + . "<p>".$erreur."</p>\n" + . fin_cadre_trait_couleur(true); + } + + + $res = "<table border='0' cellspacing='1' cellpadding='3' width=\"100%\">"; + + if ($retour) { + $res .= "<tr><td class='verdana2'>"; + $res .= $retour; + $res .= "</td></tr>\n"; + } + + + $res .= "<tr><td class='verdana2'>"; + + // TODO une liste multilingue a telecharger + $liste = array( + 'http://files.spip.org/spip-zone/crayons.zip' => 'Les Crayons', + 'http://files.spip.org/spip-zone/forms_et_tables_1_9_1.zip' => 'Forms & tables', + 'http://files.spip.org/spip-zone/autorite.zip' => 'Autorité', + 'http://files.spip.org/spip-zone/cfg.zip' => 'CFG, outil de configuration', + 'http://files.spip.org/spip-zone/ortho.zip' => 'Correcteur d\'orthographe' + ); + + + $res .= _L('<p>Sélectionnez ci-dessous un plugin ; SPIP le téléchargera et l\'installera dans le répertoire <code>'.joli_repertoire(_DIR_PLUGINS_AUTO).'</code></p> + <p>Si ce plugin existe déjà, il sera mis à jour.</p>'); + + if ($liste) { + $menu = ''; + foreach ($liste as $url => $titre) + $menu .= '<option value="'.entites_html($url).'">'.$titre."</option>\n"; + $res .= "<p><select name='url_zip_plugin'>\n" + ."<option>"._L('choisir...')."</option>" + .$menu."\n</select></p>\n"; + + $res .= _L("<p><label>... ou entrez l'adresse URL du fichier ZIP du plugin à télécharger :"); + } else + $res .= _L("<p><label>entrez l'adresse URL du fichier ZIP du plugin à télécharger"); + + // TODO: OU l'adresse d'une liste de plugins + // TODO: OU uploadez un fichier ZIP ou une liste de plugins + + $res .= "<br /><input type='text' name='url_zip_plugin2' value='http://files.spip.org/spip-zone/' size='50' /></label></p>\n"; + + $res .= "</td></tr>"; + $res .= "</table>\n"; + + $res = ajax_action_post('charger_plugin', '', 'admin_plugin', '', $res); + + + $res = debut_cadre_trait_couleur("spip-pack-24.png", true, "", _L('Ajouter un plugin')) + . $res + . fin_cadre_trait_couleur(true); + + return $res; + +} + + +function chargeur_charger_zip($quoi = array()) +{ + if (!$quoi) { + return true; + } + if (is_scalar($quoi)) { + $quoi = array('zip' => $quoi); + } + if (isset($quoi['depot']) || isset($quoi['nom'])) { + $quoi['zip'] = $quoi['depot'] . $quoi['nom'] . '.zip'; + } + foreach (array( 'remove' => 'spip', + 'dest' => _DIR_RACINE, + 'plugin' => null, + 'cache_cache' => null, + 'rename' => array(), + 'keep' => false, # keep a copy + 'edit' => array()) + as $opt=>$def) { + isset($quoi[$opt]) || ($quoi[$opt] = $def); + } + + include_spip('inc/distant'); + $contenu = recuperer_page($quoi['zip'], false, false, + 8000000 /* taille max */); + + $fichier = $quoi['dest'].basename($quoi['zip']); + if (!$contenu || !ecrire_fichier($fichier, $contenu)) { + spip_log('charger_decompresser impossible de charger ' . $quoi['zip']); + return 0; + } + + include_spip('inc/pclzip'); + $zip = new PclZip($fichier); + $list = $zip->listContent(); + $i = count($list) - 1; + $path = explode('/', $list[$i]['filename']); + while ($i--) { + $act = explode('/', $list[$i]['filename']); + for ($j = 0; $j < count($path); ++$j) { + if ($j >= count($path) || $act[$j] != $path[$j]) { + break; + } + } + for ( ; $j < count($path); ++$j) { + unset($path[$j]); + } + } + $aremove = explode('/', $quoi['remove']); + $jmax = count($path); + for ($j = 0; $j < $jmax; ++$j) { + if ($j >= count($aremove) || $path[$j] != $aremove[$j]) { + break; + } + unset($path[$j]); + } + $adest = explode('/', $quoi['dest']); + $kmax = count($adest); + for ($k = 0 ; $k < $kmax && $j < $jmax; ++$j, ++$k) { + if ($path[$j] != $adest[$k]) { + break; + } + unset($adest[$k]); + } + $quoi['dest'] = implode('/', $adest); + + $ok = $zip->extract( + PCLZIP_OPT_PATH, $quoi['dest'], + PCLZIP_OPT_SET_CHMOD, _SPIP_CHMOD, + PCLZIP_OPT_REPLACE_NEWER, + PCLZIP_OPT_REMOVE_PATH, $quoi['remove'] . "/"); + if ($zip->error_code < 0) { + spip_log('charger_decompresser erreur zip ' . $zip->error_code . + ' pour paquet: ' . $quoi['zip']); + return $zip->error_code; + } + + # supprimer le fichier zip source ? + if (!$quoi['keep']) + @unlink($fichier); + + if (!$quoi['cache_cache']) { + chargeur_montre_tout($quoi); + } + if ($quoi['rename']) { + chargeur_rename($quoi); + } + if ($quoi['edit']) { + chargeur_edit($quoi['dest'], $quoi['edit']); + } + + if ($quoi['plugin']) { + chargeur_activer_plugin($quoi['plugin']); + } + + spip_log('charger_decompresser OK pour paquet: ' . $quoi['zip']); + + $sub = ',^'.preg_quote($quoi['remove'], ',') . '/,'; + $size = $compressed_size = 0; + foreach ($list as $a => $f) { + $size += $f['size']; + $compressed_size += $f['compressed_size']; + $list[$a] = preg_replace($sub,'',$f['filename']); + } + + return array( + 'files' => $list, + 'size' => $size, + 'compressed_size' => $compressed_size, + 'dirname' => preg_replace(',/.*,', '', $list[0]) + ); +} + +// pas de fichiers caches et preg_files() les ignore (*sigh*) +function chargeur_montre_tout($quoi) +{ + # echo($quoi['dest']); + if (!($d = @opendir($quoi['dest']))) { + return; + } + while (($f = readdir($d)) !== false) { + if ($f == '.' || $f == '..' || $f[0] != '.') { + continue; + } + rename($quoi['dest'] . '/' . $f, $quoi['dest'] . '/'. substr($f, 1)); + } +} + +// renommer des morceaux +function chargeur_edit($dir, $edit) +{ + if (!($d = @opendir($dir))) { + return; + } + while (($f = readdir($d)) !== false) { + if ($f == '.' || $f == '..') { + continue; + } + if (is_dir($f = $dir . '/' . $f)) { + chargeur_edit($f, $edit); + } + $contenu = file_get_contents($f); + if (($change = preg_replace( + array_keys($edit), array_values($edit), $contenu)) == $contenu) { + continue; + } + $fw = fopen($f, 'w'); + fwrite($fw, $change); + fclose($fw); + } +} + +// renommer des morceaux +function chargeur_rename($quoi) +{ +/* + preg_files() est deficiante pour les fichiers caches, ca aurait pu etre bien pourtant ... +*/ + spip_log($quoi); + foreach ($quoi['rename'] as $old => $new) { + !is_writable($file = $quoi['dest'] . '/' . $old) || + rename($file, $quoi['dest'] . '/'. $new); + } +} + +// juste activer le plugin du repertoire $plugin +function chargeur_activer_plugin($plugin) +{ + spip_log('charger_decompresser activer plugin: ' . $plugin); + include_spip('inc/plugin'); + ecrire_plugin_actifs(array($plugin), false, 'ajoute'); + ecrire_metas(); +} + + +function liste_fichiers_pclzip($status) { + $list = $status['files']; + $ret = '<b>'._L((count($list)-1)." fichiers (" + .taille_en_octets($status['size']).') installés dans '._DIR_PLUGINS_AUTO.$list[0]).'</b>'; + + $l .= "<ul style='font-size:x-small;'>\n"; + foreach ($list as $f) { + if (basename($f) == 'svn.revision') + lire_fichier(_DIR_PLUGINS_AUTO.$f,$svn); + if ($joli = preg_replace(',^(.*/)([^/]+/?)$,', '<span style="visibility:hidden">\1</span>\2', + substr($f, strlen($list[0])))) + $l .= "<li>".$joli."</li>\n"; + } + $l .= "</ul>\n"; + + include_spip('inc/filtres'); + if (preg_match(',<revision>([^<]+)<,', $svn, $t)) + $rev = '<div>revision '.$t[1].'</div>'; + if (preg_match(',<commit>([^<]+),', $svn, $t)) + $date = '<div>' . affdate($t[1]) .'</div>'; + + return $ret . $rev . $date . $l; +} + +?> diff --git a/ecrire/inc/commencer_page.php b/ecrire/inc/commencer_page.php index 03ca574fd0..48b5f3519f 100644 --- a/ecrire/inc/commencer_page.php +++ b/ecrire/inc/commencer_page.php @@ -202,18 +202,19 @@ function avertissement_messagerie() { // http://doc.spip.org/@alertes_auteur function alertes_auteur() { - if (autoriser('detruire') - AND ( - @$GLOBALS['meta']['message_crash_tables'] - OR false // autres alertes administrateur - )) { - $alertes = array(); - - if (@$GLOBALS['meta']['message_crash_tables']) { - include_spip('inc/maintenance'); - if ($msg = message_crash_tables()) - $alertes[] = $msg; - } + $alertes = array(); + + if (isset($GLOBALS['meta']['message_crash_tables']) + AND autoriser('detruire')) { + include_spip('inc/maintenance'); + if ($msg = message_crash_tables()) + $alertes[] = $msg; + } + + if (isset($GLOBALS['meta']['plugin_erreur_activation']) + AND autoriser('configurer', 'plugins')) { + $alertes[] = $GLOBALS['meta']['plugin_erreur_activation']; + effacer_meta('plugin_erreur_activation'); // pas normal que ce soit ici } $alertes[] = avertissement_messagerie(); diff --git a/ecrire/inc/plugin.php b/ecrire/inc/plugin.php index c2528f4fd9..5fee4d5ca6 100644 --- a/ecrire/inc/plugin.php +++ b/ecrire/inc/plugin.php @@ -57,6 +57,7 @@ function plugin_version_compatible($intervalle,$version){ function liste_plugin_valides($liste_plug,&$infos, $force = false){ $liste = array(); $infos = array(); + foreach($liste_plug as $plug) $infos[$plug] = plugin_get_infos($plug,$force); @@ -101,7 +102,9 @@ function liste_plugin_valides($liste_plug,&$infos, $force = false){ } } } - if (count($liste_plug)){ + if (count($liste_plug)) { + include_spip('inc/lang'); + utiliser_langue_visiteur(); $erreurs = ""; foreach($liste_plug as $plug){ $necessite = ""; @@ -128,7 +131,8 @@ function liste_plugin_valides($liste_plug,&$infos, $force = false){ array('plugin' => $plug) )."</li>"; } - ecrire_meta('plugin_erreur_activation',"<ul>$erreurs</ul>"); + ecrire_meta('plugin_erreur_activation', + "<ul>$erreurs</ul>$necessite"); } } return $liste; @@ -740,5 +744,4 @@ function plugin_propre($texte) { return $texte; } - ?> -- GitLab