function plugins_afficher_plugin_dist($url_page, $plug_file, $checked, $actif, $expose = false, $class_li = "item", $dir_plugins = _DIR_PLUGINS) { static $id_input = 0; static $versions = array(); $force_reload = _request('var_mode') == 'recalcul'; $get_infos = charger_fonction('get_infos', 'plugins'); $info = $get_infos($plug_file, $force_reload, $dir_plugins); $prefix = $info['prefix']; $cfg = ""; $checkable = $dir_plugins !== _DIR_PLUGINS_DIST; $nom = plugin_nom($info, $dir_plugins, $plug_file); if (!plugin_version_compatible($info['compatibilite'], $GLOBALS['spip_version_branche'], 'spip')) { $info['slogan'] = _T('plugin_info_non_compatible_spip'); $erreur = http_img_pack("plugin-dis-32.png", _T('plugin_info_non_compatible_spip'), " class='picto_err'", _T('plugin_info_non_compatible_spip')); $class_li .= " disabled"; $checkable = false; } elseif (isset($info['erreur'])) { $class_li .= " error"; $erreur = http_img_pack("plugin-err-32.png", _T('plugin_info_erreur_xml'), " class='picto_err'", _T('plugin_info_erreur_xml')) . "<div class='erreur'>" . join('<br >', $info['erreur']) . "</div>"; $checkable = false; } elseif (isset($GLOBALS['erreurs_activation_raw'][$dir_plugins . $plug_file])) { $class_li .= " error"; $erreur = http_img_pack("plugin-err-32.png", _T('plugin_impossible_activer', array('plugin' => $nom)), " class='picto_err'", _T('plugin_impossible_activer', array('plugin' => $nom))) . "<div class='erreur'>" . implode("<br />", $GLOBALS['erreurs_activation_raw'][$dir_plugins . $plug_file]) . "</div>"; } else { $cfg = $actif ? plugin_bouton_config($plug_file, $info, $dir_plugins) : ""; } // numerotons les occurrences d'un meme prefix $versions[$prefix] = $id = isset($versions[$prefix]) ? $versions[$prefix] + 1 : ''; $class_li .= ($actif ? " actif" : "") . ($expose ? " on" : ""); return "<li id='{$prefix}{$id}' class='{$class_li}'>" . ((!$checkable and !$checked) ? '' : plugin_checkbox(++$id_input, $plug_file, $checked)) . plugin_resume($info, $dir_plugins, $plug_file, $url_page) . $cfg . $erreur . (($dir_plugins !== _DIR_PLUGINS_DIST and plugin_est_installe($plug_file)) ? plugin_desintalle($plug_file, $nom) : '') . "<div class='details'>" . (!$expose ? '' : affiche_bloc_plugin($plug_file, $info)) . "</div>" . "</li>"; }
/** * lecture d'un texte conforme a la DTD paquet.dtd * et conversion en tableau PHP identique a celui fourni par plugin.xml * manque la description * * @param $desc * @param string $plug * @param string $dir_plugins * @return array */ function plugins_infos_paquet($desc, $plug = '', $dir_plugins = _DIR_PLUGINS) { static $process = array('debut' => 'paquet_debutElement', 'fin' => 'paquet_finElement', 'text' => 'paquet_textElement'); $valider_xml = charger_fonction('valider', 'xml'); $vxml = $valider_xml($desc, false, $process, 'paquet.dtd', "utf-8"); if (!$vxml->err) { // On veut toutes les variantes selon la version de SPIP if (!$plug) { return $vxml->versions; } // compatibilite avec l'existant: $tree = $vxml->versions['0']; // l'arbre renvoie parfois un tag vide... etrange. Pas la peine de garder ca. if (isset($tree['']) and !strlen($tree[''])) { unset($tree['']); } $tree['slogan'] = $tree['prefix'] . "_slogan"; $tree['description'] = $tree['prefix'] . "_description"; paquet_readable_files($tree, "{$dir_plugins}{$plug}/"); if (!$tree['chemin']) { $tree['chemin'] = array(array('path' => '')); } // initialiser par defaut // On verifie qu'il existe des balises spip qu'il faudrait rajouter dans // la structure d'infos du paquet en fonction de la version spip courante if (count($vxml->versions) > 1) { $vspip = $GLOBALS['spip_version_branche']; foreach ($vxml->versions as $_compatibilite => $_version) { if ($_version['balise'] == 'spip' and plugin_version_compatible($_compatibilite, $vspip, 'spip')) { // on merge les sous-balises de la balise spip compatible avec celles de la // balise paquet foreach ($_version as $_index => $_balise) { if ($_index and $_index != 'balise') { $tree[$_index] = array_merge($tree[$_index], $_balise); } } } } } return $tree; } // Prendre les messages d'erreur sans les numeros de lignes $msg = array_map('array_shift', $vxml->err); // Construire le lien renvoyant sur l'application du validateur XML $h = $GLOBALS['meta']['adresse_site'] . '/' . substr("{$dir_plugins}{$plug}/", strlen(_DIR_RACINE)) . 'paquet.xml'; $h = generer_url_ecrire('valider_xml', "var_url={$h}"); $t = _T('plugins_erreur', array('plugins' => $plug)); array_unshift($msg, "<a href='{$h}'>{$t}</a>"); return array('erreur' => $msg); }
/** * Teste la compatibilité d'un intervalle de compatibilité avec une version * donnée de SPIP * * @uses plugin_version_compatible() * @param string $intervalle * Intervalle de compatibilité, tel que [2.1;3.0] * @param string $version_spip * Version de SPIP, tel que 3.0.4 (par défaut la version de SPIP en cours) * @return bool * true si l'intervalle est compatible, false sinon */ function svp_verifier_compatibilite_spip($intervalle, $version_spip = '') { if (!$version_spip) { $version_spip = $GLOBALS['spip_version_branche'] . "." . $GLOBALS['spip_version_code']; } return plugin_version_compatible($intervalle, $version_spip, 'spip'); }
/** * Pour une description de paquet donnée, vérifie sa validité. * * Teste la version de SPIP, les librairies nécessitées, ses dépendances * (et tente de les trouver et ajouter si elles ne sont pas là) * * Lorsqu'une dépendance est activée, on entre en récursion * dans cette fonction avec la description de la dépendance * * @param array $info * Description du paquet * @param int $prof * Profondeur de récursion * @return bool * false si erreur (dépendance non résolue, incompatibilité...), true sinon **/ public function verifier_dependances_plugin($info, $prof = 0) { $this->log("- [{$prof}] verifier dependances " . $info['p']); $id = $info['i']; $err = false; // variable receptionnant parfois des erreurs $cache = array(); // cache des actions realisees dans ce tour // 1 // tester la version de SPIP de notre paquet // si on ne valide pas, on retourne une erreur ! // mais normalement, on ne devrait vraiment pas pouvoir tomber sur ce cas if (!svp_verifier_compatibilite_spip($info['compatibilite_spip'])) { $this->invalider($info); $this->erreur($id, _T('svp:message_incompatibilite_spip', array('plugin' => $info['n']))); return false; } // 2 // ajouter les librairies necessaires a notre paquet if (is_array($info['dl']) and count($info['dl'])) { foreach ($info['dl'] as $l) { // $l = array('nom' => 'x', 'lien' => 'url') $lib = $l['nom']; $this->log("## Necessite la librairie : " . $lib); // on verifie sa presence OU le fait qu'on pourra la telecharger if ($lib and !$this->est_presente_lib($lib)) { // peut on ecrire ? if (!is_writable(_DIR_LIB)) { $this->invalider($info); $this->erreur($id, _T('svp:message_erreur_ecriture_lib', array('plugin' => $info['n'], 'lib_url' => $l['lien'], 'lib' => $lib))); $err = true; } else { $this->change(array('i' => md5(serialize($l)), 'p' => $lib, 'n' => $lib, 'v' => $l['lien']), 'getlib'); $this->log("- La librairie {$lib} sera a télécharger"); } } } if ($err) { return false; } } // 3 // Trouver les dependences aux necessites // et les activer au besoin if (is_array($info['dn']) and count($info['dn'])) { foreach ($info['dn'] as $n) { $p = $n['nom']; $v = $n['compatibilite']; if ($p == 'SPIP') { // c'est pas la que ça se fait ! // ca ne devrait plus apparaitre comme dependence a un plugin. } elseif (array_key_exists($p, $this->procure) and plugin_version_compatible($v, $this->procure[$p], 'spip')) { // rien a faire... $this->log("-- est procure par le core ({$p})"); } else { $this->log("-- verifier : {$p}"); // nous sommes face a une dependance de plugin // on regarde s'il est present et a la bonne version // sinon on le cherche et on l'ajoute if ($ninfo = $this->sera_actif($p) and !($err = $this->en_erreur($ninfo['i'])) and plugin_version_compatible($v, $ninfo['v'])) { // il est deja actif ou a activer, et tout est ok $this->log('-- dep OK pour ' . $info['p'] . ' : ' . $p); } else { // absent ou erreur ou pas compatible $etat = $err ? 'erreur' : ($ninfo ? 'conflit' : 'absent'); // conflit signifie qu'il existe le prefixe actif, mais pas a la version demandee $this->log("Dependance " . $p . " a resoudre ! ({$etat})"); switch ($etat) { // commencons par le plus simple : // en cas d'absence, on cherche ou est ce plugin ! case 'absent': // on choisit par defaut le meilleur etat de plugin. // de preference dans les plugins locaux, sinon en distant. if (!$this->sera_off($p) and $new = $this->chercher_plugin_compatible($p, $v) and $this->verifier_dependances_plugin($new, ++$prof)) { // si le plugin existe localement et possede maj_version, // c'est que c'est peut etre une mise a jour + activation a faire // si le plugin // nouveau est local => non // nouveau est distant => oui peut etre $cache[] = $new; $i = array(); if (!$new['local']) { $i = $this->infos_courtes(array('pl.prefixe=' . sql_quote($new['p']), 'pa.maj_version=' . sql_quote($new['v'])), true); } if ($i and isset($i['p'][$new['p']]) and count($i['p'][$new['p']])) { // c'est une mise a jour $vieux = $i['p'][$new['p']][0]; $this->change($vieux, 'upon'); $this->log("-- update+active : {$p}"); } else { // tout nouveau tout beau $this->change($new, $new['local'] ? 'on' : 'geton'); if ($new['local']) { $this->log("-- nouveau present : {$p}"); } else { $this->log("-- nouveau distant : {$p}"); } } $this->add($new); } else { $this->log("-- !erreur : {$p}"); // on ne trouve pas la dependance ! $this->invalider($info); $this->erreur($id, $v ? _T('svp:message_dependance_plugin_version', array('plugin' => $info['n'], 'dependance' => $p, 'version' => $v)) : _T('svp:message_dependance_plugin', array('plugin' => $info['n'], 'dependance' => $p))); } unset($new, $vieux); break; case 'erreur': break; // present, mais conflit de version // de deux choses l'une : // soit on trouve un paquet meilleur... // soit pas :) // present, mais conflit de version // de deux choses l'une : // soit on trouve un paquet meilleur... // soit pas :) case 'conflit': $this->log(" conflit -> demande {$v}, present : " . $ninfo['v']); if (!$this->sera_off($p) and $new = $this->chercher_plugin_compatible($p, $v) and $this->verifier_dependances_plugin($new, ++$prof)) { // on connait le nouveau... $cache[] = $new; $this->remove($ninfo); $this->add($new); $this->change($ninfo, 'up'); $this->log("-- update : {$p}"); } else { $this->log("-- !erreur : {$p}"); // on ne trouve pas la dependance ! $this->invalider($info); $this->erreur($id, $v ? _T('svp:message_dependance_plugin_version', array('plugin' => $info['n'], 'dependance' => $p, 'version' => $v)) : _T('svp:message_dependance_plugin', array('plugin' => $info['n'], 'dependance' => $p))); } break; } } } if ($this->sera_invalide($info['p'])) { break; } } unset($n, $v, $p, $ninfo, $present, $conflit, $erreur, $err); // si le plugin est devenu invalide... // on invalide toutes les actions qu'on vient de faire ! if ($this->sera_invalide($info['p'])) { $this->log("> Purge du cache"); foreach ($cache as $i) { $this->invalider($i); } return false; } } return true; }
function plugins_verifie_conformite_dist($plug, &$arbre, $dir_plugins = _DIR_PLUGINS) { static $etats = array('dev', 'experimental', 'test', 'stable'); $matches = array(); $silence = false; $p = null; // chercher la declaration <plugin spip='...'> a prendre pour cette version de SPIP if ($n = spip_xml_match_nodes(",^plugin(\\s|\$),", $arbre, $matches)) { // version de SPIP $vspip = $GLOBALS['spip_version_branche']; foreach ($matches as $tag => $sous) { list($tagname, $atts) = spip_xml_decompose_tag($tag); if ($tagname == 'plugin' and is_array($sous)) { // On rajoute la condition sur $n : // -- en effet si $n==1 on a pas plus a choisir la balise que l'on ait // un attribut spip ou pas. Cela permet de traiter tous les cas mono-balise // de la meme facon. if (!isset($atts['spip']) or $n == 1 or plugin_version_compatible($atts['spip'], $vspip, 'spip')) { // on prend la derniere declaration avec ce nom $p = end($sous); $compat_spip = isset($atts['spip']) ? $atts['spip'] : ''; } } } } if (is_null($p)) { $arbre = array('erreur' => array(_T('erreur_plugin_tag_plugin_absent') . " : {$plug}")); $silence = true; } else { $arbre = $p; } if (!is_array($arbre)) { $arbre = array(); } // verification de la conformite du plugin avec quelques // precautions elementaires if (!isset($arbre['nom'])) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_nom_manquant'); } $arbre['nom'] = array(""); } if (!isset($arbre['version'])) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_version_manquant'); } $arbre['version'] = array(""); } if (!isset($arbre['prefix'])) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_prefix_manquant'); } $arbre['prefix'] = array(""); } else { $prefix = trim(end($arbre['prefix'])); if (strtoupper($prefix) == 'SPIP' and $plug != "./") { $arbre['erreur'][] = _T('erreur_plugin_prefix_interdit'); } if (isset($arbre['etat'])) { $etat = trim(end($arbre['etat'])); if (!in_array($etat, $etats)) { $arbre['erreur'][] = _T('erreur_plugin_etat_inconnu') . " : '{$etat}'"; } } if (isset($arbre['options'])) { foreach ($arbre['options'] as $optfile) { $optfile = trim($optfile); if (!@is_readable($dir_plugins . "{$plug}/{$optfile}")) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_fichier_absent') . " : {$optfile}"; } } } } if (isset($arbre['fonctions'])) { foreach ($arbre['fonctions'] as $optfile) { $optfile = trim($optfile); if (!@is_readable($dir_plugins . "{$plug}/{$optfile}")) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_fichier_absent') . " : {$optfile}"; } } } } $fonctions = array(); if (isset($arbre['fonctions'])) { $fonctions = $arbre['fonctions']; } $liste_methodes_reservees = array('__construct', '__destruct', 'plugin', 'install', 'uninstall', strtolower($prefix)); $extraire_pipelines = charger_fonction("extraire_pipelines", "plugins"); $arbre['pipeline'] = $extraire_pipelines($arbre); foreach ($arbre['pipeline'] as $pipe) { if (!isset($pipe['nom'])) { if (!$silence) { $arbre['erreur'][] = _T("erreur_plugin_nom_pipeline_non_defini"); } } if (isset($pipe['action'])) { $action = $pipe['action']; } else { $action = $pipe['nom']; } // verif que la methode a un nom autorise if (in_array(strtolower($action), $liste_methodes_reservees)) { if (!$silence) { $arbre['erreur'][] = _T("erreur_plugin_nom_fonction_interdit") . " : {$action}"; } } if (isset($pipe['inclure'])) { $inclure = $dir_plugins . "{$plug}/" . $pipe['inclure']; if (!@is_readable($inclure)) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_fichier_absent') . " : {$inclure}"; } } } } $necessite = array(); $spip_trouve = false; if (spip_xml_match_nodes(',^necessite,', $arbre, $needs)) { foreach (array_keys($needs) as $tag) { list($tag, $att) = spip_xml_decompose_tag($tag); if (!isset($att['id'])) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_attribut_balise_manquant', array('attribut' => 'id', 'balise' => $att)); } } else { $necessite[] = $att; } if (strtolower($att['id']) == 'spip') { $spip_trouve = true; } } } if ($compat_spip and !$spip_trouve) { $necessite[] = array('id' => 'spip', 'version' => $compat_spip); } $arbre['necessite'] = $necessite; $utilise = array(); if (spip_xml_match_nodes(',^utilise,', $arbre, $uses)) { foreach (array_keys($uses) as $tag) { list($tag, $att) = spip_xml_decompose_tag($tag); if (!isset($att['id'])) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_attribut_balise_manquant', array('attribut' => 'id', 'balise' => $att)); } } else { $utilise[] = $att; } } } $arbre['utilise'] = $utilise; $procure = array(); if (spip_xml_match_nodes(',^procure,', $arbre, $uses)) { foreach (array_keys($uses) as $tag) { list($tag, $att) = spip_xml_decompose_tag($tag); $procure[] = $att; } } $arbre['procure'] = $procure; $path = array(); if (spip_xml_match_nodes(',^chemin,', $arbre, $paths)) { foreach (array_keys($paths) as $tag) { list($tag, $att) = spip_xml_decompose_tag($tag); $att['path'] = $att['dir']; // ancienne syntaxe $path[] = $att; } } else { $path = array(array('dir' => '')); } // initialiser par defaut $arbre['path'] = $path; // exposer les noisettes if (isset($arbre['noisette'])) { foreach ($arbre['noisette'] as $k => $nut) { $nut = preg_replace(',[.]html$,uims', '', trim($nut)); $arbre['noisette'][$k] = $nut; if (!@is_readable($dir_plugins . "{$plug}/{$nut}.html")) { if (!$silence) { $arbre['erreur'][] = _T('erreur_plugin_fichier_absent') . " : {$nut}"; } } } } $traduire = array(); if (spip_xml_match_nodes(',^traduire,', $arbre, $trads)) { foreach (array_keys($trads) as $tag) { list($tag, $att) = spip_xml_decompose_tag($tag); $traduire[] = $att; } } $arbre['traduire'] = $traduire; } }
/** * Met à jour les informations d'obsolescence des paquets locaux. * * L'obsolescence indique qu'un paquet est plus ancien (de version ou état * moins avancé) qu'un autre également présent localement. * * @param array $ids_plugin * Liste d'identifiants de plugins * En cas d'absence, passera sur tous les paquets locaux **/ function svp_corriger_obsolete_paquets($ids_plugin = array()) { // on minimise au maximum le nombre de requetes. // 1 pour lister les paquets // 1 pour mettre à jour les obsoletes à oui // 1 pour mettre à jour les obsoletes à non $where = array('pa.id_plugin = pl.id_plugin', 'id_depot=' . sql_quote(0)); if ($ids_plugin) { $where[] = sql_in('pl.id_plugin', $ids_plugin); } // comme l'on a de nouveaux paquets locaux... // certains sont peut etre devenus obsoletes // parmis tous les plugins locaux presents // concernes par les memes prefixes que les plugins ajoutes. $obsoletes = array(); $changements = array(); $paquets = sql_allfetsel(array('pa.id_paquet', 'pl.prefixe', 'pa.version', 'pa.etatnum', 'pa.obsolete', 'pa.compatibilite_spip'), array('spip_paquets AS pa', 'spip_plugins AS pl'), $where); // L'obsolescence doit tenir compte de la compatibilité avec notre version de SPIP en cours foreach ($paquets as $c => $p) { $paquets[$c]['compatible'] = plugin_version_compatible($p['compatibilite_spip'], $GLOBALS['spip_version_branche'], 'spip'); } foreach ($paquets as $c => $p) { $obsoletes[$p['prefixe']][] = $c; // si 2 paquet locaux ont le meme prefixe, // sont compatibles avec notre SPIP, // mais pas la meme version, // l'un est obsolete : la version la plus ancienne // Si version et etat sont egaux, on ne decide pas d'obsolescence. if (count($obsoletes[$p['prefixe']]) > 1) { foreach ($obsoletes[$p['prefixe']] as $cle) { if ($cle == $c) { continue; } if (!$paquets[$c]['compatible']) { continue; } // je suis plus petit qu'un autre if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '<')) { if ($paquets[$c]['etatnum'] <= $paquets[$cle]['etatnum']) { if ($paquets[$c]['obsolete'] != 'oui') { $paquets[$c]['obsolete'] = 'oui'; $changements[$c] = true; } } } else { // je suis strictement plus grand qu'un autre... if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '>')) { // si mon etat est meilleur, rendre obsolete les autres if ($paquets[$c]['etatnum'] >= $paquets[$cle]['etatnum']) { if ($paquets[$cle]['obsolete'] != 'oui') { $paquets[$cle]['obsolete'] = 'oui'; $changements[$cle] = true; } } } elseif ($paquets[$c]['etatnum'] > $paquets[$cle]['etatnum']) { if ($paquets[$cle]['obsolete'] != 'oui') { $paquets[$cle]['obsolete'] = 'oui'; $changements[$cle] = true; } } } } } else { if ($paquets[$c]['obsolete'] != 'non') { $paquets[$c]['obsolete'] = 'non'; $changements[$c] = true; } } } if (count($changements)) { $oui = $non = array(); foreach ($changements as $c => $null) { if ($paquets[$c]['obsolete'] == 'oui') { $oui[] = $paquets[$c]['id_paquet']; } else { $non[] = $paquets[$c]['id_paquet']; } } if ($oui) { sql_updateq('spip_paquets', array('obsolete' => 'oui'), sql_in('id_paquet', $oui)); } if ($non) { sql_updateq('spip_paquets', array('obsolete' => 'non'), sql_in('id_paquet', $non)); } } }
function plugins_precompile_chemin($plugin_valides, $ordre) { $chemins = array(); $contenu = ""; foreach ($ordre as $p => $info) { // $ordre peur contenir des plugins en attente et non valides pour ce hit if (isset($plugin_valides[$p])) { $dir_type = $plugin_valides[$p]['dir_type']; $plug = $plugin_valides[$p]['dir']; // definir le plugin, donc le path avant l'include du fichier options // permet de faire des include_spip pour attraper un inc_ du plugin $dir = $dir_type . ".'" . $plug . "/'"; $prefix = strtoupper(preg_replace(',\\W,', '_', $info['prefix'])); if ($prefix !== "SPIP") { $contenu .= "define('_DIR_PLUGIN_{$prefix}',{$dir});\n"; foreach ($info['chemin'] as $chemin) { if (!isset($chemin['version']) or plugin_version_compatible($chemin['version'], $GLOBALS['spip_version_branche'], 'spip')) { $dir = $chemin['path']; if (strlen($dir) and $dir[0] == "/") { $dir = substr($dir, 1); } if (strlen($dir) and $dir == "./") { $dir = ''; } if (strlen($dir)) { $dir = rtrim($dir, '/') . '/'; } if (!isset($chemin['type']) or $chemin['type'] == 'public') { $chemins['public'][] = "_DIR_PLUGIN_{$prefix}" . (strlen($dir) ? ".'{$dir}'" : ""); } if (!isset($chemin['type']) or $chemin['type'] == 'prive') { $chemins['prive'][] = "_DIR_PLUGIN_{$prefix}" . (strlen($dir) ? ".'{$dir}'" : ""); } } } } } } if (count($chemins)) { $contenu .= "if (_DIR_RESTREINT) _chemin(implode(':',array(" . implode(',', array_reverse($chemins['public'])) . ")));\n" . "else _chemin(implode(':',array(" . implode(',', array_reverse($chemins['prive'])) . ")));\n"; } ecrire_fichier_php(_CACHE_PLUGINS_PATH, $contenu); }
/** * Phrase la liste des balises <archive> * * Chaque bloc XML est constitue de 3 sous-blocs principaux : * - <zip> : contient les balises d'information sur le zip (obligatoire) * - <traductions> : contient la compilation des informations de traduction (facultatif) * - <plugin> ou <paquet> suivant la DTD : le contenu du fichier plugin.xml ou paquet.xml (facultatif) * * @param array $archives * Tableau de la liste des archives trouvées dans la description d'un dépot * @param array $md5_cache * Tableau des descriptions d'archives déjà connues : on supprime * à la fin celles qui ne font plus parties du dépot. * @return array * Tableau décrivant chaque archive, avec en index l'url de l'archive. * Tableau (url => Tableau de description de l'archive) */ function svp_phraser_archives($archives, &$md5_cache = array()) { include_spip('inc/plugin'); $seen = array(); $paquets = array(); $version_spip = $GLOBALS['spip_version_branche'] . "." . $GLOBALS['spip_version_code']; // On verifie qu'il existe au moins une archive if (!$archives) { return $paquets; } // On phrase chacune des archives // Seul le bloc <zip> est obligatoire foreach ($archives as $_cle => $_archive) { // quand version spip ou mode runtime changent, // il faut mettre le xml a jour pour voir les plugins compatibles ou non $md5 = md5($_archive . ":{$version_spip}:" . _SVP_MODE_RUNTIME); if (isset($md5_cache[$md5])) { if (is_array($p = $md5_cache[$md5])) { $paquets[$p['file']] = $p; } // ce paquet est connu $seen[] = $md5; } elseif (preg_match(_SVP_REGEXP_BALISE_ZIP, $_archive, $matches)) { // Extraction de la balise <zip> $zip = svp_phraser_zip($matches[1]); if ($zip) { // Extraction de la balise traductions $traductions = array(); if (preg_match(_SVP_REGEXP_BALISE_TRADUCTIONS, $_archive, $matches)) { $traductions = svp_phraser_traductions($matches[1]); } // La balise <archive> peut posseder un attribut qui precise la DTD utilisee pour les plugins (plugin ou paquet) // Sinon, c'est la DTD plugin qui est utilisee list($tag, $attributs) = spip_xml_decompose_tag($_archive); // -- On stocke la DTD d'extraction des infos du plugin $dtd = (isset($attributs['dtd']) and $attributs['dtd']) ? $attributs['dtd'] : _SVP_DTD_PLUGIN; // Extraction *des balises* plugin ou *de la balise* paquet suivant la DTD et la version SPIP // -- DTD : si on utilise plugin.xml on extrait la balise <plugin> sinon la balise <paquet> $xml = svp_phraser_plugin($dtd, $_archive); // Si on est en mode runtime, on est seulement interesse par les plugins compatibles avec // la version courant de SPIP. On ne stocke donc pas les autres plugins. // Si on est pas en mode runtime on prend tout ! if (!_SVP_MODE_RUNTIME or _SVP_MODE_RUNTIME and isset($xml['compatibilite']) and plugin_version_compatible($xml['compatibilite'], $version_spip, 'spip')) { $paquets[$zip['file']] = $zip; $paquets[$zip['file']]['traductions'] = $traductions; $paquets[$zip['file']]['dtd'] = $dtd; $paquets[$zip['file']]['plugin'] = $xml; $paquets[$zip['file']]['md5'] = $md5; $md5_cache[$md5] = $paquets[$zip['file']]; $seen[] = $md5; } else { $md5_cache[$md5] = $zip['file']; $seen[] = $md5; } } } } // supprimer du cache les zip qui ne sont pas dans le nouveau $archives $oldies = array_diff(array_keys($md5_cache), $seen); foreach ($oldies as $old_md5) { unset($md5_cache[$old_md5]); } return $paquets; }
function plugins_verifie_conformite_dist($plug, &$arbre, $dir_plugins = _DIR_PLUGINS){ static $etats = array('dev','experimental','test', 'stable'); $matches = array(); $silence = false; $p = null; // chercher la declaration <plugin spip='...'> a prendre pour cette version de SPIP if ($n = spip_xml_match_nodes(",^plugin(\s|$),", $arbre, $matches)){ // version de SPIP $vspip = $GLOBALS['spip_version_branche']; foreach($matches as $tag=>$sous){ list($tagname,$atts) = spip_xml_decompose_tag($tag); if ($tagname=='plugin' AND is_array($sous)){ if (!isset($atts['spip']) OR plugin_version_compatible($atts['spip'],$vspip)) { // on prend la derniere declaration avec ce nom $p = end($sous); $compat_spip = isset($atts['spip']) ? $atts['spip'] : ''; } } } } if (is_null($p)){ $arbre = array('erreur' => array(_T('erreur_plugin_tag_plugin_absent')." : $plug")); $silence = true; } else $arbre = $p; if (!is_array($arbre)) $arbre = array(); // verification de la conformite du plugin avec quelques // precautions elementaires if (!isset($arbre['nom'])){ if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_nom_manquant'); $arbre['nom'] = array(""); } if (!isset($arbre['version'])){ if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_version_manquant'); $arbre['version'] = array(""); } if (!isset($arbre['prefix'])){ if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_prefix_manquant'); $arbre['prefix'] = array(""); } else{ $prefix = trim(end($arbre['prefix'])); if (strtoupper($prefix)=='SPIP'){ $arbre['erreur'][] = _T('erreur_plugin_prefix_interdit'); } if (isset($arbre['etat'])){ $etat = trim(end($arbre['etat'])); if (!in_array($etat, $etats)) $arbre['erreur'][] = _T('erreur_plugin_etat_inconnu')." : '$etat'"; } if (isset($arbre['options'])){ foreach($arbre['options'] as $optfile){ $optfile = trim($optfile); if (!@is_readable($dir_plugins."$plug/$optfile")) if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_fichier_absent')." : $optfile"; } } if (isset($arbre['fonctions'])){ foreach($arbre['fonctions'] as $optfile){ $optfile = trim($optfile); if (!@is_readable($dir_plugins."$plug/$optfile")) if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_fichier_absent')." : $optfile"; } } $fonctions = array(); if (isset($arbre['fonctions'])) $fonctions = $arbre['fonctions']; $liste_methodes_reservees = array('__construct','__destruct','plugin','install','uninstall',strtolower($prefix)); $extraire_pipelines = charger_fonction("extraire_pipelines","plugins"); $arbre['pipeline'] = $extraire_pipelines($arbre); foreach($arbre['pipeline'] as $pipe){ if (!isset($pipe['nom'])) if (!$silence) $arbre['erreur'][] = _T("erreur_plugin_nom_pipeline_non_defini"); if (isset($pipe['action'])) $action = $pipe['action']; else $action = $pipe['nom']; // verif que la methode a un nom autorise if (in_array(strtolower($action),$liste_methodes_reservees)){ if (!$silence) $arbre['erreur'][] = _T("erreur_plugin_nom_fonction_interdit")." : $action"; } if (isset($pipe['inclure'])) { $inclure = $dir_plugins."$plug/".$pipe['inclure']; if (!@is_readable($inclure)) if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_fichier_absent')." : $inclure"; } } $necessite = array(); $spip_trouve = false; if (spip_xml_match_nodes(',^necessite,',$arbre,$needs)){ foreach(array_keys($needs) as $tag){ list($tag,$att) = spip_xml_decompose_tag($tag); $necessite[] = $att; if (strtolower($att['id']) == 'spip') $spip_trouve = true; } } if ($compat_spip AND !$spip_trouve) $necessite[] = array('id' => 'spip', 'version' => $compat_spip); $arbre['necessite'] = $necessite; $utilise = array(); if (spip_xml_match_nodes(',^utilise,',$arbre,$uses)){ foreach(array_keys($uses) as $tag){ list($tag,$att) = spip_xml_decompose_tag($tag); $utilise[] = $att; } } $arbre['utilise'] = $utilise; $path = array(); if (spip_xml_match_nodes(',^chemin,',$arbre,$paths)){ foreach(array_keys($paths) as $tag){ list($tag,$att) = spip_xml_decompose_tag($tag); $path[] = $att; } } else $path = array(array('dir'=>'')); // initialiser par defaut $arbre['path'] = $path; // exposer les noisettes if (isset($arbre['noisette'])){ foreach($arbre['noisette'] as $k=>$nut){ $nut = preg_replace(',[.]html$,uims','',trim($nut)); $arbre['noisette'][$k] = $nut; if (!@is_readable($dir_plugins."$plug/$nut.html")) if (!$silence) $arbre['erreur'][] = _T('erreur_plugin_fichier_absent')." : $nut"; } } $traduire = array(); if (spip_xml_match_nodes(',^traduire,',$arbre,$trads)){ foreach(array_keys($trads) as $tag){ list($tag,$att) = spip_xml_decompose_tag($tag); $traduire[] = $att; } } $arbre['traduire'] = $traduire; } }
function ecrire_plugin_actifs($plugin,$pipe_recherche=false,$operation='raz') { static $liste_pipe_manquants=array(); // creer le repertoire cache/ si necessaire ! (installation notamment) sous_repertoire(_DIR_CACHE, '', false,true); $liste_fichier_verif = array(); if (($pipe_recherche)&&(!in_array($pipe_recherche,$liste_pipe_manquants))) $liste_pipe_manquants[]=$pipe_recherche; if ($operation!='raz'){ $plugin_actifs = liste_chemin_plugin_actifs(); $plugin_liste = liste_plugin_files(); $plugin_valides = array_intersect($plugin_actifs,$plugin_liste); if ($operation=='ajoute') $plugin = array_merge($plugin_valides,$plugin); if ($operation=='enleve') $plugin = array_diff($plugin_valides,$plugin); } // recharger le xml des plugins a activer list($plugin_valides,$ordre,$infos) = liste_plugin_valides($plugin,true); ecrire_meta('plugin',serialize($plugin_valides)); effacer_meta('message_crash_plugins'); // baisser ce flag ! $plugin_header_info = array(); foreach($plugin_valides as $p=>$resume){ $plugin_header_info[]= $p.($resume['version']?"(".$resume['version'].")":""); } ecrire_meta('plugin_header',substr(strtolower(implode(",",$plugin_header_info)),0,900)); $start_file = "<"."?php\nif (defined('_ECRIRE_INC_VERSION')) {\n"; $end_file = "}\n?".">"; if (is_array($infos)){ // construire tableaux de boutons et onglets $liste_boutons = array(); $liste_onglets = array(); foreach($ordre as $p){ $dir_type = $plugin_valides[$p]['dir_type']; $plug = $plugin_valides[$p]['dir']; $info = $infos[$dir_type][$plug]; if (isset($info['bouton'])){ $liste_boutons = array_merge($liste_boutons,$info['bouton']); } if (isset($info['onglet'])){ $liste_onglets = array_merge($liste_onglets,$info['onglet']); } } } // generer les fichier // charger_plugins_options.php // charger_plugins_fonctions.php if (defined('_DIR_PLUGINS_SUPPL')) $dir_plugins_suppl = implode(array_filter(explode(':',_DIR_PLUGINS_SUPPL)),'|'); foreach(array('chemins'=>_CACHE_PLUGINS_PATH,'options'=>_CACHE_PLUGINS_OPT,'fonctions'=>_CACHE_PLUGINS_FCT) as $charge=>$fileconf){ $s = ""; $splugs = ""; $chemins = array(); if (is_array($infos)){ foreach($ordre as $p){ $dir_type = $plugin_valides[$p]['dir_type']; $plug = $plugin_valides[$p]['dir']; $info = $infos[$dir_type][$plug]; if($dir_plugins_suppl && preg_match(',('.$dir_plugins_suppl.'),',$plugin_valides[$p]['dir'])){ //$plugin_valides[$p]['dir_type'] = '_DIR_RACINE'; $dir_type = '_DIR_RACINE'; //if(!test_espace_prive()) $plug = str_replace('../','',$plug); } $root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type); $dir = $dir_type.".'" . $plug ."/'"; // definir le plugin, donc le path avant l'include du fichier options // permet de faire des include_spip pour attraper un inc_ du plugin if ($charge=='chemins'){ $prefix = strtoupper(preg_replace(',\W,','_',$info['prefix'])); $splugs .= "define('_DIR_PLUGIN_$prefix',$dir);\n"; foreach($info['path'] as $chemin){ if (!isset($chemin['version']) OR plugin_version_compatible($chemin['version'],$GLOBALS['spip_version_branche'])){ $dir = $chemin['dir']; if (strlen($dir) AND $dir{0}=="/") $dir = substr($dir,1); if (!isset($chemin['type']) OR $chemin['type']=='public') $chemins['public'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":""); if (!isset($chemin['type']) OR $chemin['type']=='prive') $chemins['prive'][]="_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":""); #$splugs .= "if (".(($chemin['type']=='public')?"":"!")."_DIR_RESTREINT) "; #$splugs .= "_chemin(_DIR_PLUGIN_$prefix".(strlen($dir)?".'$dir'":"").");\n"; } } } // concerne uniquement options et fonctions if (isset($info[$charge])){ foreach($info[$charge] as $file){ // on genere un if file_exists devant chaque include pour pouvoir garder le meme niveau d'erreur general $file = trim($file); if (strlen(constant($dir_type)) && (strpos($plug, constant($dir_type)) === 0)) { $dir = str_replace("'".constant($dir_type), $root_dir_type.".'", "'$plug/'"); } if($root_dir_type == '_ROOT_RACINE'){ $plug = str_replace('../','',$plug); } else $dir = $root_dir_type.".'$plug/'"; $s .= "if (file_exists(\$f=$dir.'".trim($file)."')){ include_once \$f;}\n"; $liste_fichier_verif[] = "$root_dir_type:$plug/".trim($file); } } } } if ($charge=='chemins'){ if (count($chemins)){ $splugs .= "if (_DIR_RESTREINT) _chemin(implode(':',array(".implode(',',array_reverse($chemins['public'])).")));\n"; $splugs .= "else _chemin(implode(':',array(".implode(',',array_reverse($chemins['prive'])).")));\n"; } } if ($charge=='options'){ $s .= "if (!function_exists('boutons_plugins')){function boutons_plugins(){return unserialize('".str_replace("'","\'",serialize($liste_boutons))."');}}\n"; $s .= "if (!function_exists('onglets_plugins')){function onglets_plugins(){return unserialize('".str_replace("'","\'",serialize($liste_onglets))."');}}\n"; } ecrire_fichier($fileconf, $start_file . $splugs . $s . $end_file); } if (is_array($infos)){ // construire tableaux de pipelines et matrices et boutons // $GLOBALS['spip_pipeline'] // $GLOBALS['spip_matrice'] $liste_boutons = array(); foreach($ordre as $p){ $dir_type = $plugin_valides[$p]['dir_type']; $root_dir_type = str_replace('_DIR_','_ROOT_',$dir_type); $plug = $plugin_valides[$p]['dir']; $info = $infos[$dir_type][$plug]; $prefix = ""; $prefix = $info['prefix']."_"; if (isset($info['pipeline']) AND is_array($info['pipeline'])){ foreach($info['pipeline'] as $pipe){ $nom = $pipe['nom']; if (isset($pipe['action'])) $action = $pipe['action']; else $action = $nom; $nomlower = strtolower($nom); if ($nomlower!=$nom AND isset($GLOBALS['spip_pipeline'][$nom]) AND !isset($GLOBALS['spip_pipeline'][$nomlower])){ $GLOBALS['spip_pipeline'][$nomlower] = $GLOBALS['spip_pipeline'][$nom]; unset($GLOBALS['spip_pipeline'][$nom]); } $nom = $nomlower; if (!isset($GLOBALS['spip_pipeline'][$nom])) // creer le pipeline eventuel $GLOBALS['spip_pipeline'][$nom]=""; if (strpos($GLOBALS['spip_pipeline'][$nom],"|$prefix$action")===FALSE) $GLOBALS['spip_pipeline'][$nom] = preg_replace(",(\|\||$),","|$prefix$action\\1",$GLOBALS['spip_pipeline'][$nom],1); if (isset($pipe['inclure'])){ $GLOBALS['spip_matrice']["$prefix$action"] = "$root_dir_type:$plug/".$pipe['inclure']; } } } } } // on charge les fichiers d'options qui peuvent completer // la globale spip_pipeline egalement if (@is_readable(_CACHE_PLUGINS_PATH)) include_once(_CACHE_PLUGINS_PATH); // securite : a priori n'a pu etre fait plus tot if (@is_readable(_CACHE_PLUGINS_OPT)) { include_once(_CACHE_PLUGINS_OPT); } else { spip_log("pipelines desactives: impossible de produire " . _CACHE_PLUGINS_OPT); } // on ajoute les pipe qui ont ete recenses manquants foreach($liste_pipe_manquants as $add_pipe) if (!isset($GLOBALS['spip_pipeline'][$add_pipe])) $GLOBALS['spip_pipeline'][$add_pipe]= ''; $liste_fichier_verif2 = pipeline_precompile(); $liste_fichier_verif = array_merge($liste_fichier_verif,$liste_fichier_verif2); // on note dans tmp la liste des fichiers qui doivent etre presents, // pour les verifier "souvent" // ils ne sont verifies que depuis l'espace prive, mais peuvent etre reconstruit depuis l'espace public // dans le cas d'un plugin non declare, spip etant mis devant le fait accompli // hackons donc avec un "../" en dur dans ce cas, qui ne manquera pas de nous embeter un jour... foreach ($liste_fichier_verif as $k => $f){ // si un _DIR_XXX: est dans la chaine, on extrait la constante if (preg_match(",(_(DIR|ROOT)_[A-Z_]+):,Ums",$f,$regs)) $f = str_replace($regs[0],$regs[2]=="ROOT"?constant($regs[1]):(_DIR_RACINE?"":"../").constant($regs[1]),$f); $liste_fichier_verif[$k] = $f; } ecrire_fichier(_CACHE_PLUGINS_VERIF, serialize($liste_fichier_verif)); clear_path_cache(); }