93b01283f828e5b5987bf3bcd77f2bacdae8ded6
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2020 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * API permettant la manipulation des sauvegardes
16 * @package SPIP\Dump\API
19 if (!defined('_ECRIRE_INC_VERSION')) {
25 * Répertoire de sauvegarde
27 * Crée et retourne le chemin du répertoire de sauvegarde
33 function dump_repertoire() {
34 $repertoire = _DIR_DUMP
;
35 if (!@file_exists
($repertoire)
36 and !$repertoire = sous_repertoire(_DIR_DUMP
, '', false, true)
38 $repertoire = preg_replace(',' . _DIR_TMP
. ',', '', _DIR_DUMP
);
39 $repertoire = sous_repertoire(_DIR_TMP
, $repertoire);
47 * Nom du fichier de sauvegarde
49 * la fourniture de l'extension permet de vérifier que le nom n'existe pas déjà.
51 * @param string $dir Chemin de stockage du fichier
52 * @param string $extension Extension du fichier de sauvegarde
55 function dump_nom_fichier($dir, $extension = 'sqlite') {
56 include_spip('inc/texte');
58 if (isset($GLOBALS['meta']['nom_site'])) {
59 $site = typo($GLOBALS['meta']['nom_site']); // extraire_multi
60 $site = couper(translitteration(trim($site)), 30, '');
61 $site = preg_replace(array(',\W,is', ',_(?=_),', ',_$,'), array('_', '', ''), $site);
64 $site .= '_' . date('Ymd');
68 while (file_exists($dir . $nom . ".$extension")) {
69 $nom = $site . sprintf('_%03d', ++
$cpt);
72 return $nom . ".$extension";
76 * Détermine le type de serveur de sauvegarde,
81 function dump_type_serveur() {
82 // chercher si sqlite2 ou 3 est disponible
83 include_spip('req/sqlite3');
84 if (function_exists('spip_versions_sqlite3') and spip_versions_sqlite3()) {
87 if (function_exists('spip_versions_sqlite3')) {
88 spip_log("ERREUR sqlite3 n'est pas correctement installé : "
89 ."extension_loaded('pdo')=".extension_loaded('pdo')
90 ." extension_loaded('pdo_sqlite')=".extension_loaded('pdo_sqlite'),
94 include_spip('req/sqlite2');
95 if (function_exists('spip_versions_sqlite2') and spip_versions_sqlite2()) {
103 * Conteneur pour les arguments de la connexion
105 * Si on passe $args, les arguments de la connexion sont memorisés.
106 * Renvoie toujours les derniers arguments memorisés.
108 * @staticvar array $connect_args Pour stocker le premier conteneur
112 function dump_serveur($args = null) {
113 static $connect_args = null;
115 $connect_args = $args;
118 return $connect_args;
121 function dump_connect_args($archive) {
122 if (!$type_serveur = dump_type_serveur()) {
126 return array(dirname($archive), '', '', '', basename($archive, '.sqlite'), $type_serveur, 'spip');
130 * Initialiser un dump
132 * @param string $status_file Fichier contenant les informations serialisees sur le statut de l'export
133 * @param string $archive Nom de l'archive (stockee dans le fichier de statut)
134 * @param array $tables Liste des tables a exporter (autocaculee par defaut)
135 * @param array $where Condition sur l'export
136 * @param string $action Pour differencier la sauvegarde de l'import
137 * @return bool/string
139 function dump_init($status_file, $archive, $tables = null, $where = array(), $action = 'sauvegarde') {
140 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
142 if (lire_fichier($status_file, $status)
143 and $status = unserialize($status)
144 and $status['etape'] !== 'fini'
145 and filemtime($status_file) >= time() - 120
147 // si le fichier status est trop vieux c'est un abandon
148 return _T('dump:erreur_' . $action . '_deja_en_cours');
151 if (!$type_serveur = dump_type_serveur()) {
152 return _T('dump:erreur_sqlite_indisponible');
156 list($tables, ) = base_liste_table_for_dump(lister_tables_noexport());
158 $status = array('tables' => $tables, 'where' => $where, 'archive' => $archive);
160 $status['connect'] = dump_connect_args($archive);
161 dump_serveur($status['connect']);
162 if (!spip_connect('dump')) {
163 return _T('dump:erreur_creation_base_sqlite');
166 // la constante sert a verifier qu'on utilise bien le connect/dump du plugin,
167 // et pas une base externe homonyme
168 if (!defined('_DUMP_SERVEUR_OK')) {
169 return _T('erreur_connect_dump', array('dump' => 'dump'));
172 $status['etape'] = 'init';
174 if (!ecrire_fichier($status_file, serialize($status))) {
175 return _T('dump:avis_probleme_ecriture_fichier', array('fichier' => $status_file));
182 * Afficher l'avancement de la copie
184 * @staticvar int $etape Nombre de fois ou on est passe dans cette foncion
185 * @param <type> $courant Flag pour indiquer si c'est la table sur laquelle on travaille actuellement
186 * @param <type> $total Nombre total de tables
187 * @param <type> $table Nom de la table
189 function dump_afficher_progres($courant, $total, $table) {
191 if (unique($table)) {
192 if ($total < 0 or !is_numeric($total)) {
193 echo '<br /><strong>' . $etape . '. ' . "</strong>$table ";
195 echo '<br /><strong>' . $etape . '. ' . "$table</strong> " . ($courant ?
" <i>($courant)</i> " : '');
199 if (is_numeric($total) and $total >= 0) {
202 echo '(' . (-intval($total)) . ')';
208 * Écrire le js pour relancer la procédure de dump
210 * @param string $redirect URL de la prochaine etape du dump
211 * @return string Code HTML de redirection
213 function dump_relance($redirect) {
214 // si Javascript est dispo, anticiper le Time-out
215 return "<script language=\"JavaScript\" type=\"text/javascript\">window.setTimeout('location.href=\"$redirect\";',300);</script>\n";
220 * Marquer la procédure de dump comme finie
222 * @param string $status_file
223 * Fichier qui mémorise les infos utiles concernant la sauvegarde en cours
224 * @param string $action
225 * Type d'action supplémentaire à réaliser :
227 * - restaurer : supprimer la structure qui était stockée dans le dump
228 * - 'auvegarder : stocker dans le dump la structure de la base source
230 function dump_end($status_file, $action = '') {
231 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
232 if (!lire_fichier($status_file, $status)
233 or !$status = unserialize($status)
240 // supprimer la structure qui etait stockee dans le dump
241 sql_delete('spip_meta', "nom='dump_structure_temp'");
244 // stocker dans le dump la structure de la base source
245 $structure = array();
246 foreach ($status['tables_copiees'] as $t => $n) {
247 $structure[$t] = sql_showtable($t, true);
249 dump_serveur($status['connect']);
250 spip_connect('dump');
251 // si spip_meta n'a pas ete backup elle n'est pas dans le dump, il faut la creer pour y stocker cette meta
252 if (!sql_showtable('spip_meta', true, 'dump')) {
253 $desc = sql_showtable('spip_meta', true);
254 sql_create('spip_meta', $desc['field'], $desc['key'], false, false, 'dump');
256 sql_delete('spip_meta', "nom='dump_structure_temp'", 'dump'); #enlever une vieille structure deja la, au cas ou
259 array('nom' => 'dump_structure_temp', 'valeur' => serialize($structure), 'impt' => 'non'),
266 $status['etape'] = 'fini';
267 ecrire_fichier($status_file, serialize($status));
271 * Lister les fichiers de sauvegarde existant dans un repertoire
272 * trie par nom, date ou taille
274 * @param string $dir Repertoire de sauvegarde
275 * @param string $tri Tri pour recuperer les fichiers
276 * @param string $extension Extension des fichiers de sauvegarde
277 * @param int $limit Nombre max de fichiers listes
280 function dump_lister_sauvegardes($dir, $tri = 'nom', $extension = 'sqlite', $limit = 100) {
281 $liste_dump = preg_files($dir, '\.' . $extension . '$', $limit, false);
284 $tn = $tl = $tt = $td = array();
285 foreach ($liste_dump as $fichier) {
286 $d = filemtime($fichier);
287 $t = filesize($fichier);
288 $fichier = substr($fichier, $n);
289 $tl[] = array('fichier' => $fichier, 'taille' => $t, 'date' => $d);
294 if ($tri == 'taille') {
295 array_multisort($tt, SORT_ASC
, $tl);
296 } elseif ($tri == 'date') {
297 array_multisort($td, SORT_ASC
, $tl);
299 array_multisort($tn, SORT_ASC
, $tl);
306 * Extraire le statut contenu dans un fichier
308 * @param $status_file Nom du fichier stocke dans _DIR_TMP
311 function dump_lire_status($status_file) {
312 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
313 if (!lire_fichier($status_file, $status)
314 or !$status = unserialize($status)
323 * Verifier qu'un sauvegarde est finie
325 * @param $status_file Nom du fichier stocke dans _DIR_TMP
326 * @return string Chaine non vide s'il reste des choses a faire
328 function dump_verifie_sauvegarde_finie($status_file) {
329 if (!$status = dump_lire_status($status_file)
330 or $status['etape'] !== 'fini'
339 * Recuperer le nom du fichier d'archivage qui est memorise dans le fichier de statut
341 * @param $status_file Nom du fichier stocke dans _DIR_TMP
342 * @return string Nom ou chaine vide si on a un probleme
344 function dump_nom_sauvegarde($status_file) {
345 if (!$status = dump_lire_status($status_file)
346 or !file_exists($f = $status['archive'] . '.sqlite')
355 * Recuperer la taille du fichier de sauvegarde
357 * @param $status_file Nom du fichier stocke dans _DIR_TMP
358 * @return string/int Taille ou Chaine vide en cas de probleme
360 function dump_taille_sauvegarde($status_file) {
361 if (!$f = dump_nom_sauvegarde($status_file)
362 or !$s = filesize($f)
371 * Recuperer la date de derniere modification du fichier de sauvegarde
373 * @param $status_file Nom du fichier stocke dans _DIR_TMP
374 * @return string/int Date ou Chaine vide en cas de probleme
376 function dump_date_sauvegarde($status_file) {
377 if (!$f = dump_nom_sauvegarde($status_file)
378 or !$d = filemtime($f)
383 return date('Y-m-d', $d);