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
This commit is contained in:
Laurent Destailleur 2019-09-03 22:39:24 +02:00 committed by atm-greg
parent f4df3d01b2
commit 82ace4b4ef
4 changed files with 520 additions and 372 deletions

View File

@ -49,11 +49,21 @@ if (! $user->admin)
*/ */
if ($action == 'delete') if ($action == 'delete')
{
if (preg_match('/^backup\//', GETPOST('urlfile', 'alpha')))
{ {
$file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha'));
$ret=dol_delete_file($file, 1); $ret=dol_delete_file($file, 1);
if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); 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=''; $action='';
} }
@ -113,7 +123,7 @@ jQuery(document).ready(function() {
print load_fiche_titre($langs->trans("Backup"), '', 'title_setup'); print load_fiche_titre($langs->trans("Backup"), '', 'title_setup');
//print_barre_liste($langs->trans("Backup"), '', '', '', '', '', $langs->trans("BackupDesc",DOL_DATA_ROOT), 0, 0, 'title_setup'); //print_barre_liste($langs->trans("Backup"), '', '', '', '', '', $langs->trans("BackupDesc",DOL_DATA_ROOT), 0, 0, 'title_setup');
print '<div class="center">'; print '<div class="center opacitymedium">';
print $langs->trans("BackupDesc", DOL_DATA_ROOT); print $langs->trans("BackupDesc", DOL_DATA_ROOT);
print '</div>'; print '</div>';
print '<br>'; print '<br>';
@ -211,6 +221,7 @@ print '<tr '.$bc[false].'><td style="padding-left: 8px">';
<div class="formelementrow"><input type="checkbox" <div class="formelementrow"><input type="checkbox"
name="use_transaction" value="yes" id="checkbox_use_transaction" /> <label name="use_transaction" value="yes" id="checkbox_use_transaction" /> <label
for="checkbox_use_transaction"> <?php echo $langs->trans("UseTransactionnalMode"); ?></label> for="checkbox_use_transaction"> <?php echo $langs->trans("UseTransactionnalMode"); ?></label>
</div> </div>
<?php if (! empty($conf->global->MYSQL_OLD_OPTION_DISABLE_FK)) { ?> <?php if (! empty($conf->global->MYSQL_OLD_OPTION_DISABLE_FK)) { ?>
@ -233,14 +244,6 @@ print '<tr '.$bc[false].'><td style="padding-left: 8px">';
<option value="ORACLE">ORACLE</option> <option value="ORACLE">ORACLE</option>
<option value="POSTGRESQL">POSTGRESQL</option> <option value="POSTGRESQL">POSTGRESQL</option>
</select> <br> </select> <br>
<input type="checkbox" name="use_mysql_quick_param" value="yes" id="checkbox_use_quick" />
<label for="checkbox_use_quick">
<?php echo $form->textwithpicto(
$langs->trans('ExportUseMySQLQuickParameter'),
$langs->trans('ExportUseMySQLQuickParameterHelp')
); ?>
</label>
<br/>
<!-- <input type="checkbox" name="drop_database" value="yes" <!-- <input type="checkbox" name="drop_database" value="yes"
id="checkbox_drop_database" /> <label for="checkbox_drop_database"><?php echo $langs->trans("AddDropDatabase"); ?></label> id="checkbox_drop_database" /> <label for="checkbox_drop_database"><?php echo $langs->trans("AddDropDatabase"); ?></label>
--> -->
@ -453,8 +456,10 @@ print "\n";
<br> <br>
<div align="center"><input type="submit" class="button" <div class="center">
value="<?php echo $langs->trans("GenerateBackup") ?>" id="buttonGo" /><br> <input type="submit" class="button reposition" value="<?php echo $langs->trans("GenerateBackup") ?>" id="buttonGo">
<input type="hidden" name="page_y" value="<?php echo GETPOST('page_y', 'int'); ?>">
<br>
<br> <br>
<?php <?php
@ -466,7 +471,7 @@ if (! empty($_SESSION["commandbackuplastdone"]))
//print $paramclear; //print $paramclear;
// Now run command and show result // Now show result
print '<b>'.$langs->trans("BackupResult").':</b> '; print '<b>'.$langs->trans("BackupResult").':</b> ';
print $_SESSION["commandbackupresult"]; print $_SESSION["commandbackupresult"];
@ -582,7 +587,7 @@ print "\n";
?> ?>
<br> <br>
<div align="center"><input type="submit" class="button" <div class="center"><input type="submit" class="button reposition"
value="<?php echo $langs->trans("GenerateBackup") ?>" id="buttonGo" /><br> value="<?php echo $langs->trans("GenerateBackup") ?>" id="buttonGo" /><br>
<br> <br>
</div> </div>
@ -605,9 +610,6 @@ print '<br>';
</fieldset> </fieldset>
</form> </form>
<?php <?php
// End of page // End of page

View File

@ -112,21 +112,27 @@ $utils = new Utils($db);
if ($compression == 'zip') 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) if ($ret < 0)
{ {
$errormsg = $langs->trans("ErrorFailedToWriteInDir",$outputfile); $errormsg = $langs->trans("ErrorFailedToWriteInDir", $outputdir);
} }
} }
elseif (in_array($compression, array('gz', 'bz'))) elseif (in_array($compression, array('gz', 'bz')))
{ {
$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 = substr($file, 0, strrpos($file, '.'));
$file .= '.tar'; $file .= '.tar';
$cmd = 'tar -cf '.$outputdir."/".$file." --exclude=documents/admin/documents -C ".DOL_DATA_ROOT." ".DOL_DATA_ROOT."/../documents/"; // We also exclude '/temp/' dir and 'documents/admin/documents'
exec($cmd, $out, $retval); $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);
//var_dump($cmd, DOL_DATA_ROOT);exit;
if ($retval != 0) $result = $utils->executeCLI($cmd, $outputfile);
$retval = $result['error'];
if ($result['result'] || ! empty($retval))
{ {
$langs->load("errors"); $langs->load("errors");
dol_syslog("Documents tar retval after exec=".$retval, LOG_ERR); dol_syslog("Documents tar retval after exec=".$retval, LOG_ERR);
@ -136,15 +142,17 @@ elseif (in_array($compression, array('gz', 'bz')))
{ {
if ($compression == 'gz') if ($compression == 'gz')
{ {
$cmd = "gzip " . $outputdir."/".$file; $cmd = "gzip -f " . $outputdir."/".$file;
} }
if ($compression == 'bz') if ($compression == 'bz')
{ {
$cmd = "bzip2 " . $outputdir."/".$file; $cmd = "bzip2 -f " . $outputdir."/".$file;
} }
exec($cmd, $out, $retval); $result = $utils->executeCLI($cmd, $outputfile);
if ($retval != 0)
$retval = $result['error'];
if ($result['result'] || ! empty($retval))
{ {
$errormsg = 'Error '.$compression.' generation return '.$retval; $errormsg = 'Error '.$compression.' generation return '.$retval;
unlink($outputdir."/".$file); unlink($outputdir."/".$file);
@ -166,4 +174,3 @@ header("Location: dolibarr_export.php");
$time_end = time(); $time_end = time();
$db->close(); $db->close();

View File

@ -32,15 +32,15 @@ class Utils
*/ */
public $db; public $db;
var $output; // Used by Cron method to return message public $output; // Used by Cron method to return message
var $result; // Used by Cron method to return data public $result; // Used by Cron method to return data
/** /**
* Constructor * Constructor
* *
* @param DoliDB $db Database handler * @param DoliDB $db Database handler
*/ */
function __construct($db) public function __construct($db)
{ {
$this->db = $db; $this->db = $db;
} }
@ -54,7 +54,7 @@ class Utils
* @param int $nbsecondsold Nb of seconds old to accept deletion of a directory if $choice is 'tempfilesold' * @param int $nbsecondsold Nb of seconds old to accept deletion of a directory if $choice is 'tempfilesold'
* @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK) * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
*/ */
function purgeFiles($choice = 'tempfilesold', $nbsecondsold = 86400) public function purgeFiles($choice = 'tempfilesold', $nbsecondsold = 86400)
{ {
global $conf, $langs, $dolibarr_main_data_root; global $conf, $langs, $dolibarr_main_data_root;
@ -193,7 +193,7 @@ class Utils
* @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method
* @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK) * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
*/ */
function dumpDatabase($compression='none', $type='auto', $usedefault=1, $file='auto', $keeplastnfiles=0, $execmethod=0) public function dumpDatabase($compression = 'none', $type = 'auto', $usedefault = 1, $file = 'auto', $keeplastnfiles = 0, $execmethod = 0)
{ {
global $db, $conf, $langs, $dolibarr_main_data_root; global $db, $conf, $langs, $dolibarr_main_data_root;
global $dolibarr_main_db_name, $dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_port, $dolibarr_main_db_pass; global $dolibarr_main_db_name, $dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_port, $dolibarr_main_db_pass;
@ -262,7 +262,6 @@ class Utils
if (GETPOST("disable_fk", "alpha") || $usedefault) $param.=" -K"; if (GETPOST("disable_fk", "alpha") || $usedefault) $param.=" -K";
if (GETPOST("sql_compat", "alpha") && GETPOST("sql_compat", "alpha") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat", "alpha")); if (GETPOST("sql_compat", "alpha") && GETPOST("sql_compat", "alpha") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat", "alpha"));
if (GETPOST("drop_database", "alpha")) $param.=" --add-drop-database"; if (GETPOST("drop_database", "alpha")) $param.=" --add-drop-database";
if (GETPOST("use_mysql_quick_param", "alpha"))$param.=" --quick";
if (GETPOST("sql_structure", "alpha") || $usedefault) if (GETPOST("sql_structure", "alpha") || $usedefault)
{ {
if (GETPOST("drop", "alpha") || $usedefault) $param.=" --add-drop-table=TRUE"; if (GETPOST("drop", "alpha") || $usedefault) $param.=" --add-drop-table=TRUE";
@ -317,21 +316,22 @@ class Utils
// TODO Replace with executeCLI function // TODO Replace with executeCLI function
if ($execmethod == 1) if ($execmethod == 1)
{ {
exec($fullcommandclear, $readt, $retval); $output_arr = array(); $retval = null;
$result = $retval; exec($fullcommandclear, $output_arr, $retval);
if ($retval != 0) if ($retval != 0)
{ {
$langs->load("errors"); $langs->load("errors");
dol_syslog("Datadump retval after exec=".$retval, LOG_ERR); dol_syslog("Datadump retval after exec=".$retval, LOG_ERR);
$error = 'Error '.$retval; $errormsg = 'Error '.$retval;
$ok=0; $ok=0;
} }
else else
{ {
$i=0; $i=0;
if (!empty($readt)) if (!empty($output_arr))
foreach($readt as $key=>$read) {
foreach($output_arr as $key => $read)
{ {
$i++; // output line number $i++; // output line number
if ($i == 1 && preg_match('/Warning.*Using a password/i', $read)) continue; if ($i == 1 && preg_match('/Warning.*Using a password/i', $read)) continue;
@ -341,6 +341,7 @@ class Utils
} }
} }
} }
}
if ($execmethod == 2) // With this method, there is no way to get the return code, only output if ($execmethod == 2) // With this method, there is no way to get the return code, only output
{ {
$handlein = popen($fullcommandclear, 'r'); $handlein = popen($fullcommandclear, 'r');
@ -515,7 +516,7 @@ class Utils
* @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method
* @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK. * @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK.
*/ */
function executeCLI($command, $outputfile, $execmethod=0) public function executeCLI($command, $outputfile, $execmethod = 0)
{ {
global $conf, $langs; global $conf, $langs;
@ -535,6 +536,7 @@ class Utils
if ($execmethod == 1) if ($execmethod == 1)
{ {
$retval = null;
exec($command, $output_arr, $retval); exec($command, $output_arr, $retval);
$result = $retval; $result = $retval;
if ($retval != 0) if ($retval != 0)
@ -546,7 +548,6 @@ class Utils
} }
if ($execmethod == 2) // With this method, there is no way to get the return code, only output if ($execmethod == 2) // With this method, there is no way to get the return code, only output
{ {
$ok=0;
$handle = fopen($outputfile, 'w+b'); $handle = fopen($outputfile, 'w+b');
if ($handle) if ($handle)
{ {
@ -584,14 +585,15 @@ class Utils
* @param string $module Module name * @param string $module Module name
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
function generateDoc($module) public function generateDoc($module)
{ {
global $conf, $langs; global $conf, $langs, $user, $mysoc;
global $dirins; global $dirins;
$error = 0; $error = 0;
$modulelowercase=strtolower($module); $modulelowercase=strtolower($module);
$now=dol_now();
// Dir for module // Dir for module
$dir = $dirins.'/'.$modulelowercase; $dir = $dirins.'/'.$modulelowercase;
@ -625,7 +627,8 @@ class Utils
if (count($arrayversion)) if (count($arrayversion))
{ {
$FILENAMEASCII=strtolower($module).'.asciidoc'; $FILENAMEASCII=strtolower($module).'.asciidoc';
$FILENAMEDOC=strtolower($module).'.html'; // TODO Use/text PDF $FILENAMEDOC=strtolower($module).'.html';
$FILENAMEDOCPDF=strtolower($module).'.pdf';
$dirofmodule = dol_buildpath(strtolower($module), 0); $dirofmodule = dol_buildpath(strtolower($module), 0);
$dirofmoduledoc = dol_buildpath(strtolower($module), 0).'/doc'; $dirofmoduledoc = dol_buildpath(strtolower($module), 0).'/doc';
@ -641,13 +644,25 @@ class Utils
return -1; return -1;
} }
$conf->global->MODULEBUILDER_ASCIIDOCTOR='asciidoctor'; if (empty($conf->global->MODULEBUILDER_ASCIIDOCTOR) && empty($conf->global->MODULEBUILDER_ASCIIDOCTORPDF))
if (empty($conf->global->MODULEBUILDER_ASCIIDOCTOR))
{ {
$this->error = 'Setup of module ModuleBuilder not complete'; $this->error = 'Setup of module ModuleBuilder not complete';
return -1; return -1;
} }
// Copy some files into temp directory, so instruction include::ChangeLog.md[] will works inside the asciidoc file.
dol_copy($dirofmodule.'/README.md', $dirofmoduletmp.'/README.md', 0, 1);
dol_copy($dirofmodule.'/ChangeLog.md', $dirofmoduletmp.'/ChangeLog.md', 0, 1);
// Replace into README.md and ChangeLog.md (in case they are included into documentation with tag __README__ or __CHANGELOG__)
$arrayreplacement=array();
$arrayreplacement['/^#\s.*/m']=''; // Remove first level of title into .md files
$arrayreplacement['/^#/m']='##'; // Add on # to increase level
dolReplaceInFile($dirofmoduletmp.'/README.md', $arrayreplacement, '', 0, 0, 1);
dolReplaceInFile($dirofmoduletmp.'/ChangeLog.md', $arrayreplacement, '', 0, 0, 1);
$destfile=$dirofmoduletmp.'/'.$FILENAMEASCII; $destfile=$dirofmoduletmp.'/'.$FILENAMEASCII;
$fhandle = fopen($destfile, 'w+'); $fhandle = fopen($destfile, 'w+');
@ -680,35 +695,58 @@ class Utils
$i++; $i++;
} }
fwrite($fhandle, "\n\n\n== DATA SPECIFICATIONS...\n\n");
// TODO
fwrite($fhandle, "TODO...");
fwrite($fhandle, "\n\n\n== CHANGELOG...\n\n");
// TODO
fwrite($fhandle, "TODO...");
fclose($fhandle); fclose($fhandle);
}
// Copy some files into temp directory $contentreadme=file_get_contents($dirofmoduletmp.'/README.md');
dol_copy($dirofmodule.'/README.md', $dirofmoduletmp.'/README.md', 0, 1); $contentchangelog=file_get_contents($dirofmoduletmp.'/ChangeLog.md');
dol_copy($dirofmodule.'/ChangeLog.md', $dirofmoduletmp.'/ChangeLog.md', 0, 1);
include DOL_DOCUMENT_ROOT.'/core/lib/parsemd.lib.php';
//var_dump($phpfileval['fullname']);
$arrayreplacement=array(
'mymodule'=>strtolower($module),
'MyModule'=>$module,
'MYMODULE'=>strtoupper($module),
'My module'=>$module,
'my module'=>$module,
'Mon module'=>$module,
'mon module'=>$module,
'htdocs/modulebuilder/template'=>strtolower($module),
'__MYCOMPANY_NAME__'=>$mysoc->name,
'__KEYWORDS__'=>$module,
'__USER_FULLNAME__'=>$user->getFullName($langs),
'__USER_EMAIL__'=>$user->email,
'__YYYY-MM-DD__'=>dol_print_date($now, 'dayrfc'),
'---Put here your own copyright and developer email---'=>dol_print_date($now, 'dayrfc').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':''),
'__DATA_SPECIFICATION__'=>'Not yet available',
'__README__'=>dolMd2Asciidoc($contentreadme),
'__CHANGELOG__'=>dolMd2Asciidoc($contentchangelog),
);
dolReplaceInFile($destfile, $arrayreplacement);
}
// Launch doc generation // Launch doc generation
$currentdir = getcwd(); $currentdir = getcwd();
chdir($dirofmodule); chdir($dirofmodule);
require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
$utils = new Utils($db);
// Build HTML doc
$command=$conf->global->MODULEBUILDER_ASCIIDOCTOR.' '.$destfile.' -n -o '.$dirofmoduledoc.'/'.$FILENAMEDOC; $command=$conf->global->MODULEBUILDER_ASCIIDOCTOR.' '.$destfile.' -n -o '.$dirofmoduledoc.'/'.$FILENAMEDOC;
$outfile=$dirofmoduletmp.'/out.tmp'; $outfile=$dirofmoduletmp.'/out.tmp';
require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php'; $resarray = $utils->executeCLI($command, $outfile);
$utils = new Utils($this->db); if ($resarray['result'] != '0')
{
$this->error = $resarray['error'].' '.$resarray['output'];
}
$result = ($resarray['result'] == 0) ? 1 : 0;
// Build PDF doc
$command=$conf->global->MODULEBUILDER_ASCIIDOCTORPDF.' '.$destfile.' -n -o '.$dirofmoduledoc.'/'.$FILENAMEDOCPDF;
$outfile=$dirofmoduletmp.'/outpdf.tmp';
$resarray = $utils->executeCLI($command, $outfile); $resarray = $utils->executeCLI($command, $outfile);
if ($resarray['result'] != '0') if ($resarray['result'] != '0')
{ {
@ -751,7 +789,7 @@ class Utils
* *
* @return int 0 if OK, < 0 if KO * @return int 0 if OK, < 0 if KO
*/ */
function compressSyslogs() public function compressSyslogs()
{ {
global $conf; global $conf;
@ -869,7 +907,7 @@ class Utils
* @param string $tables Table name or '*' for all * @param string $tables Table name or '*' for all
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
function backupTables($outputfile, $tables='*') public function backupTables($outputfile, $tables = '*')
{ {
global $db, $langs; global $db, $langs;
global $errormsg; global $errormsg;

View File

@ -4,6 +4,7 @@
* Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es> * Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.com> * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -54,7 +55,7 @@ function dol_basename($pathfile)
* @param string $relativename For recursive purpose only. Must be "" at first call. * @param string $relativename For recursive purpose only. Must be "" at first call.
* @param string $donotfollowsymlinks Do not follow symbolic links * @param string $donotfollowsymlinks Do not follow symbolic links
* @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file',...) * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file',...)
* @see dol_dir_list_indatabase * @see dol_dir_list_in_database()
*/ */
function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0, $nohook = 0, $relativename = "", $donotfollowsymlinks = 0) function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0, $nohook = 0, $relativename = "", $donotfollowsymlinks = 0)
{ {
@ -194,15 +195,9 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil
closedir($dir); closedir($dir);
// Obtain a list of columns // Obtain a list of columns
if (! empty($sortcriteria)) if (! empty($sortcriteria) && $sortorder)
{ {
$myarray=array(); $file_list = dol_sort_array($file_list, $sortcriteria, ($sortorder == SORT_ASC ? 'asc' : 'desc'));
foreach ($file_list as $key => $row)
{
$myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
}
// Sort the data
if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
} }
} }
} }
@ -224,7 +219,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil
* @param string $sortorder Sort order (SORT_ASC, SORT_DESC) * @param string $sortorder Sort order (SORT_ASC, SORT_DESC)
* @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like description * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like description
* @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','type'=>'dir|file',...) * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','type'=>'dir|file',...)
* @see dol_dir_list * @see dol_dir_list()
*/ */
function dol_dir_list_in_database($path, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0) function dol_dir_list_in_database($path, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0)
{ {
@ -442,6 +437,18 @@ function dol_is_dir($folder)
else return false; else return false;
} }
/**
* Return if path is empty
*
* @param string $dir Path of Directory
* @return boolean True or false
*/
function dol_is_dir_empty($dir)
{
if (!is_readable($dir)) return false;
return (count(scandir($dir)) == 2);
}
/** /**
* Return if path is a file * Return if path is a file
* *
@ -515,7 +522,7 @@ function dol_dir_is_emtpy($folder)
* *
* @param string $file Filename * @param string $file Filename
* @return int <0 if KO, Number of lines in files if OK * @return int <0 if KO, Number of lines in files if OK
* @see dol_nboflines * @see dol_nboflines()
*/ */
function dol_count_nb_of_line($file) function dol_count_nb_of_line($file)
{ {
@ -575,14 +582,15 @@ function dol_filemtime($pathoffile)
* @param string $destfile Destination file (can't be a directory). If empty, will be same than source file. * @param string $destfile Destination file (can't be a directory). If empty, will be same than source file.
* @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
* @param int $indexdatabase 1=index new file into database. * @param int $indexdatabase 1=index new file into database.
* @param int $arrayreplacementisregex 1=Array of replacement is regex
* @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK * @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK
* @see dol_copy dolReplaceRegExInFile * @see dol_copy()
*/ */
function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0) function dolReplaceInFile($srcfile, $arrayreplacement, $destfile = '', $newmask = 0, $indexdatabase = 0, $arrayreplacementisregex = 0)
{ {
global $conf; global $conf;
dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase); dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase." arrayreplacementisregex=".$arrayreplacementisregex);
if (empty($srcfile)) return -1; if (empty($srcfile)) return -1;
if (empty($destfile)) $destfile=$srcfile; if (empty($destfile)) $destfile=$srcfile;
@ -613,7 +621,17 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0,
// Create $newpathoftmpdestfile from $newpathofsrcfile // Create $newpathoftmpdestfile from $newpathofsrcfile
$content = file_get_contents($newpathofsrcfile, 'r'); $content = file_get_contents($newpathofsrcfile, 'r');
if (empty($arrayreplacementisregex))
{
$content = make_substitutions($content, $arrayreplacement, null); $content = make_substitutions($content, $arrayreplacement, null);
}
else
{
foreach ($arrayreplacement as $key => $value)
{
$content = preg_replace($key, $value, $content);
}
}
file_put_contents($newpathoftmpdestfile, $content); file_put_contents($newpathoftmpdestfile, $content);
@chmod($newpathoftmpdestfile, octdec($newmask)); @chmod($newpathoftmpdestfile, octdec($newmask));
@ -637,21 +655,6 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0,
return 1; return 1;
} }
/**
* Make replacement of strings into a file.
*
* @param string $srcfile Source file (can't be a directory)
* @param array $arrayreplacement Array with strings to replace. Example: array('valuebefore'=>'valueafter', ...)
* @param string $destfile Destination file (can't be a directory). If empty, will be same than source file.
* @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
* @param int $indexdatabase Index new file into database.
* @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK
* @see dol_copy dolReplaceInFile
*/
function dolReplaceRegExInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
{
// TODO
}
/** /**
* Copy a file to another file. * Copy a file to another file.
@ -661,7 +664,7 @@ function dolReplaceRegExInFile($srcfile, $arrayreplacement, $destfile='', $newma
* @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
* @param int $overwriteifexists Overwrite file if exists (1 by default) * @param int $overwriteifexists Overwrite file if exists (1 by default)
* @return int <0 if error, 0 if nothing done (dest file already exists and overwriteifexists=0), >0 if OK * @return int <0 if error, 0 if nothing done (dest file already exists and overwriteifexists=0), >0 if OK
* @see dol_delete_file * @see dol_delete_file() dolCopyDir()
*/ */
function dol_copy($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1) function dol_copy($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1)
{ {
@ -717,7 +720,7 @@ function dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
* @param int $overwriteifexists Overwrite file if exists (1 by default) * @param int $overwriteifexists Overwrite file if exists (1 by default)
* @param array $arrayreplacement Array to use to replace filenames with another one during the copy (works only on file names, not on directory names). * @param array $arrayreplacement Array to use to replace filenames with another one during the copy (works only on file names, not on directory names).
* @return int <0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK * @return int <0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK
* @see dol_copy * @see dol_copy()
*/ */
function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement = null) function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement = null)
{ {
@ -809,7 +812,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep
* @param int $testvirus Do an antivirus test. Move is canceled if a virus is found. * @param int $testvirus Do an antivirus test. Move is canceled if a virus is found.
* @param int $indexdatabase Index new file into database. * @param int $indexdatabase Index new file into database.
* @return boolean True if OK, false if KO * @return boolean True if OK, false if KO
* @see dol_move_uploaded_file * @see dol_move_uploaded_file()
*/ */
function dol_move($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1, $testvirus = 0, $indexdatabase = 1) function dol_move($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1, $testvirus = 0, $indexdatabase = 1)
{ {
@ -956,7 +959,7 @@ function dol_unescapefile($filename)
*/ */
function dolCheckVirus($src_file) function dolCheckVirus($src_file)
{ {
global $conf, $db; global $conf;
if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))
{ {
@ -982,6 +985,7 @@ function dolCheckVirus($src_file)
* - This function can be used only into a HTML page context. Use dol_move if you are outside. * - This function can be used only into a HTML page context. Use dol_move if you are outside.
* - Test on antivirus is always done (if antivirus set). * - Test on antivirus is always done (if antivirus set).
* - Database of files is NOT updated (this is done by dol_add_file_process() that calls this function). * - Database of files is NOT updated (this is done by dol_add_file_process() that calls this function).
* - Extension .noexe may be added if file is executable and MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED is not set.
* *
* @param string $src_file Source full path filename ($_FILES['field']['tmp_name']) * @param string $src_file Source full path filename ($_FILES['field']['tmp_name'])
* @param string $dest_file Target full path filename ($_FILES['field']['name']) * @param string $dest_file Target full path filename ($_FILES['field']['name'])
@ -990,8 +994,8 @@ function dolCheckVirus($src_file)
* @param integer $uploaderrorcode Value of PHP upload error code ($_FILES['field']['error']) * @param integer $uploaderrorcode Value of PHP upload error code ($_FILES['field']['error'])
* @param int $nohook Disable all hooks * @param int $nohook Disable all hooks
* @param string $varfiles _FILES var name * @param string $varfiles _FILES var name
* @return int|string >0 if OK, <0 or string if KO * @return int >0 if OK, <0 or string if KO
* @see dol_move * @see dol_move()
*/ */
function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan = 0, $uploaderrorcode = 0, $nohook = 0, $varfiles = 'addedfile') function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan = 0, $uploaderrorcode = 0, $nohook = 0, $varfiles = 'addedfile')
{ {
@ -1045,7 +1049,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
$checkvirusarray=dolCheckVirus($src_file); $checkvirusarray=dolCheckVirus($src_file);
if (count($checkvirusarray)) if (count($checkvirusarray))
{ {
dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: result='.$result.' errors='.join(',',$checkvirusarray), LOG_WARNING); dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: errors='.join(',', $checkvirusarray), LOG_WARNING);
return 'ErrorFileIsInfectedWithAVirus: '.join(',', $checkvirusarray); return 'ErrorFileIsInfectedWithAVirus: '.join(',', $checkvirusarray);
} }
} }
@ -1060,15 +1064,15 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
// Security: // Security:
// We refuse cache files/dirs, upload using .. and pipes into filenames. // We refuse cache files/dirs, upload using .. and pipes into filenames.
if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file)) if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file))
{ {
dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING); dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
return -1; return -1;
} }
// Security: // Security:
// On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers. // We refuse cache files/dirs, upload using .. and pipes into filenames.
if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file)) if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file))
{ {
dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING); dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
return -2; return -2;
@ -1134,7 +1138,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
* @param boolean $allowdotdot Allow to delete file path with .. inside. Never use this, it is reserved for migration purpose. * @param boolean $allowdotdot Allow to delete file path with .. inside. Never use this, it is reserved for migration purpose.
* @param int $indexdatabase Try to remove also index entries. * @param int $indexdatabase Try to remove also index entries.
* @return boolean True if no error (file is deleted or if glob is used and there's nothing to delete), False if error * @return boolean True if no error (file is deleted or if glob is used and there's nothing to delete), False if error
* @see dol_delete_dir * @see dol_delete_dir()
*/ */
function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $object = null, $allowdotdot = false, $indexdatabase = 1) function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $object = null, $allowdotdot = false, $indexdatabase = 1)
{ {
@ -1217,11 +1221,14 @@ function dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $obje
} }
} }
} }
else dol_syslog("Failed to remove file ".$filename, LOG_WARNING); 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 // 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 // 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); else dol_syslog("No files to delete found", LOG_DEBUG);
} }
else else
@ -1244,7 +1251,7 @@ function dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $obje
* @param string $dir Directory to delete * @param string $dir Directory to delete
* @param int $nophperrors Disable all PHP output errors * @param int $nophperrors Disable all PHP output errors
* @return boolean True if success, false if error * @return boolean True if success, false if error
* @see dol_delete_file dol_copy * @see dol_delete_file() dolCopyDir()
*/ */
function dol_delete_dir($dir, $nophperrors = 0) function dol_delete_dir($dir, $nophperrors = 0)
{ {
@ -1319,7 +1326,7 @@ function dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$
* *
* @param object $object Object to clean * @param object $object Object to clean
* @return int 0 if error, 1 if OK * @return int 0 if error, 1 if OK
* @see dol_convert_file * @see dol_convert_file()
*/ */
function dol_delete_preview($object) function dol_delete_preview($object)
{ {
@ -1820,19 +1827,22 @@ function deleteFilesIntoDatabaseIndex($dir, $file, $mode='uploaded')
* @param string $fileinput Input file name * @param string $fileinput Input file name
* @param string $ext Format of target file (It is also extension added to file if fileoutput is not provided). * @param string $ext Format of target file (It is also extension added to file if fileoutput is not provided).
* @param string $fileoutput Output filename * @param string $fileoutput Output filename
* @param string $page Page number if we convert a PDF into png
* @return int <0 if KO, 0=Nothing done, >0 if OK * @return int <0 if KO, 0=Nothing done, >0 if OK
*/ */
function dol_convert_file($fileinput, $ext='png', $fileoutput='') function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = '')
{ {
global $langs; global $langs;
if (class_exists('Imagick')) if (class_exists('Imagick'))
{ {
$image=new Imagick(); $image=new Imagick();
try { try {
$ret = $image->readImage($fileinput); $filetoconvert=$fileinput.(($page != '')?'['.$page.']':'');
//var_dump($filetoconvert);
$ret = $image->readImage($filetoconvert);
} catch(Exception $e) { } catch(Exception $e) {
dol_syslog("Failed to read image using Imagick. Try to install package 'apt-get install ghostscript'.", LOG_WARNING); $ext = pathinfo($fileinput, PATHINFO_EXTENSION);
dol_syslog("Failed to read image using Imagick (Try to install package 'apt-get install php-imagick ghostscript' and check there is no policy to disable ".$ext." convertion in /etc/ImageMagick*/policy.xml): ".$e->getMessage(), LOG_WARNING);
return 0; return 0;
} }
if ($ret) if ($ret)
@ -1843,16 +1853,11 @@ function dol_convert_file($fileinput, $ext='png', $fileoutput='')
if (empty($fileoutput)) $fileoutput=$fileinput.".".$ext; if (empty($fileoutput)) $fileoutput=$fileinput.".".$ext;
$count = $image->getNumberImages(); $count = $image->getNumberImages();
if (! dol_is_file($fileoutput) || is_writeable($fileoutput)) if (! dol_is_file($fileoutput) || is_writeable($fileoutput))
{ {
try {
$ret = $image->writeImages($fileoutput, true); $ret = $image->writeImages($fileoutput, true);
} }
catch(Exception $e)
{
dol_syslog($e->getMessage(), LOG_WARNING);
}
}
else else
{ {
dol_syslog("Warning: Failed to write cache preview file '.$fileoutput.'. Check permission on file/dir", LOG_ERR); dol_syslog("Warning: Failed to write cache preview file '.$fileoutput.'. Check permission on file/dir", LOG_ERR);
@ -1887,26 +1892,89 @@ function dol_convert_file($fileinput, $ext='png', $fileoutput='')
*/ */
function dol_compress_file($inputfile, $outputfile, $mode = "gz") function dol_compress_file($inputfile, $outputfile, $mode = "gz")
{ {
global $conf;
$foundhandler=0; $foundhandler=0;
try try
{ {
dol_syslog("dol_compress_file mode=".$mode." inputfile=".$inputfile." outputfile=".$outputfile);
$data = implode("", file(dol_osencode($inputfile))); $data = implode("", file(dol_osencode($inputfile)));
if ($mode == 'gz') { $foundhandler=1; $compressdata = gzencode($data, 9); } if ($mode == 'gz') { $foundhandler=1; $compressdata = gzencode($data, 9); }
elseif ($mode == 'bz') { $foundhandler=1; $compressdata = bzcompress($data, 9); } elseif ($mode == 'bz') { $foundhandler=1; $compressdata = bzcompress($data, 9); }
elseif ($mode == 'zip') elseif ($mode == 'zip')
{ {
if (class_exists('ZipArchive') && ! empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_COMPRESS))
{
$foundhandler=1;
$rootPath = realpath($inputfile);
dol_syslog("Class ZipArchive is set so we zip using ZipArchive to zip into ".$outputfile.' rootPath='.$rootPath);
$zip = new ZipArchive;
if ($zip->open($outputfile, ZipArchive::CREATE) !== true) {
$errormsg="Failed to open file ".$outputfile."\n";
dol_syslog("dol_compress_file failure - ".$errormsg, LOG_ERR);
return -6;
}
// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}
// Zip archive will be created only after closing object
$zip->close();
dol_syslog("dol_compress_file success - ".count($zip->numFiles)." files");
return 1;
}
if (defined('ODTPHP_PATHTOPCLZIP')) if (defined('ODTPHP_PATHTOPCLZIP'))
{ {
$foundhandler=1; $foundhandler=1;
include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php'; include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
$archive = new PclZip($outputfile); $archive = new PclZip($outputfile);
$archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile)); $result = $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
//$archive->add($inputfile);
if ($result === 0)
{
global $errormsg;
$errormsg=$archive->errorInfo(true);
dol_syslog("dol_compress_file failure - ".$errormsg, LOG_ERR);
if ($archive->errorCode() == PCLZIP_ERR_WRITE_OPEN_FAIL)
{
dol_syslog("dol_compress_file error PCLZIP_ERR_WRITE_OPEN_FAIL", LOG_ERR);
return -4;
}
return -3;
}
else
{
dol_syslog("dol_compress_file success - ".count($result)." files");
return 1; return 1;
} }
} }
}
if ($foundhandler) if ($foundhandler)
{ {
@ -1940,9 +2008,9 @@ function dol_compress_file($inputfile, $outputfile, $mode="gz")
*/ */
function dol_uncompress($inputfile, $outputdir) function dol_uncompress($inputfile, $outputdir)
{ {
global $langs; global $conf, $langs;
if (defined('ODTPHP_PATHTOPCLZIP')) if (defined('ODTPHP_PATHTOPCLZIP') && empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_UNCOMPRESS))
{ {
dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir); dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir);
include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php'; include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
@ -1997,9 +2065,10 @@ function dol_uncompress($inputfile,$outputdir)
* @param string $inputdir Source dir name * @param string $inputdir Source dir name
* @param string $outputfile Target file name (output directory must exists and be writable) * @param string $outputfile Target file name (output directory must exists and be writable)
* @param string $mode 'zip' * @param string $mode 'zip'
* @param string $excludefiles A regex pattern. For example: '/\.log$|\/temp\//'
* @return int <0 if KO, >0 if OK * @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; $foundhandler=0;
@ -2030,6 +2099,7 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip")
return 1; return 1;
} }
else*/ else*/
//if (class_exists('ZipArchive') && ! empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_COMPRESS))
if (class_exists('ZipArchive')) if (class_exists('ZipArchive'))
{ {
$foundhandler=1; $foundhandler=1;
@ -2037,6 +2107,13 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip")
// Initialize archive object // Initialize archive object
$zip = new ZipArchive(); $zip = new ZipArchive();
$result = $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE); $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 // Create recursive directory iterator
/** @var SplFileInfo[] $files */ /** @var SplFileInfo[] $files */
@ -2053,11 +2130,13 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip")
// Get real and relative path for current file // Get real and relative path for current file
$filePath = $file->getRealPath(); $filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($inputdir) + 1); $relativePath = substr($filePath, strlen($inputdir) + 1);
if (empty($excludefiles) || ! preg_match($excludefiles, $filePath))
{
// Add current file to archive // Add current file to archive
$zip->addFile($filePath, $relativePath); $zip->addFile($filePath, $relativePath);
} }
} }
}
// Zip archive will be created only after closing object // Zip archive will be created only after closing object
$zip->close(); $zip->close();
@ -2115,7 +2194,7 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta
* @param string $refname Ref of object to check permission for external users (autodetect if not provided) * @param string $refname Ref of object to check permission for external users (autodetect if not provided)
* @param string $mode Check permission for 'read' or 'write' * @param string $mode Check permission for 'read' or 'write'
* @return mixed Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name) * @return mixed Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name)
* @see restrictedArea * @see restrictedArea()
*/ */
function dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser = '', $refname = '', $mode = 'read') function dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser = '', $refname = '', $mode = 'read')
{ {
@ -2134,6 +2213,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
if ($modulepart == 'users') $modulepart='user'; if ($modulepart == 'users') $modulepart='user';
dol_syslog('modulepart='.$modulepart.' original_file='.$original_file.' entity='.$entity); dol_syslog('modulepart='.$modulepart.' original_file='.$original_file.' entity='.$entity);
// We define $accessallowed and $sqlprotectagainstexternals // We define $accessallowed and $sqlprotectagainstexternals
$accessallowed=0; $accessallowed=0;
$sqlprotectagainstexternals=''; $sqlprotectagainstexternals='';
@ -2142,8 +2222,6 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
// Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10' // Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10'
if (empty($refname)) $refname=basename(dirname($original_file)."/"); if (empty($refname)) $refname=basename(dirname($original_file)."/");
$relative_original_file = $original_file;
// Define possible keys to use for permission check // Define possible keys to use for permission check
$lire='lire'; $read='read'; $download='download'; $lire='lire'; $read='read'; $download='download';
if ($mode == 'write') if ($mode == 'write')
@ -2381,7 +2459,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
} }
// Wrapping for third parties // Wrapping for third parties
else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output)) elseif (($modulepart == 'company' || $modulepart == 'societe' || $modulepart == 'thirdparty') && !empty($conf->societe->dir_output))
{ {
if (empty($entity) || empty($conf->societe->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided'); if (empty($entity) || empty($conf->societe->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
if ($fuser->rights->societe->{$lire} || preg_match('/^specimen/i', $original_file)) if ($fuser->rights->societe->{$lire} || preg_match('/^specimen/i', $original_file))
@ -2569,7 +2647,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
$accessallowed=1; $accessallowed=1;
} }
$original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file; $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$db->escape($refname)."' AND entity=".$conf->entity; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
} }
// Wrapping pour les rapport de paiements // Wrapping pour les rapport de paiements
elseif ($modulepart == 'supplier_payment') elseif ($modulepart == 'supplier_payment')
@ -2665,6 +2743,17 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
if (! empty($conf->productbatch->enabled)) $original_file=$conf->productbatch->multidir_output[$entity].'/'.$original_file; if (! empty($conf->productbatch->enabled)) $original_file=$conf->productbatch->multidir_output[$entity].'/'.$original_file;
} }
// Wrapping for stock movements
elseif ($modulepart == 'movement' || $modulepart == 'mouvement')
{
if (empty($entity) || empty($conf->stock->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
if (($fuser->rights->stock->{$lire} || $fuser->rights->stock->movement->{$lire} || $fuser->rights->stock->mouvement->{$lire}) || preg_match('/^specimen/i', $original_file))
{
$accessallowed=1;
}
if (! empty($conf->stock->enabled)) $original_file=$conf->stock->multidir_output[$entity].'/movement/'.$original_file;
}
// Wrapping pour les contrats // Wrapping pour les contrats
elseif ($modulepart == 'contract' && !empty($conf->contrat->dir_output)) elseif ($modulepart == 'contract' && !empty($conf->contrat->dir_output))
{ {
@ -2697,7 +2786,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
} }
// Wrapping pour les remises de cheques // Wrapping pour les remises de cheques
else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output)) elseif ($modulepart == 'remisecheque' && !empty($conf->bank->dir_output))
{ {
if ($fuser->rights->banque->{$lire} || preg_match('/^specimen/i', $original_file)) if ($fuser->rights->banque->{$lire} || preg_match('/^specimen/i', $original_file))
{ {
@ -2708,7 +2797,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
} }
// Wrapping for bank // Wrapping for bank
else if ($modulepart == 'bank' && !empty($conf->bank->dir_output)) elseif (($modulepart == 'banque' || $modulepart == 'bank') && !empty($conf->bank->dir_output))
{ {
if ($fuser->rights->banque->{$lire}) if ($fuser->rights->banque->{$lire})
{ {
@ -2821,6 +2910,19 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1; if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
$original_file=$conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file; $original_file=$conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file;
} }
elseif (preg_match('/^massfilesarea_([a-z]+)$/i', $modulepart, $reg))
{
if (empty($conf->{$reg[1]}->dir_output)) // modulepart not supported
{
dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
exit;
}
if ($fuser->rights->{$reg[1]}->{$lire} || preg_match('/^specimen/i', $original_file))
{
$accessallowed=1;
}
$original_file=$conf->{$reg[1]}->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
}
else else
{ {
if (empty($conf->$modulepart->dir_output)) // modulepart not supported if (empty($conf->$modulepart->dir_output)) // modulepart not supported
@ -2971,4 +3073,3 @@ function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathre
return $file_list; return $file_list;
} }