From 0a17e6bfd5adc6bc1bfc4dc3a99c264b6918cb1f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Sep 2019 22:39:24 +0200 Subject: [PATCH] FIX Several pb in export of documents FIX Must escape shell FIX Must exclude logs and some dirs for compressed backup FIX gzip and bzip2 must use option -f --- htdocs/admin/tools/dolibarr_export.php | 20 +++++++++++---- htdocs/admin/tools/export_files.php | 34 ++++++++++++++++---------- htdocs/core/class/utils.class.php | 24 +++++++++--------- htdocs/core/lib/files.lib.php | 28 +++++++++++++++------ 4 files changed, 70 insertions(+), 36 deletions(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index c06314daa9a..0bef19dde56 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -50,10 +50,20 @@ if (! $user->admin) if ($action == 'delete') { - $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); - $ret=dol_delete_file($file, 1); - if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); - else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); + if (preg_match('/^backup\//', GETPOST('urlfile', 'alpha'))) + { + $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); + $ret=dol_delete_file($file, 1); + if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); + else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); + } + else + { + $file=$conf->admin->dir_output.'/documents/'.basename(GETPOST('urlfile', 'alpha')); + $ret=dol_delete_file($file, 1); + if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); + else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); + } $action=''; } @@ -577,7 +587,7 @@ print "\n"; ?>
-
" id="buttonGo" />

