function info_maj($dir, $file, $version) { include_spip('inc/plugin'); list($maj, $min, $rev) = preg_split('/\\D+/', $version); $nom = _DIR_CACHE_XML . _VERSIONS_LISTE; $page = !file_exists($nom) ? '' : file_get_contents($nom); $page = info_maj_cache($nom, $dir, $page); // reperer toutes les versions de numero majeur superieur ou egal // (a revoir quand on arrivera a SPIP V10 ...) $p = substr("0123456789", intval($maj)); $p = ',/' . $file . '\\D+([' . $p . ']+)\\D+(\\d+)(\\D+(\\d+))?.*?[.]zip",i'; preg_match_all($p, $page, $m, PREG_SET_ORDER); $page = ''; foreach ($m as $v) { list(, $maj2, $min2, , $rev2) = $v; $version_maj = $maj2 . '.' . $min2 . '.' . $rev2; if (spip_version_compare($version, $version_maj, '<') and spip_version_compare($page, $version_maj, '<')) { $page = $version_maj; } } if (!$page) { return ""; } return "<a class='info_maj_spip' href='" . _VERSIONS_SERVEUR . "{$dir}' title='{$page}'>" . _T('nouvelle_version_spip', array('version' => $page)) . '</a>'; }
function info_maj ($dir, $file, $version){ include_spip('inc/plugin'); list($maj,$min,$rev) = preg_split('/\D+/', $version); $nom = _DIR_CACHE_XML . _VERSIONS_LISTE; $page = !file_exists($nom) ? '' : file_get_contents($nom); $page = info_maj_cache($nom, $dir, $page); // reperer toutes les versions de numero majeur superieur ou egal // (a revoir quand on arrivera a SPIP V10 ...) $p = substr("0123456789", intval($maj)); $p = ',/' . $file . '\D+([' . $p . ']+)\D+(\d+)(\D+(\d+))?.*?[.]zip",i'; preg_match_all($p, $page, $m, PREG_SET_ORDER); $page = ''; foreach ($m as $v) { list(, $maj2, $min2,, $rev2) = $v; $version_maj = $maj2 . '.' . $min2 . '.' . $rev2; if ((spip_version_compare($version, $version_maj, '<')) AND (spip_version_compare($page, $version_maj, '<'))) $page = $version_maj; } if (!$page) return ""; return $page; }
/** * Pour une description de plugin donnée (issue de la dtd de paquet.xml), * prépare les données à installer en bdd * * Les données sont parfois sérialisées, parfois compilées * pour tenir compte des spécificités de cette DTD et du stockage en bdd. * * @param array $plugin * Description de plugin * @return array * Couples clés => valeurs de description du paquet **/ function plugins_preparer_sql_paquet($plugin) { include_spip('inc/svp_outiller'); $champs = array(); if (!$plugin) { return $champs; } // On initialise les champs ne necessitant aucune transformation foreach (array('categorie' => 'categorie', 'etat' => 'etat', 'version_base' => 'schema', 'logo' => 'logo', 'lien_doc' => 'documentation', 'lien_demo' => 'demonstration', 'lien_dev' => 'developpement') as $cle_champ => $cle_plugin) { $champs[$cle_champ] = (isset($plugin[$cle_plugin]) and $plugin[$cle_plugin]) ? $plugin[$cle_plugin] : ''; } // on normalise la version 1.3.12 => 001.003.012 $champs['version'] = (isset($plugin['version']) and $plugin['version']) ? normaliser_version($plugin['version']) : ''; // On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP // Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin $champs['prefixe'] = strtoupper($plugin['prefix']); // Indicateurs d'etat numerique (pour simplifier la recherche des maj de STP) static $num = array('stable' => 4, 'test' => 3, 'dev' => 2, 'experimental' => 1); $champs['etatnum'] = isset($num[$plugin['etat']]) ? $num[$plugin['etat']] : 0; // On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html foreach (array('nom' => 'nom', 'description' => 'description', 'slogan' => 'slogan') as $cle_champ => $cle_plugin) { $champs[$cle_champ] = (isset($plugin[$cle_plugin]) and $plugin[$cle_plugin]) ? entite2charset($plugin[$cle_plugin], 'utf-8') : ''; } // Cles necessitant d'etre serialisees // Tags : liste de mots-cles // Traitement des auteurs, credits, licences et copyright foreach (array('tags' => 'tags', 'auteur' => 'auteur', 'credit' => 'credit', 'licence' => 'licence', 'copyright' => 'copyright') as $cle_champ => $cle_plugin) { $champs[$cle_champ] = (isset($plugin[$cle_plugin]) and $plugin[$cle_plugin]) ? serialize($plugin[$cle_plugin]) : ''; } // Extraction de la compatibilite SPIP et construction de la liste des branches spip supportees $champs['compatibilite_spip'] = (isset($plugin['compatibilite']) and $plugin['compatibilite']) ? $plugin['compatibilite'] : ''; $champs['branches_spip'] = (isset($plugin['compatibilite']) and $plugin['compatibilite']) ? compiler_branches_spip($plugin['compatibilite']) : ''; // Construction du tableau des dependances necessite, lib et utilise $dependances['necessite'] = $plugin['necessite']; $dependances['librairie'] = $plugin['lib']; $dependances['utilise'] = $plugin['utilise']; $champs['dependances'] = serialize($dependances); // Calculer le champ 'procure' (tableau sérialisé prefixe => version) $champs['procure'] = ''; if (!empty($plugin['procure'][0])) { $champs['procure'] = array(); foreach ($plugin['procure'][0] as $procure) { $p = strtoupper($procure['nom']); if (!isset($champs['procure'][$p]) or spip_version_compare($procure['version'], $champs['procure'][$p], '>')) { $champs['procure'][$p] = $procure['version']; } } $champs['procure'] = serialize($champs['procure']); } return $champs; }
/** * Upload de documents * * Cette action recoit des fichiers ($_FILES) * et les affecte a l'objet courant ; * puis renvoie la liste des documents joints */ function action_crayons_upload() { $type = preg_replace('/\\W+/', '', strval(_request('type'))); $id = intval(_request('id')); // check securite :-) include_spip('inc/autoriser'); if (!autoriser('joindredocument', $type, $id)) { echo "Erreur: upload interdit"; return false; } // on n'accepte qu'un seul document à la fois, dans la variable 'upss' if ($file = $_FILES['upss'] and $file['error'] == 0) { $source = $file['tmp_name']; # /tmp/php/phpxxx $nom_envoye = $file['name']; # mon-image.jpg include_spip('plugins/installer'); // spip_version_compare dans SPIP 3.x include_spip('inc/plugin'); // spip_version_compare dans SPIP 2.x if (function_exists('spip_version_compare')) { // gerer son absence dans les branche precedente a SPIP 2.x if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) { define('_SPIP3', true); } } if (defined('_SPIP3')) { include_spip('action/ajouter_documents'); $ajouter_un_document = charger_fonction('ajouter_un_document', 'action'); $id = $ajouter_un_document("new", $file, $type, $id, 'document'); } else { include_spip('inc/ajouter_documents'); $id = ajouter_un_document($source, $nom_envoye, $type, $id, 'document', $id_document = 0, $documents_actifs, $titrer = true); } } if (!$id) { $erreur = "erreur !"; } $a = recuperer_fond('modeles/uploader_item', array('id_document' => $id, 'erreur' => $erreur)); echo $a; }
function liste_webmestres($void) { $webmestres = array(); include_spip('inc/texte'); include_spip('inc/plugin'); // Version SPIP < 2.1 ou alors >= 2.1 mais utilisant toujours le define pour etablir la liste if (!function_exists('spip_version_compare') OR spip_version_compare($GLOBALS['spip_version_branche'],"2.1.0-rc","<") OR defined('_ID_WEBMESTRES')) { $s = spip_query("SELECT * FROM spip_auteurs WHERE id_auteur IN (". join (',', array_filter(explode(':', _ID_WEBMESTRES), is_numeric)).")"); } // Version SPIP >= 2.1 et utilisation du flag webmestre en base de donnees else { $s = spip_query("SELECT * FROM spip_auteurs WHERE webmestre='oui'"); } while ($qui = sql_fetch($s)) { if (autoriser('webmestre','','',$qui)) $webmestres[$qui['id_auteur']] = typo($qui['nom']); } return join(', ', $webmestres); }
function maj_vieille_base_charger_dist($version_cible){ $vieilles_bases = array( '1.813'=>'1813', '1.821'=>'1821', '1.915'=>'1915', '1.917'=>'1917', '1.927'=>'1927', '10000'=>'10000', '12000'=>'13000', ); $version = false; foreach($vieilles_bases as $v=>$n){ if (!$version OR spip_version_compare($v,$version_cible,'<')) $version = $n; } /* include_spip('base/serial'); include_spip('base/auxiliaires'); $GLOBALS['nouvelle_base']['tables_principales'] = $GLOBALS['tables_principales']; $GLOBALS['nouvelle_base']['tables_auxiliaires'] = $GLOBALS['tables_auxiliaires'];*/ unset($GLOBALS['tables_principales']); unset($GLOBALS['tables_auxiliaires']); unset($GLOBALS['tables_images']); unset($GLOBALS['tables_sequences']); unset($GLOBALS['tables_documents']); unset($GLOBALS['tables_mime']); // chargera les descriptions de table $create = charger_fonction('create',"maj/vieille_base/$version"); if (!isset($GLOBALS['tables_auxiliaires']['spip_meta']['field']['impt'])) $GLOBALS['tables_auxiliaires']['spip_meta']['field']['impt'] = "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL"; return $version; }
/** * Teste qu'un paquet (via son préfixe) sera actif directement * ou par l'intermediaire d'un procure * * @param string $prefixe * Préfixe du paquet * @return bool * Le paquet sera t'il actif ? **/ public function sera_actif($prefixe) { if (isset($this->end['p'][$prefixe])) { return $this->end['p'][$prefixe]; } // sinon regarder les procure $v = "0.0.0"; $plugin = false; foreach ($this->end['p'] as $endp => $end) { if (isset($end['procure'][$prefixe]) and spip_version_compare($end['procure'][$prefixe], $v, ">")) { $v = $end['procure'][$prefixe]; $plugin = $this->end['p'][$endp]; } } return $plugin; }
/** * Détermine la version max de chaque plugin, c'est à dire * la version maxi d'un des paquets qui lui est lié. * * @param array $plugins Liste d'identifiant de plugins **/ function svp_corriger_vmax_plugins($plugins) { // tous les plugins encore lies a des depots (hors local)... // la vmax est a retablir... if ($plugins) { $p = sql_allfetsel('DISTINCT(p.id_plugin)', array('spip_plugins AS p', 'spip_paquets AS pa'), array(sql_in('p.id_plugin', $plugins), 'p.id_plugin=pa.id_plugin', 'pa.id_depot>' . intval(0))); $p = array_map('array_shift', $p); // pour les autres, on la fixe correctement // On insere, en encapsulant pour sqlite... if (sql_preferer_transaction()) { sql_demarrer_transaction(); } foreach ($p as $id_plugin) { $vmax = ''; if ($pa = sql_allfetsel('version', 'spip_paquets', array('id_plugin=' . $id_plugin, 'id_depot>' . intval(0)))) { foreach ($pa as $v) { if (spip_version_compare($v['version'], $vmax, '>')) { $vmax = $v['version']; } } } sql_updateq('spip_plugins', array('vmax' => $vmax), 'id_plugin=' . intval($id_plugin)); } if (sql_preferer_transaction()) { sql_terminer_transaction(); } } }
/** * Test du statut d'install * * @param string $action * @param string $prefix * @param string $version_cible * @return bool */ function bank_install($action, $prefix, $version_cible) { $version_base = $GLOBALS[$prefix . "_base_version"]; switch ($action) { case 'test': $ok = (isset($GLOBALS['meta'][$prefix . "_base_version"]) and spip_version_compare($GLOBALS['meta'][$prefix . "_base_version"], $version_cible, ">=")); if ($ok) { // verifier/maj des fichiers de config bank_presta_install(); } return $ok; break; case 'install': bank_upgrade($prefix . "_base_version", $version_cible); break; case 'uninstall': bank_vider_tables($prefix . "_base_version"); break; } }
/** * Vérifier si une nouvelle version de SPIP est disponible * * Repérer aussi si cette version est une version majeure de SPIP. * * @param string $dir * @param string $file * @param string $version * La version reçue ici est sous la forme x.y.z * On la transforme par la suite pour avoir des integer ($maj, $min, $rev) * et ainsi pouvoir mieux les comparer * * @return string */ function info_maj($dir, $file, $version) { include_spip('inc/plugin'); list($maj, $min, $rev) = preg_split('/\\D+/', $version); $nom = _DIR_CACHE_XML . _VERSIONS_LISTE; $page = !file_exists($nom) ? '' : file_get_contents($nom); $page = info_maj_cache($nom, $dir, $page); // reperer toutes les versions de numero majeur superieur ou egal // (a revoir quand on arrivera a SPIP V10 ...) $p = substr("0123456789", intval($maj)); $p = ',/' . $file . '\\D+([' . $p . ']+)\\D+(\\d+)(\\D+(\\d+))?.*?[.]zip",i'; preg_match_all($p, $page, $m, PREG_SET_ORDER); $page = $page_majeure = ''; // branche en cours d'utilisation $branche = implode('.', array_slice(explode('.', $version, 3), 0, 2)); foreach ($m as $v) { list(, $maj2, $min2, , $rev2) = $v; $branche_maj = $maj2 . '.' . $min2; $version_maj = $maj2 . '.' . $min2 . '.' . $rev2; // d'abord les mises à jour de la même branche if (spip_version_compare($version, $version_maj, '<') and spip_version_compare($page, $version_maj, '<') and spip_version_compare($branche, $branche_maj, '=')) { $page = $version_maj; } // puis les mises à jours majeures if (spip_version_compare($version, $version_maj, '<') and spip_version_compare($page, $version_maj, '<') and spip_version_compare($branche, $branche_maj, '<')) { $page_majeure = $version_maj; } } if (!$page and !$page_majeure) { return ""; } $message = $page ? _T('nouvelle_version_spip', array('version' => $page)) . ($page_majeure ? ' | ' : '') : ''; $message .= $page_majeure ? _T('nouvelle_version_spip_majeure', array('version' => $page_majeure)) : ''; return "<a class='info_maj_spip' href='http://www.spip.net/fr_update' title='{$page}'>" . $message . '</a>'; }
function plugin_message_incompatibilite($intervalle, $version, $nom, $balise) { if (preg_match(_EXTRAIRE_INTERVALLE, $intervalle, $regs)) { $minimum = $regs[1]; $maximum = $regs[2]; $minimum_inclus = $intervalle[0] == "["; $maximum_inclus = substr($intervalle, -1) == "]"; if (strlen($minimum)) { if ($minimum_inclus and spip_version_compare($version, $minimum, '<')) { return _T("plugin_{$balise}_plugin", array('plugin' => $nom, 'version' => ' ≥ ' . $minimum)); } if (!$minimum_inclus and spip_version_compare($version, $minimum, '<=')) { return _T("plugin_{$balise}_plugin", array('plugin' => $nom, 'version' => ' > ' . $minimum)); } } if (strlen($maximum)) { if ($maximum_inclus and spip_version_compare($version, $maximum, '>')) { return _T("plugin_{$balise}_plugin", array('plugin' => $nom, 'version' => ' ≤ ' . $maximum)); } if (!$maximum_inclus and spip_version_compare($version, $maximum, '>=')) { return _T("plugin_{$balise}_plugin", array('plugin' => $nom, 'version' => ' < ' . $maximum)); } } } return _T("plugin_necessite_plugin_sans_version", array('plugin' => $nom)); }
/** * Pour une description de plugin donnée (issue de la dtd de plugin.xml), * prépare les données à installer en bdd * * Les données sont parfois sérialisées, parfois transcodées, parfois compilées * pour tenir compte des spécificités de cette DTD et du stockage en bdd. * * @uses compiler_branches_spip() * @param array $plugin * Description de plugin * @return array * Couples clés => valeurs de description du paquet **/ function plugins_preparer_sql_plugin($plugin) { include_spip('inc/svp_outiller'); $champs = array(); if (!$plugin) { return $champs; } // On initialise les champs ne necessitant aucune transformation $champs['categorie'] = (isset($plugin['categorie']) and $plugin['categorie']) ? $plugin['categorie'] : ''; $champs['etat'] = (isset($plugin['etat']) and $plugin['etat']) ? $plugin['etat'] : ''; $champs['version'] = $plugin['version'] ? normaliser_version($plugin['version']) : ''; $champs['version_base'] = (isset($plugin['schema']) and $plugin['schema']) ? $plugin['schema'] : ''; // Renommage de certains champs $champs['logo'] = (isset($plugin['logo']) and $plugin['logo']) ? $plugin['logo'] : ''; $champs['lien_doc'] = (isset($plugin['documentation']) and $plugin['documentation']) ? normaliser_lien($plugin['documentation']) : ''; // On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP // Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin $champs['prefixe'] = strtoupper($plugin['prefix']); // Indicateurs d'etat numerique (pour simplifier la recherche des maj de STP) static $num = array('stable' => 4, 'test' => 3, 'dev' => 2, 'experimental' => 1); $champs['etatnum'] = (isset($plugin['etat']) and isset($num[$plugin['etat']])) ? $num[$plugin['etat']] : 0; // Tags : liste de mots-cles $champs['tags'] = (isset($plugin['tags']) and $plugin['tags']) ? serialize($plugin['tags']) : ''; // On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html $champs['description'] = entite2charset($plugin['description'], 'utf-8'); // Traitement des auteurs, credits, licences et copyright // -- on extrait les auteurs, licences et copyrights sous forme de tableaux // -- depuis le commit 18294 du core la balise auteur est renvoyee sous forme de tableau mais // contient toujours qu'un seul index $balise_auteur = entite2charset($plugin['auteur'][0], 'utf-8'); $auteurs = normaliser_auteur_licence($balise_auteur, 'auteur'); $balise_licence = isset($plugin['licence'][0]) ? entite2charset($plugin['licence'][0], 'utf-8') : ''; $licences = normaliser_auteur_licence($balise_licence, 'licence'); // -- on merge les tableaux recuperes dans auteur et licence $champs['auteur'] = $champs['licence'] = $champs['copyright'] = ''; if ($t = array_merge($auteurs['auteur'], $licences['auteur'])) { $champs['auteur'] = serialize($t); } if ($t = array_merge($auteurs['licence'], $licences['licence'])) { $champs['licence'] = serialize($t); } if ($t = array_merge($auteurs['copyright'], $licences['copyright'])) { $champs['copyright'] = serialize($t); } // Extrait d'un nom et un slogan normalises // Slogan : si vide on ne fait plus rien de special, on traitera ça a l'affichage $champs['slogan'] = $plugin['slogan'] ? entite2charset($plugin['slogan'], 'utf-8') : ''; // Nom : on repere dans le nom du plugin un chiffre en fin de nom // et on l'ampute de ce numero pour le normaliser // et on passe tout en unicode avec le charset du site $champs['nom'] = trim(entite2charset($plugin['nom'], 'utf-8')); // Extraction de la compatibilite SPIP et construction de la liste des branches spip supportees $champs['compatibilite_spip'] = $plugin['compatibilite'] ? $plugin['compatibilite'] : ''; $champs['branches_spip'] = $plugin['compatibilite'] ? compiler_branches_spip($plugin['compatibilite']) : ''; // Construction du tableau des dependances necessite, lib et utilise $dependances['necessite'] = $plugin['necessite']; $dependances['librairie'] = $plugin['lib']; $dependances['utilise'] = $plugin['utilise']; $champs['dependances'] = serialize($dependances); // Calculer le champ 'procure' (tableau sérialisé prefixe => version) $champs['procure'] = ''; if (!empty($plugin['procure'][0])) { $champs['procure'] = array(); foreach ($plugin['procure'][0] as $procure) { $p = strtoupper($procure['nom']); if (!isset($champs['procure'][$p]) or spip_version_compare($procure['version'], $champs['procure'][$p], '>')) { $champs['procure'][$p] = $procure['version']; } } $champs['procure'] = serialize($champs['procure']); } // Champs non supportes par la DTD plugin et ne pouvant etre deduits d'autres balises $champs['lien_demo'] = ''; $champs['lien_dev'] = ''; $champs['credit'] = ''; return $champs; }
function article_import_k2($mon_article) { include_spip('joomla2spip_fonctions'); include_spip('plugins/installer'); $err = ''; // chercher si l'article n'a pas deja ete importe $ancien_id = $mon_article['id_article']; $result = sql_fetsel('id_article', 'spip_articles', 'id_article=' . intval($ancien_id)); if ($result) { return; } // chercher la rubrique $titre_rub = $mon_article['rubrique']; $result = sql_fetsel('id_rubrique', 'spip_rubriques', 'titre=' . sql_quote($titre_rub)); if ($result) { $id_rubrique = $result['id_rubrique']; } // creer article vide include_spip('action/editer_article'); $id_article = insert_article($id_rubrique); $sql = "UPDATE spip_articles SET id_article = '{$ancien_id}' WHERE id_article = '{$id_article}'"; spip_query($sql); if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0', '>=')) { include_spip('action/editer_article'); $sql = "UPDATE spip_auteurs_liens SET id_objet = '{$ancien_id}' WHERE id_objet = '{$id_article}' AND objet = 'article'"; } else { include_spip('inc/modifier'); $sql = "UPDATE spip_auteurs_articles SET id_article = '{$ancien_id}' WHERE id_article = '{$id_article}'"; } spip_query($sql); $id_article = $ancien_id; // le remplir $c = array(); foreach (array('surtitre', 'titre', 'soustitre', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'maj', 'ps', 'visites') as $champ) { $c[$champ] = $mon_article[$champ]; } revisions_articles($id_article, $c); // Modification de statut, changement de rubrique ? $c = array(); foreach (array('date', 'statut', 'id_parent') as $champ) { $c[$champ] = $mon_article[$champ]; } $c['id_parent'] = $id_rubrique; $err .= instituer_article($id_article, $c); // Un lien de trad a prendre en compte if (!spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0', '>=')) { $err .= article_referent($id_article, array('lier_trad' => _request('lier_trad'))); } // ajouter les extras // les documents attachées if (isset($mon_article['document']) and count($mon_article['document']) > 0) { $ajouter_documents = charger_fonction('ajouter_documents', 'action'); $copie_local = charger_fonction('copier_local', 'action'); include_spip('inc/joindre_document'); include_spip('formulaires/joindre_document'); foreach ($mon_article['document'] as $document) { $file = url_absolue('media/k2/attachments/' . $document['fichier']); spip_log($file, 'teste'); set_request('joindre_distant', true); set_request('url', $file); $files = joindre_trouver_fichier_envoye(); $mode = joindre_determiner_mode('auto', 'new', 'article'); $nouveaux_doc = $ajouter_documents('new', $files, 'article', $id_article, $mode); spip_log($nouveaux_doc, 'teste'); $id_document = $nouveaux_doc[0]; $copie_local($id_document); $titre = isset($document['titre']) ? $document['titre'] : ''; sql_updateq('spip_documents', array('titre' => $titre), 'id_document=' . $id_document); } } return $err; }
/** * Vérifie qu'un plugin plus récent existe pour un préfixe et une version donnée * * @param string $prefixe * Préfixe du plugin * @param string $version * Compatibilité à comparer, exemple '[1.0;]' * @return bool|array * false si pas de plugin plus récent trouvé * tableau de description du paquet le plus récent sinon */ function chercher_plugin_recent($prefixe, $version) { $news = $this->infos_courtes(array('pl.prefixe=' . sql_quote($prefixe), 'pa.obsolete=' . sql_quote('non'), 'pa.id_depot > ' . sql_quote(0)), true); $res = false; if ($news and count($news['p'][$prefixe]) > 0) { foreach ($news['p'][$prefixe] as $new) { if (spip_version_compare($new['v'], $version, '>')) { if (!$res or version_compare($new['v'], $res['v'], '>')) { $res = $new; } } } } return $res; }
function plugin_valide_resume(&$liste, $plug, $infos, $dir) { $i = $infos[$dir][$plug]; if (isset($i['erreur']) and $i['erreur']) { return; } if (!plugin_version_compatible($i['compatibilite'], $GLOBALS['spip_version_branche'], 'spip')) { return; } $p = strtoupper($i['prefix']); if (!isset($liste[$p]) or spip_version_compare($i['version'], $liste[$p]['version'], '>')) { $liste[$p] = array('nom' => $i['nom'], 'etat' => $i['etat'], 'version' => $i['version'], 'dir' => $plug, 'dir_type' => $dir); } }
/** * Fusion des informations de chaque balise plugin d'un plugin.xml en * considérant la compatibilité SPIP * * Pour les balises plugins uniques cette fonction permet de générer une structure * identique pour les balises dites techniques * * On limite le traitement a deux balises plugins maximum, * ce qui est le cas de tous les plugin.xml actuellement connus * * @param array $plugins * Arbre des balises plugins présents dans un plugin.xml * @return array * Fusion des éléments classé par balise, puis par compatibilité à SPIP. * L'index 0 dans la compatibilité est valable quelque soit la version de SPIP. */ function plugins_fusion_plugin($plugins) { global $balises_techniques; $fusion = array(); if (!$plugins) { return $fusion; } if (count($plugins) == 1) { // Balise plugin unique : on ne traite que les balises techniques $fusion = $plugins[0]; foreach ($balises_techniques as $_btech) { if (isset($fusion[$_btech]) and $fusion[$_btech]) { $balise = $fusion[$_btech]; unset($fusion[$_btech]); $fusion[$_btech][0] = $balise; } else { $fusion[$_btech] = array(); } } } else { // On initialise les informations a retourner avec le bloc a priori le plus recent determine par la compatibilite SPIP : // On selectionne le bloc dont la borne min de compatibilite SPIP est la plus elevee $cle_min_max = -1; $borne_min_max = _SVP_VERSION_SPIP_MIN; foreach ($plugins as $_cle => $_plugin) { if (!$_plugin['compatibilite']) { $borne_min = _SVP_VERSION_SPIP_MIN; } $bornes_spip = extraire_bornes($_plugin['compatibilite']); $borne_min = $bornes_spip['min']['valeur'] ? $bornes_spip['min']['valeur'] : _SVP_VERSION_SPIP_MIN; if (spip_version_compare($borne_min_max, $borne_min, '<=')) { $cle_min_max = $_cle; $borne_min_max = $borne_min; } } $fusion = $plugins[$cle_min_max]; // On relit les autres blocs que celui venant d'etre selectionne et on fusionne les informations necessaires // les traitements effectues sont les suivants : // -- nom, prefix, documentation, version, etat, version_base, description : *rien*, on conserve ces informations en l'etat // -- options, fonctions, install : *rien*, meme si certaines pourraient etre fusionnees ces infos ne sont pas stockees // -- auteur, licence : *rien*, l'heuristique pour fusionner ces infos est trop compliquee aujourdhui car c'est du texte libre // -- categorie, logo : si la valeur du bloc selectionne est vide on essaye d'en trouver une non vide dans les autres blocs // -- compatible : on constuit l'intervalle global de compatibilite SPIP // -- necessite, utilise, lib : on construit le tableau par intervalle de compatibilite SPIP $cle_min_min = $cle_min_max == 0 ? 1 : 0; if (!$fusion['categorie'] and $plugins[$cle_min_min]['categorie']) { $fusion['categorie'] = $plugins[$cle_min_min]['categorie']; } if ((!isset($fusion['logo']) or !$fusion['logo']) and $plugins[$cle_min_min]['logo']) { $fusion['logo'] = $plugins[$cle_min_min]['logo']; } $fusion['compatibilite'] = fusionner_intervalles($fusion['compatibilite'], $plugins[$cle_min_min]['compatibilite']); // necessite, utilise, lib, chemin, pipeline, bouton, onglet : on indexe chaque liste de dependances // par l'intervalle de compatibilite sans regrouper les doublons pour l'instant foreach ($balises_techniques as $_btech) { if (!isset($fusion[$_btech]) and !isset($plugins[$cle_min_min][$_btech])) { // Aucun des tableaux ne contient cette balise technique : on la positionne a un array vide $fusion[$_btech] = array(); } else { if (!isset($fusion[$_btech]) or !$fusion[$_btech]) { if ($plugins[$cle_min_min][$_btech]) { // La balise technique est vide dans le tableau de fusion mais non vide dans la deuxieme balise plugin // On range cette balise dans le tableau fusion de sa compatibilite et on cree la cle commune vide $fusion[$_btech][$plugins[$cle_min_min]['compatibilite']] = $plugins[$cle_min_min][$_btech]; $fusion[$_btech][0] = array(); } } else { if (!isset($plugins[$cle_min_min][$_btech]) or !$plugins[$cle_min_min][$_btech]) { // La balise technique est non vide dans le tableau de fusion mais vide dans la deuxieme balise plugin // On deplace cette balise dans le tableau fusion de sa compatibilite et on cree la cle commune vide $balise = $fusion[$_btech]; unset($fusion[$_btech]); $fusion[$_btech][$plugins[$cle_min_max]['compatibilite']] = $balise; $fusion[$_btech][0] = array(); } else { // Les deux tableaux contiennent une balise technique non vide : il faut fusionner cette balise technique ! // On parcourt le premier tableau (fusion) en verifiant une egalite avec le deuxieme tableau foreach ($fusion[$_btech] as $_cle0 => $_balise0) { $balise_commune = false; foreach ($plugins[$cle_min_min][$_btech] as $_cle1 => $_balise1) { if (balise_identique($_balise0, $_balise1)) { // On classe cette balise dans le bloc commun (index 0) et on la supprime dans les // 2 tableaux en cours de comparaison unset($fusion[$_btech][$_cle0]); $fusion[$_btech][0][] = $_balise1; unset($plugins[$cle_min_min][$_btech][$_cle1]); $balise_commune = true; break; } } if (!$balise_commune) { $fusion[$_btech][$plugins[$cle_min_max]['compatibilite']][] = $_balise0; unset($fusion[$_btech][$_cle0]); } if (!isset($fusion[$_btech][0])) { $fusion[$_btech][0] = array(); } } // On traite maintenant les balises restantes du deuxieme tableau if ($plugins[$cle_min_min][$_btech]) { foreach ($plugins[$cle_min_min][$_btech] as $_balise2) { $fusion[$_btech][$plugins[$cle_min_min]['compatibilite']][] = $_balise2; } } } } } } } return $fusion; }
function crayons_store_set_modifs($modifs, $return) { // sinon on bosse : toutes les modifs ont ete acceptees // verifier qu'on a tout ce qu'il faut pour mettre a jour la base // et regrouper les mises a jour par type/id foreach ($modifs as $modif) { list($type, $modele, $id, $content, $wid) = $modif; $fun = ''; // si le crayon est un MODELE avec une fonction xxx_revision associee // cas ou une fonction xxx_revision existe if (function_exists($f = $type . '_' . $modele . "_revision") or function_exists($f = $modele . "_revision") or function_exists($f = $type . "_revision")) { $fun = $f; } elseif (function_exists('lister_tables_objets_sql') and $tables_objet = lister_tables_objets_sql() and isset($tables_objet[table_objet_sql($type)])) { $fun = 'crayons_objet_modifier'; } else { switch ($type) { case 'article': $fun = 'crayons_update_article'; break; case 'breve': include_spip('action/editer_breve'); $fun = 'revisions_breves'; break; case 'forum': include_spip('inc/forum'); $fun = 'enregistre_et_modifie_forum'; break; case 'rubrique': include_spip('action/editer_rubrique'); $fun = 'revisions_rubriques'; break; case 'syndic': case 'site': include_spip('action/editer_site'); $fun = 'revisions_sites'; break; case 'document': include_spip('plugins/installer'); include_spip('inc/plugin'); if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) { include_spip('action/editer_document'); $fun = 'document_modifier'; } else { include_spip('inc/modifier'); $fun = 'revision_document'; } break; // cas geres de la maniere la plus standard // cas geres de la maniere la plus standard case 'auteur': case 'mot': case 'signature': case 'petition': default: include_spip('inc/modifier'); $fun = 'revision_' . $type; break; } } // si on a pas reussi on passe par crayons_update() qui fera un update sql brutal if (!$fun or !function_exists($fun)) { $fun = 'crayons_update'; // $return['$erreur'] = "$type: " . _U('crayons:non_implemente'); // break; } if (!isset($updates[$type][$fun])) { $updates[$type][$fun] = array(); } if (!isset($updates[$type][$fun][$id])) { $updates[$type][$fun][$id] = array('wdg' => array(), 'chval' => array()); } // pour reaffecter le retour d'erreur sql au cas ou $updates[$type][$fun][$id]['wdg'][] = $wid; foreach ($content as $champtable => $val) { $updates[$type][$fun][$id]['chval'][$champtable] = $val; } } // il manque une fonction de mise a jour ==> on ne fait rien ! if ($return['$erreur']) { return $return; } // hop ! mises a jour table par table et id par id foreach ($updates as $type => $idschamps) { foreach ($idschamps as $fun => $ids) { foreach ($ids as $id => $champsvaleurs) { /* cas particulier du logo dans un crayon complexe : ce n'est pas un champ de la table */ if (isset($champsvaleurs['chval']['logo'])) { spip_log('revision logo', 'crayons'); logo_revision($id, $champsvaleurs['chval'], $type, $champsvaleurs['wdg']); unset($champsvaleurs['chval']['logo']); } if (count($champsvaleurs['chval'])) { // -- revisions_articles($id_article, $c) -- spip_log("{$fun}({$id} ...)", 'crayons'); $updok = $fun($id, $champsvaleurs['chval'], $type, $champsvaleurs['wdg']); // Renvoyer erreur si update base distante echoue, on ne regarde pas les updates base local car ils ne renvoient rien list($distant, $table) = distant_table($type); if ($distant and !$updok) { $return['$erreur'] = "{$type}: " . _U('crayons:update_impossible'); } } } } } return $return; }
function spip_plugin_install($action, $infos, $version_cible) { $prefix = $infos['prefix']; if (isset($infos['meta']) and ($table = $infos['meta']) !== 'meta') { $nom_meta = "base_version"; } else { $nom_meta = $prefix . "_base_version"; $table = 'meta'; } switch ($action) { case 'test': return isset($GLOBALS[$table]) and isset($GLOBALS[$table][$nom_meta]) and spip_version_compare($GLOBALS[$table][$nom_meta], $version_cible, '>='); break; case 'install': if (function_exists($upgrade = $prefix . "_upgrade")) { $upgrade($nom_meta, $version_cible, $table); } break; case 'uninstall': if (function_exists($vider_tables = $prefix . "_vider_tables")) { $vider_tables($nom_meta, $table); } break; } }
if ($GLOBALS['autorite']['statut_ignorer_admins_restreints'] == 'oui') { if (defined('_ADMINS_RESTREINTS')) $autorite_erreurs[] = 'ignorer_admins_restreints'; else define('_ADMINS_RESTREINTS', false); } // Charger les versions *_dist des fonctions include_once _DIR_RESTREINT.'inc/autoriser.php'; // si ca n'a pas ete fait et que l'on est dans une version ancienne de spip // definir _ID_WEBMESTRES if (!defined('_ID_WEBMESTRES') AND include_spip('inc/plugin') AND (!function_exists('spip_version_compare') OR spip_version_compare($GLOBALS['spip_version_branche'],"2.1.0-rc","<"))) { define ('_ID_WEBMESTRES', '1'); // '1:5:90' a regler dans mes_options } // // Les FONCTIONS // ## ## une fonction qui gere les droits publieurs ## if ($GLOBALS['autorite']['espace_publieur']) { if (!function_exists('autorisation_publie_visiteur')) { function autorisation_publie_visiteur($qui, $id_secteur) {
/** * Cherche dans les dépots distants un plugin qui serait plus à jour * que le prefixe, version et état que l'on transmet * * @param string $prefixe * Préfixe du plugin * @param string $version * Version du paquet à comparer * @param int $etatnum * État du paquet numérique * @return string * Version plus à jour, sinon rien **/ function svp_rechercher_maj_version($prefixe, $version, $etatnum) { $maj_version = ""; if ($res = sql_allfetsel(array('pl.id_plugin', 'pa.version'), array('spip_plugins AS pl', 'spip_paquets AS pa'), array('pl.id_plugin = pa.id_plugin', 'pa.id_depot>' . sql_quote(0), 'pl.prefixe=' . sql_quote($prefixe), 'pa.etatnum>=' . sql_quote($etatnum)))) { foreach ($res as $paquet_distant) { // si version superieure et etat identique ou meilleur, // c'est que c'est une mise a jour possible ! if (spip_version_compare($paquet_distant['version'], $version, '>')) { if (!strlen($maj_version) or spip_version_compare($paquet_distant['version'], $maj_version, '>')) { $maj_version = $paquet_distant['version']; } # a voir si on utilisera... # "superieur" => "varchar(3) DEFAULT 'non' NOT NULL", # // superieur : version plus recente disponible (distant) d'un plugin (actif?) existant } } } return $maj_version; }
/** * Callback de tri pour trier les résultats de plugin par nom (alphabétique). * * Si le nom est identique on classe par version decroissante * Cette fonction est appelée par un usort ou uasort * * @param array $p1 * Plugin à comparer * @param array $p2 * Plugin à comparer * @return int */ function svp_trier_par_nom($p1, $p2) { $c1 = strcasecmp($p1['nom'], $p2['nom']); if ($c1 == 0) { $c2 = spip_version_compare($p1['version'], $p1['version'], '<'); $retour = $c2 ? 1 : -1; } else { $retour = $c1 < 0 ? -1 : 1; } return $retour; }
/** * Retourne la liste des branches de SPIP comprises dans un intervalle * de compatibilité donné. * * @param string $intervalle * Intervalle de compatibilité, tel que [2.0.0;3.0.0] * @return string * Branches de SPIP séparées par des virgules, tel que 2.0,2.1,3.0 **/ function compiler_branches_spip($intervalle) { include_spip('plugins/installer'); global $infos_branches_spip; $liste_branches_spip = array_keys($GLOBALS['infos_branches_spip']); $bornes = extraire_bornes($intervalle, false); // On traite d'abord les cas ou l'intervalle est : // - vide // - non vide mais avec les deux bornes vides // Dans ces cas la compatibilite est totale, on renvoie toutes les branches if (!$intervalle or !$bornes['min']['valeur'] and !$bornes['max']['valeur']) { return implode(',', $liste_branches_spip); } // On force l'initialisation des bornes et on les nettoie des suffixes d'etat $bornes = extraire_bornes($intervalle, true); // Si les bornes sont en dehors de l'intervalle [_SVP_VERSION_SPIP_MIN;_SVP_VERSION_SPIP_MAX] on le reduit if (spip_version_compare($bornes['min']['valeur'], _SVP_VERSION_SPIP_MIN, '<')) { $bornes['min']['valeur'] = _SVP_VERSION_SPIP_MIN; $bornes['min']['incluse'] = true; } if (spip_version_compare(_SVP_VERSION_SPIP_MAX, $bornes['max']['valeur'], '<=')) { $bornes['max']['valeur'] = _SVP_VERSION_SPIP_MAX; $bornes['max']['incluse'] = true; } // On les nettoie des suffixes d'etat $borne_inf = strtolower(preg_replace(',([0-9])[\\s-.]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1', $bornes['min']['valeur'])); $borne_sup = strtolower(preg_replace(',([0-9])[\\s-.]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1', $bornes['max']['valeur'])); // On determine les branches inf et sup issues du phrasage de l'intervalle // -- on initialise la branche inf de l'intervalle que l'on va preciser ensuite $t = explode('.', $borne_inf); $branche_inf = $t[0] . '.' . $t[1]; // -- pour eviter toutes erreur fatale on verifie que la branche est bien dans la liste des possibles // -- -> si non, on renvoie vide if (!in_array($branche_inf, $liste_branches_spip)) { return ''; } // -- on complete la borne inf de l'intervalle de x.y en x.y.z et on determine la vraie branche if (!isset($t[2]) or !$t[2]) { if ($bornes['min']['incluse']) { $borne_inf = $infos_branches_spip[$branche_inf][0]; } else { $branche_inf = $liste_branches_spip[array_search($branche_inf, $liste_branches_spip) + 1]; $borne_inf = $infos_branches_spip[$branche_inf][0]; } } // -- on initialise la branche sup de l'intervalle que l'on va preciser ensuite $t = explode('.', $borne_sup); // des gens mettent juste * (pas glop) $branche_sup = $t[0] . (isset($t[1]) ? '.' . $t[1] : ''); // -- pour eviter toutes erreur fatale on verifie que la branche est bien dans la liste des possibles // -- -> si non, on renvoie vide if (!in_array($branche_sup, $liste_branches_spip)) { return ''; } // -- on complete la borne sup de l'intervalle de x.y en x.y.z et on determine la vraie branche if (!isset($t[2]) or !$t[2]) { if ($bornes['max']['incluse']) { $borne_sup = $infos_branches_spip[$branche_sup][1]; } else { $branche_sup = $liste_branches_spip[array_search($branche_sup, $liste_branches_spip) - 1]; $borne_sup = $infos_branches_spip[$branche_sup][1]; } } // -- on verifie que les bornes sont bien dans l'ordre : // -> sinon on retourne la branche sup uniquement if (spip_version_compare($borne_inf, $borne_sup, '>=')) { return $branche_sup; } // A ce stade, on a un intervalle ferme en bornes ou en branches // Il suffit de trouver les branches qui y sont incluses, sachant que les branches inf et sup // le sont a coup sur maintenant $index_inf = array_search($branche_inf, $liste_branches_spip); $index_sup = array_search($branche_sup, $liste_branches_spip); $liste = array(); for ($i = $index_inf; $i <= $index_sup; $i++) { $liste[] = $liste_branches_spip[$i]; } return implode(',', $liste); }
/** * Creer la requete pour la creation d'une table * retourne la requete pour utilisation par sql_create() et sql_alter() * * http://code.spip.net/@_sqlite_requete_create * * @param $nom * @param $champs * @param $cles * @param bool $autoinc * @param bool $temporary * @param bool $_ifnotexists * @param string $serveur * @param bool $requeter * @return bool|string */ function _sqlite_requete_create($nom, $champs, $cles, $autoinc = false, $temporary = false, $_ifnotexists = true, $serveur = '', $requeter = true) { $query = $keys = $s = $p = ''; // certains plugins declarent les tables (permet leur inclusion dans le dump) // sans les renseigner (laisse le compilo recuperer la description) if (!is_array($champs) || !is_array($cles)) { return; } // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE // il faut passer par des create index // Il gere par contre primary key ! // Soit la PK est definie dans les cles, soit dans un champs $c = ""; // le champ de cle primaire if (!isset($cles[$pk = "PRIMARY KEY"]) or !($c = $cles[$pk])) { foreach ($champs as $k => $v) { if (false !== stripos($v, $pk)) { $c = $k; // on n'en a plus besoin dans field, vu que defini dans key $champs[$k] = preg_replace("/{$pk}/is", '', $champs[$k]); break; } } } if ($c) { $keys = "\n\t\t{$pk} ({$c})"; } // Pas de DEFAULT 0 sur les cles primaires en auto-increment if (isset($champs[$c]) and stripos($champs[$c], "default 0") !== false) { $champs[$c] = trim(str_ireplace("default 0", "", $champs[$c])); } $champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $c : false); foreach ($champs as $k => $v) { $query .= "{$s}\n\t\t{$k} {$v}"; $s = ","; } $ifnotexists = ""; if ($_ifnotexists) { $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version", $serveur), '', $serveur); if (!function_exists('spip_version_compare')) { include_spip('plugins/installer'); } if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) { $ifnotexists = ' IF NOT EXISTS'; } else { /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */ $a = spip_sqlite_showtable($table, $serveur); if (isset($a['key']['KEY ' . $nom])) { return true; } } } $temporary = $temporary ? ' TEMPORARY' : ''; $q = "CREATE{$temporary} TABLE{$ifnotexists} {$nom} ({$query}" . ($keys ? ",{$keys}" : '') . ")\n"; return $q; }
/** * A partir des > 1.926 (i.e SPIP > 1.9.2), cette fonction gere les MAJ. * Se relancer soi-meme pour eviter l'interruption pendant une operation SQL * (qu'on espere pas trop longue chacune) * evidemment en ecrivant dans la meta a quel numero on en est. * * Cette fonction peut servir aux plugins qui doivent donner comme arguments: * 1. le numero de version courant (numero de version 1.2.3 ou entier) * 2. le numero de version a atteindre (numero de version 1.2.3 ou entier) * 3. le tableau des instructions de mise a jour a executer * Pour profiter du mecanisme de reprise sur interruption il faut de plus * 4. le nom de la meta permettant de retrouver tout ca * 5. la table des meta ou elle se trouve ($table_prefix . '_meta' par defaut) * (cf debut de fichier) * en cas d'echec, cette fonction retourne un tableau (etape,sous-etape) * sinon elle retourne un tableau vide * * les fonctions sql_xx appelees lors des maj sont supposees atomiques et ne sont pas relancees * en cas de timeout * mais les fonctions specifiques sont relancees jusqu'a ce qu'elles finissent * elles doivent donc s'assurer de progresser a chaque reprise * * http://doc.spip.org/@maj_while * * @param $installee * @param $cible * @param $maj * @param string $meta * @param string $table * @param string $redirect * @param bool $debut_page * @return array */ function maj_while($installee, $cible, $maj, $meta = '', $table = 'meta', $redirect = '', $debut_page = false) { # inclusions pour que les procedures d'upgrade disposent des fonctions de base include_spip('base/create'); include_spip('base/abstract_sql'); $trouver_table = charger_fonction('trouver_table', 'base'); include_spip('inc/plugin'); // pour spip_version_compare $n = 0; $time = time(); // definir le timeout qui peut etre utilise dans les fonctions // de maj qui durent trop longtemps define('_TIME_OUT', $time + _UPGRADE_TIME_OUT); reset($maj); while (list($v, ) = each($maj)) { // si une maj pour cette version if ($v == 'init' or spip_version_compare($v, $installee, '>') and spip_version_compare($v, $cible, '<=')) { if ($debut_page) { maj_debut_page($v, $meta, $table); } echo "MAJ {$v}"; $etape = serie_alter($v, $maj[$v], $meta, $table, $redirect); $trouver_table(''); // vider le cache des descriptions de table # echec sur une etape en cours ? # on sort if ($etape) { return array($v, $etape); } $n = time() - $time; spip_log("{$table} {$meta}: {$v} en {$n} secondes", 'maj.' . _LOG_INFO_IMPORTANTE); if ($meta) { ecrire_meta($meta, $installee = $v, 'oui', $table); } echo "<br />"; } if (time() >= _TIME_OUT) { relance_maj($meta, $table, $redirect); } } $trouver_table(''); // vider le cache des descriptions de table // indispensable pour les chgt de versions qui n'ecrivent pas en base // tant pis pour la redondance eventuelle avec ci-dessus if ($meta) { ecrire_meta($meta, $cible, 'oui', $table); } spip_log("MAJ terminee. {$meta}: {$installee}", 'maj.' . _LOG_INFO_IMPORTANTE); return array(); }