dolibarr/htdocs/admin/tools/export.php
Frédéric FRANCE 0ace4d500b
FIX: Remove always-true error checks in mysql dump export (#39339)
$errormsg is initialized to '' just above and nothing sets it before
these checks in the mysql branch, so PHPStan correctly flags both
negated conditions as always true (booleanNot.alwaysTrue). Unlike the
postgresql branch below, this is the first $what branch evaluated, so
there is no earlier code path that could have set $errormsg yet.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-07-31 21:34:51 +02:00

236 lines
8.4 KiB
PHP

<?php
/* Copyright (C) 2006-2014 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2021 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Anthony Berton <anthony.berton@bb2a.fr>
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/admin/tools/export.php
* \brief Page to export a database into a dump file
*/
// Load Dolibarr environment
require '../../main.inc.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*
* @var string $dolibarr_main_restrict_os_commands
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
$langs->load("admin");
$action = GETPOST('action', 'aZ09');
$what = GETPOST('what', 'alpha');
$export_type = GETPOST('export_type', 'alpha');
$file = dol_sanitizeFileName(GETPOST('filename_template', 'alpha'));
// Load variable for pagination
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$sortfield = GETPOST('sortfield', 'aZ09comma');
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
$page = 0;
} // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
$offset = $limit * $page;
if (!$sortorder) {
$sortorder = "DESC";
}
if (!$sortfield) {
$sortfield = "date";
}
if (!$user->admin) {
accessforbidden();
}
$errormsg = '';
$utils = new Utils($db);
/*
* Actions
*/
if ($file && !$what) {
//print DOL_URL_ROOT.'/dolibarr_export.php';
header("Location: ".DOL_URL_ROOT.'/admin/tools/dolibarr_export.php?msg='.urlencode($langs->trans("ErrorFieldRequired", $langs->transnoentities("ExportMethod"))).(GETPOSTINT('page_y') ? '&page_y='.GETPOSTINT('page_y') : ''));
exit;
}
if ($action == 'delete') {
$file = $conf->admin->dir_output.'/'.dol_sanitizeFileName(GETPOST('urlfile'));
$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 = '';
}
$_SESSION["commandbackuplastdone"] = '';
$_SESSION["commandbackuptorun"] = '';
$_SESSION["commandbackupresult"] = '';
// Increase limit of time. Works only if we are not in safe mode
$ExecTimeLimit = 600; // Set it to 0 to not use a forced time limit
if (!empty($ExecTimeLimit)) {
$err = error_reporting();
error_reporting(0); // Disable all errors
//error_reporting(E_ALL);
@set_time_limit($ExecTimeLimit); // Need more than 240 on Windows 7/64
error_reporting($err);
}
$MemoryLimit = 0;
if (!empty($MemoryLimit)) {
@ini_set('memory_limit', $MemoryLimit);
}
// We will send fake headers to avoid browser timeout when buffering
$time_start = time();
$outputdir = $conf->admin->dir_output.'/backup';
$result = dol_mkdir($outputdir);
$lowmemorydump = (int) (GETPOSTISSET("lowmemorydump") ? GETPOSTINT("lowmemorydump") : getDolGlobalInt('MAIN_LOW_MEMORY_DUMP'));
// MYSQL
if ($what == 'mysql') {
$cmddump = GETPOST("mysqldump", 'none'); // Do not sanitize here with 'alpha', will be sanitize later by dol_sanitizePathName and escapeshellarg
$cmddump = dol_sanitizePathName($cmddump); // Sanitize path
$cmddump = dol_string_nospecial($cmddump, '', array("|", ";", "<", ">", "&", "+")); // Sanitize command
$basenamecmddump = basename(str_replace('\\', '/', $cmddump));
// Add a fallback when we detect something wrong with the path of the dump command
if (preg_match('/\//', str_replace('\\', '/', $cmddump))) { // If command is a full path
if (!dol_is_file($cmddump)) { // And if file not reachable with its full path
$reg = array();
if (preg_match('/mysqldump(\.exe)?$/', $cmddump, $reg)) { // And if command ends with mysqldump
$cmddump = 'mysqldump'.(empty($reg[1]) ? '' : $reg[1]); // Then we try the command with no forced path
$langs->load("errors");
setEventMessage($langs->trans("WarningFullPathWasNotFoundSoWeUseAnAlternativeValue", $cmddump), 'warnings');
}
}
}
if ($cmddump) {
dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump, 'chaine', 0, '', 0);
}
$result = $utils->dumpDatabase(GETPOST('compression', 'alpha'), $what, 0, $file, 0, 0, $lowmemorydump);
$errormsg = $utils->error;
$_SESSION["commandbackuplastdone"] = $utils->result['commandbackuplastdone'];
$_SESSION["commandbackuptorun"] = $utils->result['commandbackuptorun'];
}
// MYSQL NO BIN
if ($what == 'mysqlnobin') {
$utils->dumpDatabase(GETPOST('compression', 'alpha'), $what, 0, $file, 0, 0, $lowmemorydump);
$errormsg = $utils->error;
$_SESSION["commandbackuplastdone"] = $utils->result['commandbackuplastdone'];
$_SESSION["commandbackuptorun"] = $utils->result['commandbackuptorun'];
}
// POSTGRESQL
if ($what == 'postgresql') {
$cmddump = GETPOST("postgresqldump", 'none'); // Do not sanitize here with 'alpha', will be sanitize later by dol_sanitizePathName and escapeshellarg
$cmddump = dol_sanitizePathName($cmddump);
$cmddump = dol_string_nospecial($cmddump, '', array("|", ";", "<", ">", "&", "+")); // Sanitize command
/* Not required, the command is output on screen but not ran for pgsql
if (!empty($dolibarr_main_restrict_os_commands))
{
$arrayofallowedcommand=explode(',', $dolibarr_main_restrict_os_commands);
$arrayofallowedcommand = array_map('trim', $arrayofallowedcommand);
dol_syslog("Command are restricted to ".$dolibarr_main_restrict_os_commands.". We check that one of this command is inside ".$cmddump);
$basenamecmddump = basename(str_replace('\\', '/', $cmddump));
if (! in_array($basenamecmddump, $arrayofallowedcommand)) // the provided command $cmddump must be an allowed command
{
$errormsg=$langs->trans('CommandIsNotInsideAllowedCommands');
}
} */
if (!$errormsg && $cmddump) {
dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump, 'chaine', 0, '', 0);
}
if (!$errormsg) {
$utils->dumpDatabase(GETPOST('compression', 'alpha'), $what, 0, $file, 0, 0, $lowmemorydump);
$errormsg = $utils->error;
$_SESSION["commandbackuplastdone"] = $utils->result['commandbackuplastdone'];
$_SESSION["commandbackuptorun"] = $utils->result['commandbackuptorun'];
}
$what = ''; // Clear to show message to run command
}
if ($errormsg) {
setEventMessages($langs->trans("Error")." : ".$errormsg, null, 'errors');
$resultstring = '';
$resultstring .= '<div class="error">'.$langs->trans("Error")." : ".$errormsg.'</div>';
$_SESSION["commandbackupresult"] = $resultstring;
} else {
if ($what) {
setEventMessages($langs->trans("BackupFileSuccessfullyCreated").'.<br>'.$langs->trans("YouCanDownloadBackupFile"), null, 'mesgs');
$resultstring = '<div class="ok">';
$resultstring .= $langs->trans("BackupFileSuccessfullyCreated").'.<br>';
$resultstring .= $langs->trans("YouCanDownloadBackupFile");
$resultstring .= '</div>';
$_SESSION["commandbackupresult"] = $resultstring;
}
/*else
{
setEventMessages($langs->trans("YouMustRunCommandFromCommandLineAfterLoginToUser",$dolibarr_main_db_user,$dolibarr_main_db_user), null, 'warnings');
}*/
}
/*
* View
*/
top_httphead();
$db->close();
// Redirect to backup page
header("Location: dolibarr_export.php".(GETPOSTINT('page_y') ? '?page_y='.GETPOSTINT('page_y') : ''));
exit();