diff --git a/htdocs/admin/tools/export_files.php b/htdocs/admin/tools/export_files.php index c1ddedfea53..4f9e8b933d2 100644 --- a/htdocs/admin/tools/export_files.php +++ b/htdocs/admin/tools/export_files.php @@ -112,21 +112,27 @@ $utils = new Utils($db); if ($compression == 'zip') { - $ret = dol_compress_dir(DOL_DATA_ROOT, $outputdir."/".$file, $compression); + $ret = dol_compress_dir(DOL_DATA_ROOT, $outputdir."/".$file, $compression, '/(\.log|\/temp\/|documents\/admin\/documents\/)/'); if ($ret < 0) { - $errormsg = $langs->trans("ErrorFailedToWriteInDir", $outputfile); + $errormsg = $langs->trans("ErrorFailedToWriteInDir", $outputdir); } } elseif (in_array($compression, array('gz', 'bz'))) { - $file = substr($file, 0, strrpos($file, '.')); + $userlogin = ($user->login ? $user->login : 'unknown'); + + $outputfile = $conf->admin->dir_temp.'/export_files.'.$userlogin.'.out'; // File used with popen method + + $file = substr($file, 0, strrpos($file, '.')); $file .= '.tar'; - $cmd = 'tar -cf '.$outputdir."/".$file." --exclude=documents/admin/documents -C ".DOL_DATA_ROOT." ".DOL_DATA_ROOT."/../documents/"; - exec($cmd, $out, $retval); - //var_dump($cmd, DOL_DATA_ROOT);exit; - - if ($retval != 0) + // We also exclude '/temp/' dir and 'documents/admin/documents' + $cmd = "tar -cf ".$outputdir."/".$file." --exclude-vcs --exclude 'temp' --exclude 'dolibarr.log' --exclude='documents/admin/documents' -C ".dirname(DOL_DATA_ROOT)." ".basename(DOL_DATA_ROOT); + + $result = $utils->executeCLI($cmd, $outputfile); + + $retval = $result['error']; + if ($result['result'] || ! empty($retval)) { $langs->load("errors"); dol_syslog("Documents tar retval after exec=".$retval, LOG_ERR); @@ -136,15 +142,17 @@ elseif (in_array($compression, array('gz', 'bz'))) { if ($compression == 'gz') { - $cmd = "gzip " . $outputdir."/".$file; + $cmd = "gzip -f " . $outputdir."/".$file; } if ($compression == 'bz') { - $cmd = "bzip2 " . $outputdir."/".$file; + $cmd = "bzip2 -f " . $outputdir."/".$file; } - - exec($cmd, $out, $retval); - if ($retval != 0) + + $result = $utils->executeCLI($cmd, $outputfile); + + $retval = $result['error']; + if ($result['result'] || ! empty($retval)) { $errormsg = 'Error '.$compression.' generation return '.$retval; unlink($outputdir."/".$file); diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index f86d6570e5c..86eff6613c1 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -316,27 +316,29 @@ class Utils // TODO Replace with executeCLI function if ($execmethod == 1) { - exec($fullcommandclear, $readt, $retval); - $result = $retval; + $output_arr = array(); $retval = null; + exec($fullcommandclear, $output_arr, $retval); if ($retval != 0) { $langs->load("errors"); dol_syslog("Datadump retval after exec=".$retval, LOG_ERR); - $error = 'Error '.$retval; + $errormsg = 'Error '.$retval; $ok=0; } else { $i=0; - if (!empty($readt)) - foreach($readt as $key=>$read) + if (!empty($output_arr)) { - $i++; // output line number - if ($i == 1 && preg_match('/Warning.*Using a password/i', $read)) continue; - fwrite($handle, $read.($execmethod == 2 ? '' : "\n")); - if (preg_match('/'.preg_quote('-- Dump completed').'/i', $read)) $ok=1; - elseif (preg_match('/'.preg_quote('SET SQL_NOTES=@OLD_SQL_NOTES').'/i', $read)) $ok=1; + foreach($output_arr as $key => $read) + { + $i++; // output line number + if ($i == 1 && preg_match('/Warning.*Using a password/i', $read)) continue; + fwrite($handle, $read.($execmethod == 2 ? '' : "\n")); + if (preg_match('/'.preg_quote('-- Dump completed').'/i', $read)) $ok=1; + elseif (preg_match('/'.preg_quote('SET SQL_NOTES=@OLD_SQL_NOTES').'/i', $read)) $ok=1; + } } } } @@ -534,6 +536,7 @@ class Utils if ($execmethod == 1) { + $retval = null; exec($command, $output_arr, $retval); $result = $retval; if ($retval != 0) @@ -545,7 +548,6 @@ class Utils } if ($execmethod == 2) // With this method, there is no way to get the return code, only output { - $ok=0; $handle = fopen($outputfile, 'w+b'); if ($handle) { diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index c6a5cb14426..d2aee3e6a30 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1221,9 +1221,12 @@ function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, } } } - else dol_syslog("Failed to remove file ".$filename, LOG_WARNING); - // TODO Failure to remove can be because file was already removed or because of permission - // If error because it does not exists, we should return true, and we should return false if this is a permission problem + else + { + dol_syslog("Failed to remove file ".$filename, LOG_WARNING); + // TODO Failure to remove can be because file was already removed or because of permission + // If error because it does not exists, we should return true, and we should return false if this is a permission problem + } } } else dol_syslog("No files to delete found", LOG_DEBUG); @@ -2062,9 +2065,10 @@ function dol_uncompress($inputfile, $outputdir) * @param string $inputdir Source dir name * @param string $outputfile Target file name (output directory must exists and be writable) * @param string $mode 'zip' + * @param string $excludefiles A regex pattern. For example: '/\.log$|\/temp\//' * @return int <0 if KO, >0 if OK */ -function dol_compress_dir($inputdir, $outputfile, $mode = "zip") +function dol_compress_dir($inputdir, $outputfile, $mode = "zip", $excludefiles = '') { $foundhandler=0; @@ -2095,6 +2099,7 @@ function dol_compress_dir($inputdir, $outputfile, $mode = "zip") return 1; } else*/ + //if (class_exists('ZipArchive') && ! empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_COMPRESS)) if (class_exists('ZipArchive')) { $foundhandler=1; @@ -2102,6 +2107,13 @@ function dol_compress_dir($inputdir, $outputfile, $mode = "zip") // Initialize archive object $zip = new ZipArchive(); $result = $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE); + if (! $result) + { + global $langs, $errormsg; + $langs->load("errors"); + $errormsg=$langs->trans("ErrorFailedToWriteInFile", $outputfile); + return -4; + } // Create recursive directory iterator /** @var SplFileInfo[] $files */ @@ -2118,9 +2130,11 @@ function dol_compress_dir($inputdir, $outputfile, $mode = "zip") // Get real and relative path for current file $filePath = $file->getRealPath(); $relativePath = substr($filePath, strlen($inputdir) + 1); - - // Add current file to archive - $zip->addFile($filePath, $relativePath); + if (empty($excludefiles) || ! preg_match($excludefiles, $filePath)) + { + // Add current file to archive + $zip->addFile($filePath, $relativePath); + } } }