Source for file class.data.php
Documentation is available at class.data.php
* Fichier de classe pour les backups
* LODEL - Logiciel d'Edition ELectronique.
* Home page: http://www.lodel.org
* E-Mail: lodel@lodel.org
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* @author Ghislain Picard
* @copyright 2001-2002, Ghislain Picard, Marin Dacos
* @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
* @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
* @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
* @licence http://www.gnu.org/copyleft/gpl.html
* @since Fichier ajouté depuis la version 0.8
* @version CVS:$Id: class.data.php 4468 2008-07-17 14:13:31Z mignot $
* Classe de logique permettant de gérer les backup et import de données et de ME
* @author Sophie Malafosse
* @author Pierre-Alain Mignot
* @copyright 2001-2002, Ghislain Picard, Marin Dacos
* @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
* @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
* @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
* @licence http://www.gnu.org/copyleft/gpl.html
* @since Classe ajoutée depuis la version 0.8
* @see backupfunc.php, pma/sql-modified.php
* Prefix du fichier (pour l'import de ME et l'import de données)
* Expression utilisée pour filtrer les fichiers pour un import
* Extension du fichier d'import
* Tables correspondantes au ME
* Tables enregistrées lors du parsage du fichier XML
* Structure de la base XML
* Structure de la base SQL
* Liste des tables différentes entre SQL/XML
* Liste des champs différents entre chaque table SQL/XML
* Donnés récupérées dans le XML
* Tables à créer (présentes dans le XML et non dans la base)
* Tableau des requêtes à effectuer
* Tableau des champs absent du XML mais présent dans la base
* Tableau des types (entité ou entrée) n'ayant pas trouvé leur équivalent dans le XML
* Interdit l'accès aux utilisateurs qui ne sont pas ADMIN
|| ($GLOBALS['lodeluser']['rights'] == LEVEL_ADMIN && ($GLOBALS['context']['do'] == 'import'
|| $GLOBALS['context']['do'] == 'backup'
|| $GLOBALS['context']['do'] == 'importmodel'
|| $GLOBALS['context']['do'] == 'importxmlmodel'))) {
die("ERROR: you don't have the right to access this feature");
* Importation des données
* Cette fonction importe les données issus d'un backup de lodel : le dump SQL, les fichiers associés (si ils ont été sauvegardés).
* @param array $context le contexte passé par référence
* @param array $error les éventuelles erreur, passées par référence
$context['importdir'] = $GLOBALS['importdir'];
// les répertoires d'import
$context['importdirs'] = array('CACHE');
if ($context['importdir']) {
$context['importdirs'][] = $context['importdir'];
if ($file) { // Si on a bien spécifié un fichier
set_time_limit(120); //pas d'effet si safe_mode on ; on met le temps à unlimited
//noms des répertoires acceptés
$accepteddirs = array('lodel/txt', 'lodel/rtf', 'lodel/sources', 'lodel/icons', 'docannexe/file', 'docannexe/image');
require_once 'backupfunc.php';
$err = $error['error_extract'] = 'extract';
#require_once 'connect.php';
// drop les tables existantes
//$db->execute(lq('DROP TABLE IF EXISTS '. join(',', $GLOBALS['lodelsitetables']))) or dberror();
$error['error_execute_dump'] = $err = $db->errormsg();
require_once 'cachefunc.php';
// verifie les .htaccess dans le CACHE
$error['file'] = 'unknown_file';
* Fait un dump de la base de données du site et si indiqué sauve aussi les fichiers annexes et source.
* @param array $context le contexte passé par référence
* @param array $error les éventuelles erreurs, passées par référence
$context['importdir'] = $GLOBALS['importdir'];
if ($context['backup']) { // si on a demandé le backup
require_once 'backupfunc.php';
$site = $context['site'];
$outfile = "site-$site.sql";
//$uselodelprefix = true; // ? NON UTILISE
$GLOBALS['tmpdir'] = $tmpdir = tmpdir();
$fh = fopen($tmpdir. '/'. $outfile, 'w');
die ("ERROR: unable to open a temporary file in write mode");
$this->_dump($site, $tmpdir. '/'. $outfile, $errors, $fh);
// verifie que le fichier SQL n'est pas vide
if (filesize($tmpdir. '/'. $outfile) <= 0) {
$error['mysql'] = 'dump_failed';
// zip le site et ajoute la base
$archivetmp = tempnam($tmpdir, 'lodeldump_'). '.zip';
$archivefilename = "site-$site-". date("dmy"). '.zip';
// fichiers à exclure de l'archive
$GLOBALS['excludes'] = $excludes = array('lodel/sources/.htaccess',
'docannexe/fichier/.htaccess',
'docannexe/image/index.html',
'docannexe/image/tmpdir-\*',
$sitedirs = array('lodel/icons', 'lodel/sources', 'docannexe');
// si sauvegarde des répertoires demandée (en + de la base)
if (!$context['sqlonly']) {
//verifie que les repertoires sont accessibles en lecture
foreach ($sitedirs as $sitedir) {
// initialise $error pour affichage dans le template backup.html
// conversion en chaîne pour ligne de commande
if ($zipcmd && $zipcmd != 'pclzip') { //Commande ZIP
if (!$context['sqlonly']) {
die ("ERROR: can't chdir in SITEROOT");
$prefixdir = $tmpdir[0] == "/" ? '' : 'lodel/admin/';
$excludefiles = $excludes ? " -x ". join(" -x ", $excludes) : "";
system($zipcmd. " -q $prefixdir$archivetmp -r $dirs $excludefiles");
if (!chdir("lodel/admin")) {
die ("ERROR: can't chdir in lodel/admin");
system($zipcmd. " -q -g $archivetmp -j $tmpdir/$outfile");
system($zipcmd. " -q $archivetmp -j $tmpdir/$outfile");
} else { // Comande PCLZIP
require_once 'pclzip/pclzip.lib.php';
$archive = new PclZip($archivetmp);
if (!$context['sqlonly']) {
// function to exclude files and rename directories
function preadd($p_event, &$p_header)
global $excludes, $tmpdir; // that's bad to depend on globals like that
$p_header['stored_filename'] = preg_replace("/^". preg_quote($tmpdir, "/"). "\//", "", $p_header['stored_filename']);
foreach ($excludes as $exclude) {
// end of function to exclude files
// ajout de la racine du site aux chemins des répertoires
for($i= 0 ; $i< count($good_dirs) ; $i++ ){
$good_dirs[$i] = SITEROOT. $good_dirs[$i];
// ajout du fichier sql issu du dump de la base du site
$archive->create($good_dirs,
} // end of pclzip option
die ("ERROR: the zip command or library does not produce any output");
@unlink($tmpdir. '/'. $outfile); // delete the sql file
if($error) { // Pour avoir accès aux erreurs dans les templates
$context['error'] = $error;}
if (operation($context['operation'], $archivetmp, $archivefilename, $context)) {
* Backup global des données. Seulement autorisé pour un admin lodel
* Cela crée un backup de la base principale mais aussi de tous les sites
* @param array $context le contexte passé par référence
* @param array $error les éventuelles erreurs, passées par référence
* @return le nom du template utilisé pour cette action : backup
* @todo Trouver une alternative à la commande système tar
if($context['lodeluser']['rights'] < 128) {
die('ERROR : You d\'ont have the rights to use this feature');
require_once 'backupfunc.php';
$context['importdir'] = $GLOBALS['importdir'];
$operation = $context['operation'];
if ($context['backup']) {
// il faut locker la base parce que le dump ne doit pas se faire en meme temps que quelqu'un ecrit un fichier.
$dirlocked = tempnam('/tmp', 'lodeldump_'). '.dir'; // this allow to be sure to have a unique dir.
$fh = fopen($dirlocked. '/'. $outfile, 'w');
die ("ERROR: unable to open a temporary file in write mode");
// save the main database
die("ERROR: unable to write in the temporary file");
$GLOBALS['currentprefix'] = '#_MTP_';
require_once 'backupfunc.php';
// Trouve les sites a inclure au backup.
$result = $db->execute(lq('SELECT name, path FROM #_MTP_sites WHERE status > -32')) or dberror();
$GLOBALS['currentprefix'] = '#_TP_';
$name = $result->fields['name'];
$sitepath = $result->fields['path'];
if (fputs($fh, 'DROP DATABASE IF EXISTS '. $name. ";\nCREATE DATABASE ". $name. ";USE ". $name. ";\n") === FALSE) {
die("ERROR: unable to write in the temporary file");
$this->_dump($name, $outfile, $errors, $fh);
if (!$context['sqlonly']) {
if ($sitepath == '/') { $root = ''; } // site à la racine
else { $root = $name . '/'; }
// liste des répertoires du site à archiver
$sitedirs = array('lodel/icons', 'lodel/sources', 'docannexe');
//verifie que les repertoires sont accessibles en lecture
foreach ($sitedirs as $sitedir) {
if(is_readable($root . $sitedir)){ $dirtotar[] = $root . $sitedir;}
else { $bad_dirs[] = $root . $sitedir;}
$db->selectDB(DATABASE); //selectionne la base principale.
// tar les sites et ajoute la base
$archivetmp = tempnam('/tmp', 'lodeldump_');
$archivefilename = 'lodel-'. date('dmy'). '.tar.gz';
// Attention ce qui suit ne fonctionnera que sous Linux
system("tar czf $archivetmp ". join(' ', $dirtotar). " -C $dirlocked $outfile") !== false or die ("impossible d'executer tar");
unlink($dirlocked. '/'. $outfile);
chdir('lodeladmin'. ($GLOBALS['version'] ? '-'. $GLOBALS['version'] : ''));
if (operation($operation, $archivetmp, $archivefilename, $context)) {
//$context['error'] = $errors;
|