2016-01-30 00:12:58 +01:00
< ? php
/* Copyright ( C ) 2016 Destailleur Laurent < eldy @ users . sourceforge . net >
*
* 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
* 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
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2016-01-30 00:12:58 +01:00
*/
/**
* \file htdocs / core / class / utils . class . php
* \ingroup core
* \brief File for Utils class
*/
/**
* Class to manage utility methods
*/
class Utils
{
2018-08-22 11:06:34 +02:00
/**
2020-10-31 14:32:18 +01:00
* @ var DoliDB Database handler .
*/
public $db ;
2017-07-12 20:23:35 +02:00
2020-10-31 14:32:18 +01:00
public $output ; // Used by Cron method to return message
public $result ; // Used by Cron method to return data
2017-07-12 20:23:35 +02:00
2016-01-30 00:12:58 +01:00
/**
* Constructor
*
* @ param DoliDB $db Database handler
*/
2019-02-25 22:50:19 +01:00
public function __construct ( $db )
2016-01-30 00:12:58 +01:00
{
$this -> db = $db ;
}
/**
* Purge files into directory of data files .
2016-03-29 14:52:27 +02:00
* CAN BE A CRON TASK
2016-01-30 00:12:58 +01:00
*
2021-02-12 17:15:23 +01:00
* @ param string $choices Choice of purge mode ( 'tempfiles' , 'tempfilesold' to purge temp older than $nbsecondsold seconds , 'logfiles' , or mix of this ) . Note 'allfiles' is possible too but very dangerous .
2019-06-25 20:02:14 +02:00
* @ 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 )
2016-01-30 00:12:58 +01:00
*/
2021-02-12 17:15:23 +01:00
public function purgeFiles ( $choices = 'tempfilesold+logfiles' , $nbsecondsold = 86400 )
2016-01-30 00:12:58 +01:00
{
2016-01-31 13:42:49 +01:00
global $conf , $langs , $dolibarr_main_data_root ;
2017-07-12 20:23:35 +02:00
2016-03-04 01:09:31 +01:00
$langs -> load ( " admin " );
2017-07-12 20:23:35 +02:00
2016-01-30 02:51:26 +01:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
2017-07-12 20:23:35 +02:00
2021-02-15 08:36:40 +01:00
if ( empty ( $choices )) {
2021-02-15 15:53:46 +01:00
$choices = 'tempfilesold+logfiles' ;
2021-02-15 08:36:40 +01:00
}
2017-07-12 20:23:35 +02:00
2020-12-18 13:24:02 +01:00
dol_syslog ( " Utils::purgeFiles choice= " . $choices , LOG_DEBUG );
2019-06-25 20:02:14 +02:00
2020-12-18 13:24:02 +01:00
$count = 0 ;
$countdeleted = 0 ;
$counterror = 0 ;
2021-02-15 08:36:40 +01:00
$filelog = '' ;
2020-12-18 13:24:02 +01:00
2021-02-12 17:15:23 +01:00
$choicesarray = preg_split ( '/[\+,]/' , $choices );
2020-12-18 13:24:02 +01:00
foreach ( $choicesarray as $choice ) {
$filesarray = array ();
2019-06-25 20:02:14 +02:00
2021-02-23 22:03:23 +01:00
if ( $choice == 'tempfiles' || $choice == 'tempfilesold' ) {
2020-12-18 13:24:02 +01:00
// Delete temporary files
2021-02-23 22:03:23 +01:00
if ( $dolibarr_main_data_root ) {
2020-12-18 13:24:02 +01:00
$filesarray = dol_dir_list ( $dolibarr_main_data_root , " directories " , 1 , '^temp$' , '' , 'name' , SORT_ASC , 2 , 0 , '' , 1 ); // Do not follow symlinks
2021-02-23 22:03:23 +01:00
if ( $choice == 'tempfilesold' ) {
2020-12-18 13:24:02 +01:00
$now = dol_now ();
2021-02-23 22:03:23 +01:00
foreach ( $filesarray as $key => $val ) {
if ( $val [ 'date' ] > ( $now - ( $nbsecondsold ))) {
unset ( $filesarray [ $key ]); // Discard temp dir not older than $nbsecondsold
}
2020-12-18 13:24:02 +01:00
}
2016-01-30 02:51:26 +01:00
}
}
2016-01-30 00:12:58 +01:00
}
2017-07-12 20:23:35 +02:00
2021-02-23 22:03:23 +01:00
if ( $choice == 'allfiles' ) {
2020-12-18 13:24:02 +01:00
// Delete all files (except install.lock, do not follow symbolic links)
2021-02-23 22:03:23 +01:00
if ( $dolibarr_main_data_root ) {
2020-12-18 13:24:02 +01:00
$filesarray = dol_dir_list ( $dolibarr_main_data_root , " all " , 0 , '' , 'install\.lock$' , 'name' , SORT_ASC , 0 , 0 , '' , 1 );
}
2017-07-12 20:23:35 +02:00
}
2021-02-23 22:03:23 +01:00
if ( $choice == 'logfile' || $choice == 'logfiles' ) {
2020-12-18 13:24:02 +01:00
// Define files log
2021-02-23 22:03:23 +01:00
if ( $dolibarr_main_data_root ) {
2020-12-18 13:24:02 +01:00
$filesarray = dol_dir_list ( $dolibarr_main_data_root , " files " , 0 , '.*\.log[\.0-9]*(\.gz)?$' , 'install\.lock$' , 'name' , SORT_ASC , 0 , 0 , '' , 1 );
}
2016-01-30 00:12:58 +01:00
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> syslog -> enabled )) {
2020-12-18 13:24:02 +01:00
$filelog = $conf -> global -> SYSLOG_FILE ;
$filelog = preg_replace ( '/DOL_DATA_ROOT/i' , DOL_DATA_ROOT , $filelog );
$alreadyincluded = false ;
2021-02-23 22:03:23 +01:00
foreach ( $filesarray as $tmpcursor ) {
if ( $tmpcursor [ 'fullname' ] == $filelog ) {
$alreadyincluded = true ;
}
}
if ( ! $alreadyincluded ) {
$filesarray [] = array ( 'fullname' => $filelog , 'type' => 'file' );
2020-12-18 13:24:02 +01:00
}
2017-07-12 20:23:35 +02:00
}
}
2020-12-18 13:24:02 +01:00
if ( is_array ( $filesarray ) && count ( $filesarray )) {
2021-02-23 22:03:23 +01:00
foreach ( $filesarray as $key => $value ) {
2020-12-18 13:24:02 +01:00
//print "x ".$filesarray[$key]['fullname']."-".$filesarray[$key]['type']."<br>\n";
if ( $filesarray [ $key ][ 'type' ] == 'dir' ) {
$startcount = 0 ;
$tmpcountdeleted = 0 ;
2019-06-25 20:02:14 +02:00
2020-12-18 13:24:02 +01:00
$result = dol_delete_dir_recursive ( $filesarray [ $key ][ 'fullname' ], $startcount , 1 , 0 , $tmpcountdeleted );
if ( ! in_array ( $filesarray [ $key ][ 'fullname' ], array ( $conf -> api -> dir_temp , $conf -> user -> dir_temp ))) { // The 2 directories $conf->api->dir_temp and $conf->user->dir_temp are recreated at end, so we do not count them
$count += $result ;
$countdeleted += $tmpcountdeleted ;
}
} elseif ( $filesarray [ $key ][ 'type' ] == 'file' ) {
// If (file that is not logfile) or (if mode is logfile)
2021-02-23 22:03:23 +01:00
if ( $filesarray [ $key ][ 'fullname' ] != $filelog || $choice == 'logfile' || $choice == 'logfiles' ) {
2020-12-18 13:24:02 +01:00
$result = dol_delete_file ( $filesarray [ $key ][ 'fullname' ], 1 , 1 );
2021-02-15 08:36:40 +01:00
if ( $result ) {
2020-12-18 13:24:02 +01:00
$count ++ ;
$countdeleted ++ ;
} else {
$counterror ++ ;
}
2018-03-21 13:30:30 +01:00
}
2016-01-30 00:12:58 +01:00
}
}
2017-07-12 20:23:35 +02:00
2020-12-18 13:24:02 +01:00
// Update cachenbofdoc
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> ecm -> enabled ) && $choice == 'allfiles' ) {
2020-12-18 13:24:02 +01:00
require_once DOL_DOCUMENT_ROOT . '/ecm/class/ecmdirectory.class.php' ;
$ecmdirstatic = new EcmDirectory ( $this -> db );
$result = $ecmdirstatic -> refreshcachenboffile ( 1 );
}
2016-01-30 00:12:58 +01:00
}
}
2017-07-12 20:23:35 +02:00
2020-12-18 13:24:02 +01:00
if ( $count > 0 ) {
2019-12-18 15:20:36 +01:00
$this -> output = $langs -> trans ( " PurgeNDirectoriesDeleted " , $countdeleted );
2021-02-15 08:36:40 +01:00
if ( $count > $countdeleted ) {
$this -> output .= '<br>' . $langs -> trans ( " PurgeNDirectoriesFailed " , ( $count - $countdeleted ));
}
2020-12-18 13:24:02 +01:00
} else {
2020-12-24 03:03:38 +01:00
$this -> output = $langs -> trans ( " PurgeNothingToDelete " ) . ( in_array ( 'tempfilesold' , $choicesarray ) ? ' (older than 24h for temp files)' : '' );
2020-12-18 13:24:02 +01:00
}
2016-01-31 13:42:49 +01:00
2019-06-25 20:02:14 +02:00
// Recreate temp dir that are not automatically recreated by core code for performance purpose, we need them
2020-12-18 13:24:02 +01:00
if ( ! empty ( $conf -> api -> enabled )) {
2020-10-31 14:32:18 +01:00
dol_mkdir ( $conf -> api -> dir_temp );
2019-06-25 19:02:24 +02:00
}
2019-06-25 20:02:14 +02:00
dol_mkdir ( $conf -> user -> dir_temp );
2019-06-25 19:02:24 +02:00
2016-01-31 13:42:49 +01:00
//return $count;
2019-12-18 15:20:36 +01:00
return 0 ; // This function can be called by cron so must return 0 if OK
2016-01-30 00:12:58 +01:00
}
2017-07-12 20:23:35 +02:00
2016-03-29 14:52:27 +02:00
/**
* Make a backup of database
* CAN BE A CRON TASK
*
* @ param string $compression 'gz' or 'bz' or 'none'
* @ param string $type 'mysql' , 'postgresql' , ...
* @ param int $usedefault 1 = Use default backup profile ( Set this to 1 when used as cron )
* @ param string $file 'auto' or filename to build
2017-02-27 00:20:17 +01:00
* @ param int $keeplastnfiles Keep only last n files ( not used yet )
2018-10-04 13:10:48 +02:00
* @ param int $execmethod 0 = Use default method ( that is 1 by default ), 1 = Use the PHP 'exec' , 2 = Use the 'popen' method
2017-07-12 20:23:35 +02:00
* @ return int 0 if OK , < 0 if KO ( this function is used also by cron so only 0 is OK )
2016-03-29 14:52:27 +02:00
*/
2019-02-25 22:50:19 +01:00
public function dumpDatabase ( $compression = 'none' , $type = 'auto' , $usedefault = 1 , $file = 'auto' , $keeplastnfiles = 0 , $execmethod = 0 )
2016-03-29 14:52:27 +02:00
{
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 ;
2021-03-02 09:54:52 +01:00
global $dolibarr_main_db_character_set ;
2017-02-27 02:04:25 +01:00
2016-03-29 14:52:27 +02:00
$langs -> load ( " admin " );
2017-07-12 20:23:35 +02:00
2016-03-29 14:52:27 +02:00
dol_syslog ( " Utils::dumpDatabase type= " . $type . " compression= " . $compression . " file= " . $file , LOG_DEBUG );
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
// Check compression parameter
2021-02-23 22:03:23 +01:00
if ( ! in_array ( $compression , array ( 'none' , 'gz' , 'bz' , 'zip' ))) {
2017-12-11 13:50:26 +01:00
$langs -> load ( " errors " );
2019-12-18 15:20:36 +01:00
$this -> error = $langs -> transnoentitiesnoconv ( " ErrorBadValueForParameter " , $compression , " Compression " );
2017-12-11 13:50:26 +01:00
return - 1 ;
2016-03-29 14:52:27 +02:00
}
// Check type parameter
2021-02-23 22:03:23 +01:00
if ( $type == 'auto' ) {
$type = $this -> db -> type ;
}
if ( ! in_array ( $type , array ( 'postgresql' , 'pgsql' , 'mysql' , 'mysqli' , 'mysqlnobin' ))) {
2017-12-11 13:50:26 +01:00
$langs -> load ( " errors " );
2019-12-18 15:20:36 +01:00
$this -> error = $langs -> transnoentitiesnoconv ( " ErrorBadValueForParameter " , $type , " Basetype " );
2017-12-11 13:50:26 +01:00
return - 1 ;
2016-03-29 14:52:27 +02:00
}
// Check file parameter
2021-02-23 22:03:23 +01:00
if ( $file == 'auto' ) {
2019-12-18 15:20:36 +01:00
$prefix = 'dump' ;
$ext = 'sql' ;
2021-02-23 22:03:23 +01:00
if ( in_array ( $type , array ( 'mysql' , 'mysqli' ))) {
2021-03-01 20:37:16 +01:00
$prefix = 'mysqldump' ;
$ext = 'sql' ;
2021-02-23 22:03:23 +01:00
}
2017-12-11 13:50:26 +01:00
//if ($label == 'PostgreSQL') { $prefix='pg_dump'; $ext='dump'; }
2021-02-23 22:03:23 +01:00
if ( in_array ( $type , array ( 'pgsql' ))) {
2021-03-01 20:37:16 +01:00
$prefix = 'pg_dump' ;
$ext = 'sql' ;
2021-02-23 22:03:23 +01:00
}
2019-12-18 15:20:36 +01:00
$file = $prefix . '_' . $dolibarr_main_db_name . '_' . dol_sanitizeFileName ( DOL_VERSION ) . '_' . strftime ( " %Y%m%d%H%M " ) . '.' . $ext ;
2016-03-29 14:52:27 +02:00
}
2019-12-18 15:20:36 +01:00
$outputdir = $conf -> admin -> dir_output . '/backup' ;
$result = dol_mkdir ( $outputdir );
2020-01-15 16:45:13 +01:00
$errormsg = '' ;
2016-03-29 14:52:27 +02:00
// MYSQL
2021-02-23 22:03:23 +01:00
if ( $type == 'mysql' || $type == 'mysqli' ) {
2019-12-18 15:20:36 +01:00
$cmddump = $conf -> global -> SYSTEMTOOLS_MYSQLDUMP ;
2017-12-11 13:50:26 +01:00
$outputfile = $outputdir . '/' . $file ;
// for compression format, we add extension
2019-12-18 15:20:36 +01:00
$compression = $compression ? $compression : 'none' ;
2021-02-23 22:03:23 +01:00
if ( $compression == 'gz' ) {
$outputfile .= '.gz' ;
}
if ( $compression == 'bz' ) {
$outputfile .= '.bz2' ;
}
2017-12-11 13:50:26 +01:00
$outputerror = $outputfile . '.err' ;
dol_mkdir ( $conf -> admin -> dir_output . '/backup' );
// Parameteres execution
2019-04-25 22:25:19 +02:00
$command = $cmddump ;
2019-12-18 15:20:36 +01:00
$command = preg_replace ( '/(\$|%)/' , '' , $command ); // We removed chars that can be used to inject vars that contains space inside path of command without seeing there is a space to bypass the escapeshellarg.
2021-02-23 22:03:23 +01:00
if ( preg_match ( " / \ s/ " , $command )) {
$command = escapeshellarg ( $command ); // If there is spaces, we add quotes on command to be sure $command is only a program and not a program+parameters
}
2017-12-11 13:50:26 +01:00
//$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
2019-12-18 15:20:36 +01:00
$param = $dolibarr_main_db_name . " -h " . $dolibarr_main_db_host ;
$param .= " -u " . $dolibarr_main_db_user ;
2021-02-23 22:03:23 +01:00
if ( ! empty ( $dolibarr_main_db_port )) {
$param .= " -P " . $dolibarr_main_db_port ;
}
if ( ! GETPOST ( " use_transaction " , " alpha " )) {
$param .= " -l --single-transaction " ;
}
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 ( " drop_database " , " alpha " )) {
$param .= " --add-drop-database " ;
}
if ( GETPOST ( " use_mysql_quick_param " , " alpha " )) {
$param .= " --quick " ;
}
if ( GETPOST ( " sql_structure " , " alpha " ) || $usedefault ) {
if ( GETPOST ( " drop " , " alpha " ) || $usedefault ) {
$param .= " --add-drop-table=TRUE " ;
} else {
$param .= " --add-drop-table=FALSE " ;
}
2020-05-21 15:05:19 +02:00
} else {
2019-12-18 15:20:36 +01:00
$param .= " -t " ;
2017-12-11 13:50:26 +01:00
}
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " disable-add-locks " , " alpha " )) {
$param .= " --add-locks=FALSE " ;
}
if ( GETPOST ( " sql_data " , " alpha " ) || $usedefault ) {
2019-12-18 15:20:36 +01:00
$param .= " --tables " ;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " showcolumns " , " alpha " ) || $usedefault ) {
$param .= " -c " ;
}
if ( GETPOST ( " extended_ins " , " alpha " ) || $usedefault ) {
$param .= " -e " ;
} else {
$param .= " --skip-extended-insert " ;
}
if ( GETPOST ( " delayed " , " alpha " )) {
$param .= " --delayed-insert " ;
}
if ( GETPOST ( " sql_ignore " , " alpha " )) {
$param .= " --insert-ignore " ;
}
if ( GETPOST ( " hexforbinary " , " alpha " ) || $usedefault ) {
$param .= " --hex-blob " ;
}
2020-05-21 15:05:19 +02:00
} else {
2019-12-18 15:20:36 +01:00
$param .= " -d " ; // No row information (no data)
2017-12-11 13:50:26 +01:00
}
2021-03-02 09:54:52 +01:00
if ( $dolibarr_main_db_character_set == 'utf8mb4' ) {
// We save output into utf8mb4 charset
$param .= " --default-character-set=utf8mb4 " ;
} else {
$param .= " --default-character-set=utf8 " ; // We always save output into utf8 charset
}
2019-12-18 15:20:36 +01:00
$paramcrypted = $param ;
$paramclear = $param ;
2021-02-23 22:03:23 +01:00
if ( ! empty ( $dolibarr_main_db_pass )) {
2019-12-18 15:20:36 +01:00
$paramcrypted .= ' -p"' . preg_replace ( '/./i' , '*' , $dolibarr_main_db_pass ) . '"' ;
2021-01-19 16:04:21 +01:00
$paramclear .= ' -p"' . str_replace ( array ( '"' , '`' , '$' ), array ( '\"' , '\`' , '\$' ), $dolibarr_main_db_pass ) . '"' ;
2017-12-11 13:50:26 +01:00
}
2018-10-15 13:30:25 +02:00
$handle = '' ;
2017-12-11 13:50:26 +01:00
2018-10-15 13:30:25 +02:00
// Start call method to execute dump
2019-12-18 15:20:36 +01:00
$fullcommandcrypted = $command . " " . $paramcrypted . " 2>&1 " ;
$fullcommandclear = $command . " " . $paramclear . " 2>&1 " ;
2021-02-23 22:03:23 +01:00
if ( $compression == 'none' ) {
$handle = fopen ( $outputfile , 'w' );
}
if ( $compression == 'gz' ) {
$handle = gzopen ( $outputfile , 'w' );
}
if ( $compression == 'bz' ) {
$handle = bzopen ( $outputfile , 'w' );
}
2017-12-11 13:50:26 +01:00
2020-02-13 12:33:34 +01:00
$ok = 0 ;
2021-02-23 22:03:23 +01:00
if ( $handle ) {
if ( ! empty ( $conf -> global -> MAIN_EXEC_USE_POPEN )) {
$execmethod = $conf -> global -> MAIN_EXEC_USE_POPEN ;
}
if ( empty ( $execmethod )) {
$execmethod = 1 ;
}
2018-10-04 13:10:48 +02:00
2021-05-12 19:18:51 +02:00
dol_syslog ( " Utils::dumpDatabase execmethod= " . $execmethod . " command: " . $fullcommandcrypted , LOG_INFO );
2018-10-04 13:10:48 +02:00
// TODO Replace with executeCLI function
2021-02-23 22:03:23 +01:00
if ( $execmethod == 1 ) {
2021-03-01 20:37:16 +01:00
$output_arr = array ();
$retval = null ;
2019-09-03 22:39:24 +02:00
exec ( $fullcommandclear , $output_arr , $retval );
2018-10-04 13:10:48 +02:00
2021-02-23 22:03:23 +01:00
if ( $retval != 0 ) {
2018-10-04 13:10:48 +02:00
$langs -> load ( " errors " );
dol_syslog ( " Datadump retval after exec= " . $retval , LOG_ERR );
2019-09-03 22:39:24 +02:00
$errormsg = 'Error ' . $retval ;
2019-12-18 15:20:36 +01:00
$ok = 0 ;
2020-05-21 15:05:19 +02:00
} else {
2019-12-18 15:20:36 +01:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
if ( ! empty ( $output_arr )) {
foreach ( $output_arr as $key => $read ) {
2019-12-18 15:20:36 +01:00
$i ++ ; // output line number
2021-02-23 22:03:23 +01:00
if ( $i == 1 && preg_match ( '/Warning.*Using a password/i' , $read )) {
continue ;
}
2019-09-03 22:39:24 +02:00
fwrite ( $handle , $read . ( $execmethod == 2 ? '' : " \n " ));
2021-02-23 22:03:23 +01:00
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 ;
}
2019-09-03 22:39:24 +02:00
}
2018-10-04 13:10:48 +02:00
}
}
2017-12-11 13:50:26 +01:00
}
2021-02-23 22:03:23 +01:00
if ( $execmethod == 2 ) { // With this method, there is no way to get the return code, only output
2018-10-04 13:10:48 +02:00
$handlein = popen ( $fullcommandclear , 'r' );
2019-12-18 15:20:36 +01:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
while ( ! feof ( $handlein )) {
2019-12-18 15:20:36 +01:00
$i ++ ; // output line number
2018-10-04 13:10:48 +02:00
$read = fgets ( $handlein );
// Exclude warning line we don't want
2021-02-23 22:03:23 +01:00
if ( $i == 1 && preg_match ( '/Warning.*Using a password/i' , $read )) {
continue ;
}
2019-01-27 11:55:16 +01:00
fwrite ( $handle , $read );
2021-02-23 22:03:23 +01:00
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 ;
}
2018-10-04 13:10:48 +02:00
}
pclose ( $handlein );
}
2017-12-11 13:50:26 +01:00
2021-02-23 22:03:23 +01:00
if ( $compression == 'none' ) {
fclose ( $handle );
}
if ( $compression == 'gz' ) {
gzclose ( $handle );
}
if ( $compression == 'bz' ) {
bzclose ( $handle );
}
2017-12-11 13:50:26 +01:00
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> MAIN_UMASK )) {
2017-12-11 13:50:26 +01:00
@ chmod ( $outputfile , octdec ( $conf -> global -> MAIN_UMASK ));
2021-02-23 22:03:23 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$langs -> load ( " errors " );
2019-01-27 11:55:16 +01:00
dol_syslog ( " Failed to open file " . $outputfile , LOG_ERR );
2019-12-18 15:20:36 +01:00
$errormsg = $langs -> trans ( " ErrorFailedToWriteInDir " );
2017-12-11 13:50:26 +01:00
}
// Get errorstring
2021-02-23 22:03:23 +01:00
if ( $compression == 'none' ) {
$handle = fopen ( $outputfile , 'r' );
}
if ( $compression == 'gz' ) {
$handle = gzopen ( $outputfile , 'r' );
}
if ( $compression == 'bz' ) {
$handle = bzopen ( $outputfile , 'r' );
}
if ( $handle ) {
2017-12-11 13:50:26 +01:00
// Get 2048 first chars of error message.
2019-01-27 11:55:16 +01:00
$errormsg = fgets ( $handle , 2048 );
2020-01-15 16:45:13 +01:00
//$ok=0;$errormsg=''; To force error
2017-12-11 13:50:26 +01:00
// Close file
2021-02-23 22:03:23 +01:00
if ( $compression == 'none' ) {
fclose ( $handle );
}
if ( $compression == 'gz' ) {
gzclose ( $handle );
}
if ( $compression == 'bz' ) {
bzclose ( $handle );
}
2020-02-13 10:44:08 +01:00
if ( $ok && preg_match ( '/^-- (MySql|MariaDB)/i' , $errormsg )) { // No error
2020-02-09 18:38:27 +01:00
$errormsg = '' ;
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
// Renommer fichier sortie en fichier erreur
//print "$outputfile -> $outputerror";
2018-09-26 01:45:24 +02:00
@ dol_delete_file ( $outputerror , 1 , 0 , 0 , null , false , 0 );
2019-01-27 11:55:16 +01:00
@ rename ( $outputfile , $outputerror );
2017-12-11 13:50:26 +01:00
// Si safe_mode on et command hors du parametre exec, on a un fichier out vide donc errormsg vide
2021-02-23 22:03:23 +01:00
if ( ! $errormsg ) {
2017-12-11 13:50:26 +01:00
$langs -> load ( " errors " );
2019-12-18 15:20:36 +01:00
$errormsg = $langs -> trans ( " ErrorFailedToRunExternalCommand " );
2017-12-11 13:50:26 +01:00
}
}
}
// Fin execution commande
$this -> output = $errormsg ;
$this -> error = $errormsg ;
$this -> result = array ( " commandbackuplastdone " => $command . " " . $paramcrypted , " commandbackuptorun " => " " );
//if (empty($this->output)) $this->output=$this->result['commandbackuplastdone'];
2016-03-29 14:52:27 +02:00
}
2017-07-12 20:23:35 +02:00
2016-03-29 14:52:27 +02:00
// MYSQL NO BIN
2021-02-23 22:03:23 +01:00
if ( $type == 'mysqlnobin' ) {
2017-12-11 13:50:26 +01:00
$outputfile = $outputdir . '/' . $file ;
$outputfiletemp = $outputfile . '-TMP.sql' ;
// for compression format, we add extension
2019-12-18 15:20:36 +01:00
$compression = $compression ? $compression : 'none' ;
2021-02-23 22:03:23 +01:00
if ( $compression == 'gz' ) {
$outputfile .= '.gz' ;
}
if ( $compression == 'bz' ) {
$outputfile .= '.bz2' ;
}
2017-12-11 13:50:26 +01:00
$outputerror = $outputfile . '.err' ;
dol_mkdir ( $conf -> admin -> dir_output . '/backup' );
2021-02-23 22:03:23 +01:00
if ( $compression == 'gz' or $compression == 'bz' ) {
2018-10-04 20:23:58 +02:00
$this -> backupTables ( $outputfiletemp );
2017-12-11 13:50:26 +01:00
dol_compress_file ( $outputfiletemp , $outputfile , $compression );
unlink ( $outputfiletemp );
2020-05-21 15:05:19 +02:00
} else {
2018-10-04 20:23:58 +02:00
$this -> backupTables ( $outputfile );
2017-12-11 13:50:26 +01:00
}
$this -> output = " " ;
$this -> result = array ( " commandbackuplastdone " => " " , " commandbackuptorun " => " " );
2016-03-29 14:52:27 +02:00
}
2017-07-12 20:23:35 +02:00
2016-03-29 14:52:27 +02:00
// POSTGRESQL
2021-02-23 22:03:23 +01:00
if ( $type == 'postgresql' || $type == 'pgsql' ) {
2019-12-18 15:20:36 +01:00
$cmddump = $conf -> global -> SYSTEMTOOLS_POSTGRESQLDUMP ;
2017-12-11 13:50:26 +01:00
$outputfile = $outputdir . '/' . $file ;
// for compression format, we add extension
2019-12-18 15:20:36 +01:00
$compression = $compression ? $compression : 'none' ;
2021-02-23 22:03:23 +01:00
if ( $compression == 'gz' ) {
$outputfile .= '.gz' ;
}
if ( $compression == 'bz' ) {
$outputfile .= '.bz2' ;
}
2017-12-11 13:50:26 +01:00
$outputerror = $outputfile . '.err' ;
dol_mkdir ( $conf -> admin -> dir_output . '/backup' );
// Parameteres execution
2019-04-25 22:25:19 +02:00
$command = $cmddump ;
2019-12-18 15:20:36 +01:00
$command = preg_replace ( '/(\$|%)/' , '' , $command ); // We removed chars that can be used to inject vars that contains space inside path of command without seeing there is a space to bypass the escapeshellarg.
2021-02-23 22:03:23 +01:00
if ( preg_match ( " / \ s/ " , $command )) {
$command = escapeshellarg ( $command ); // If there is spaces, we add quotes on command to be sure $command is only a program and not a program+parameters
}
2017-12-11 13:50:26 +01:00
//$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
//$param="-F c";
2019-12-18 15:20:36 +01:00
$param = " -F p " ;
$param .= " --no-tablespaces --inserts -h " . $dolibarr_main_db_host ;
$param .= " -U " . $dolibarr_main_db_user ;
2021-02-23 22:03:23 +01:00
if ( ! empty ( $dolibarr_main_db_port )) {
$param .= " -p " . $dolibarr_main_db_port ;
2017-12-11 13:50:26 +01:00
}
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " sql_compat " ) && GETPOST ( " sql_compat " ) == 'ANSI' ) {
$param .= " --disable-dollar-quoting " ;
}
if ( GETPOST ( " drop_database " )) {
$param .= " -c -C " ;
}
if ( GETPOST ( " sql_structure " )) {
if ( GETPOST ( " drop " )) {
$param .= " --add-drop-table " ;
}
if ( ! GETPOST ( " sql_data " )) {
$param .= " -s " ;
}
}
if ( GETPOST ( " sql_data " )) {
if ( ! GETPOST ( " sql_structure " )) {
$param .= " -a " ;
}
if ( GETPOST ( " showcolumns " )) {
$param .= " -c " ;
}
2017-12-11 13:50:26 +01:00
}
2019-12-18 15:20:36 +01:00
$param .= ' -f "' . $outputfile . '"' ;
2017-12-11 13:50:26 +01:00
//if ($compression == 'none')
2021-02-23 22:03:23 +01:00
if ( $compression == 'gz' ) {
$param .= ' -Z 9' ;
}
2017-12-11 13:50:26 +01:00
//if ($compression == 'bz')
2019-12-18 15:20:36 +01:00
$paramcrypted = $param ;
$paramclear = $param ;
2017-12-11 13:50:26 +01:00
/* if ( ! empty ( $dolibarr_main_db_pass ))
{
$paramcrypted .= " -W " . preg_replace ( '/./i' , '*' , $dolibarr_main_db_pass );
$paramclear .= " -W " . $dolibarr_main_db_pass ;
} */
2019-12-18 15:20:36 +01:00
$paramcrypted .= " -w " . $dolibarr_main_db_name ;
$paramclear .= " -w " . $dolibarr_main_db_name ;
2017-12-11 13:50:26 +01:00
$this -> output = " " ;
$this -> result = array ( " commandbackuplastdone " => " " , " commandbackuptorun " => $command . " " . $paramcrypted );
2016-03-29 14:52:27 +02:00
}
2017-02-27 02:04:25 +01:00
// Clean old files
2021-02-23 22:03:23 +01:00
if ( ! $errormsg && $keeplastnfiles > 0 ) {
2017-12-11 13:50:26 +01:00
$tmpfiles = dol_dir_list ( $conf -> admin -> dir_output . '/backup' , 'files' , 0 , '' , '(\.err|\.old|\.sav)$' , 'date' , SORT_DESC );
2019-12-18 15:20:36 +01:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
foreach ( $tmpfiles as $key => $val ) {
2017-12-11 13:50:26 +01:00
$i ++ ;
2021-02-23 22:03:23 +01:00
if ( $i <= $keeplastnfiles ) {
continue ;
}
2018-09-26 01:45:24 +02:00
dol_delete_file ( $val [ 'fullname' ], 0 , 0 , 0 , null , false , 0 );
2017-12-11 13:50:26 +01:00
}
2017-02-27 02:04:25 +01:00
}
2017-07-12 20:23:35 +02:00
2020-01-15 16:45:13 +01:00
return ( $errormsg ? - 1 : 0 );
2016-03-29 14:52:27 +02:00
}
2017-11-06 20:24:12 +01:00
/**
* Execute a CLI command .
*
* @ param string $command Command line to execute .
* @ param string $outputfile Output file ( used only when method is 2 ) . For exemple $conf -> admin -> dir_temp . '/out.tmp' ;
* @ 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 .
*/
2019-02-25 22:50:19 +01:00
public function executeCLI ( $command , $outputfile , $execmethod = 0 )
2017-11-06 20:24:12 +01:00
{
global $conf , $langs ;
$result = 0 ;
$output = '' ;
$error = '' ;
2019-12-18 15:20:36 +01:00
$command = escapeshellcmd ( $command );
$command .= " 2>&1 " ;
2017-11-06 20:24:12 +01:00
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> MAIN_EXEC_USE_POPEN )) {
$execmethod = $conf -> global -> MAIN_EXEC_USE_POPEN ;
}
if ( empty ( $execmethod )) {
$execmethod = 1 ;
}
2017-11-06 20:24:12 +01:00
//$execmethod=1;
dol_syslog ( " Utils::executeCLI execmethod= " . $execmethod . " system: " . $command , LOG_DEBUG );
2019-12-18 15:20:36 +01:00
$output_arr = array ();
2017-11-06 20:24:12 +01:00
2021-02-23 22:03:23 +01:00
if ( $execmethod == 1 ) {
2019-09-03 22:39:24 +02:00
$retval = null ;
2017-11-06 20:24:12 +01:00
exec ( $command , $output_arr , $retval );
$result = $retval ;
2021-02-23 22:03:23 +01:00
if ( $retval != 0 ) {
2017-11-06 20:24:12 +01:00
$langs -> load ( " errors " );
dol_syslog ( " Utils::executeCLI retval after exec= " . $retval , LOG_ERR );
$error = 'Error ' . $retval ;
}
}
2021-02-23 22:03:23 +01:00
if ( $execmethod == 2 ) { // With this method, there is no way to get the return code, only output
2017-11-06 20:24:12 +01:00
$handle = fopen ( $outputfile , 'w+b' );
2021-02-23 22:03:23 +01:00
if ( $handle ) {
2017-11-06 20:24:12 +01:00
dol_syslog ( " Utils::executeCLI run command " . $command );
$handlein = popen ( $command , 'r' );
2021-02-23 22:03:23 +01:00
while ( ! feof ( $handlein )) {
2017-11-06 20:24:12 +01:00
$read = fgets ( $handlein );
2019-01-27 11:55:16 +01:00
fwrite ( $handle , $read );
2019-12-18 15:20:36 +01:00
$output_arr [] = $read ;
2017-11-06 20:24:12 +01:00
}
pclose ( $handlein );
fclose ( $handle );
}
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> MAIN_UMASK )) {
@ chmod ( $outputfile , octdec ( $conf -> global -> MAIN_UMASK ));
}
2017-11-06 20:24:12 +01:00
}
// Update with result
2021-02-23 22:03:23 +01:00
if ( is_array ( $output_arr ) && count ( $output_arr ) > 0 ) {
foreach ( $output_arr as $val ) {
2019-12-18 15:20:36 +01:00
$output .= $val . ( $execmethod == 2 ? '' : " \n " );
2017-11-06 20:24:12 +01:00
}
}
dol_syslog ( " Utils::executeCLI result= " . $result . " output= " . $output . " error= " . $error , LOG_DEBUG );
return array ( 'result' => $result , 'output' => $output , 'error' => $error );
}
2017-12-11 13:50:26 +01:00
/**
* Generate documentation of a Module
*
* @ param string $module Module name
* @ return int < 0 if KO , > 0 if OK
*/
2019-02-25 22:50:19 +01:00
public function generateDoc ( $module )
2017-12-11 13:50:26 +01:00
{
2019-03-22 13:20:37 +01:00
global $conf , $langs , $user , $mysoc ;
2017-12-12 16:11:40 +01:00
global $dirins ;
2017-12-11 13:50:26 +01:00
$error = 0 ;
2019-12-18 15:20:36 +01:00
$modulelowercase = strtolower ( $module );
$now = dol_now ();
2017-12-11 13:50:26 +01:00
// Dir for module
$dir = $dirins . '/' . $modulelowercase ;
// Zip file to build
2019-12-18 15:20:36 +01:00
$FILENAMEDOC = '' ;
2017-12-11 13:50:26 +01:00
// Load module
dol_include_once ( $modulelowercase . '/core/modules/mod' . $module . '.class.php' );
2019-12-18 15:20:36 +01:00
$class = 'mod' . $module ;
2017-12-11 13:50:26 +01:00
2021-02-23 22:03:23 +01:00
if ( class_exists ( $class )) {
2017-12-11 13:50:26 +01:00
try {
2017-12-12 16:11:40 +01:00
$moduleobj = new $class ( $this -> db );
2021-02-23 22:03:23 +01:00
} catch ( Exception $e ) {
2017-12-11 13:50:26 +01:00
$error ++ ;
dol_print_error ( $e -> getMessage ());
}
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$error ++ ;
$langs -> load ( " errors " );
dol_print_error ( $langs -> trans ( " ErrorFailedToLoadModuleDescriptorForXXX " , $module ));
exit ;
}
2019-12-18 15:20:36 +01:00
$arrayversion = explode ( '.' , $moduleobj -> version , 3 );
2021-02-23 22:03:23 +01:00
if ( count ( $arrayversion )) {
2019-12-18 15:20:36 +01:00
$FILENAMEASCII = strtolower ( $module ) . '.asciidoc' ;
$FILENAMEDOC = strtolower ( $module ) . '.html' ;
$FILENAMEDOCPDF = strtolower ( $module ) . '.pdf' ;
2017-12-11 13:50:26 +01:00
2019-02-09 14:12:36 +01:00
$dirofmodule = dol_buildpath ( strtolower ( $module ), 0 );
$dirofmoduledoc = dol_buildpath ( strtolower ( $module ), 0 ) . '/doc' ;
2017-12-11 13:50:26 +01:00
$dirofmoduletmp = dol_buildpath ( strtolower ( $module ), 0 ) . '/doc/temp' ;
2019-02-09 14:12:36 +01:00
$outputfiledoc = $dirofmoduledoc . '/' . $FILENAMEDOC ;
2021-02-23 22:03:23 +01:00
if ( $dirofmoduledoc ) {
if ( ! dol_is_dir ( $dirofmoduledoc )) {
dol_mkdir ( $dirofmoduledoc );
}
if ( ! dol_is_dir ( $dirofmoduletmp )) {
dol_mkdir ( $dirofmoduletmp );
}
if ( ! is_writable ( $dirofmoduletmp )) {
2017-12-11 13:50:26 +01:00
$this -> error = 'Dir ' . $dirofmoduletmp . ' does not exists or is not writable' ;
return - 1 ;
}
2021-02-23 22:03:23 +01:00
if ( empty ( $conf -> global -> MODULEBUILDER_ASCIIDOCTOR ) && empty ( $conf -> global -> MODULEBUILDER_ASCIIDOCTORPDF )) {
2020-10-31 14:32:18 +01:00
$this -> error = 'Setup of module ModuleBuilder not complete' ;
return - 1 ;
2019-02-09 14:12:36 +01:00
}
2019-03-17 19:33:25 +01:00
// 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__)
2019-12-18 15:20:36 +01:00
$arrayreplacement = array ();
$arrayreplacement [ '/^#\s.*/m' ] = '' ; // Remove first level of title into .md files
$arrayreplacement [ '/^#/m' ] = '##' ; // Add on # to increase level
2019-03-17 19:33:25 +01:00
dolReplaceInFile ( $dirofmoduletmp . '/README.md' , $arrayreplacement , '' , 0 , 0 , 1 );
dolReplaceInFile ( $dirofmoduletmp . '/ChangeLog.md' , $arrayreplacement , '' , 0 , 0 , 1 );
2019-12-18 15:20:36 +01:00
$destfile = $dirofmoduletmp . '/' . $FILENAMEASCII ;
2017-12-11 13:50:26 +01:00
$fhandle = fopen ( $destfile , 'w+' );
2021-02-23 22:03:23 +01:00
if ( $fhandle ) {
2019-12-18 15:20:36 +01:00
$specs = dol_dir_list ( dol_buildpath ( strtolower ( $module ) . '/doc' , 0 ), 'files' , 1 , '(\.md|\.asciidoc)$' , array ( '\/temp\/' ));
2017-12-11 13:50:26 +01:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
foreach ( $specs as $spec ) {
if ( preg_match ( '/notindoc/' , $spec [ 'relativename' ])) {
continue ; // Discard file
}
if ( preg_match ( '/example/' , $spec [ 'relativename' ])) {
continue ; // Discard file
}
if ( preg_match ( '/disabled/' , $spec [ 'relativename' ])) {
continue ; // Discard file
}
2017-12-11 13:50:26 +01:00
$pathtofile = strtolower ( $module ) . '/doc/' . $spec [ 'relativename' ];
2019-12-18 15:20:36 +01:00
$format = 'asciidoc' ;
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/\.md$/i' , $spec [ 'name' ])) {
$format = 'markdown' ;
}
2017-12-11 13:50:26 +01:00
$filecursor = @ file_get_contents ( $spec [ 'fullname' ]);
2021-02-23 22:03:23 +01:00
if ( $filecursor ) {
2017-12-11 13:50:26 +01:00
fwrite ( $fhandle , ( $i ? " \n <<< \n \n " : " " ) . $filecursor . " \n " );
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$this -> error = 'Failed to concat content of file ' . $spec [ 'fullname' ];
return - 1 ;
}
$i ++ ;
}
2019-03-17 19:33:25 +01:00
fclose ( $fhandle );
2019-02-09 14:12:36 +01:00
2019-12-18 15:20:36 +01:00
$contentreadme = file_get_contents ( $dirofmoduletmp . '/README.md' );
$contentchangelog = file_get_contents ( $dirofmoduletmp . '/ChangeLog.md' );
2019-02-09 14:12:36 +01:00
2019-03-17 19:33:25 +01:00
include DOL_DOCUMENT_ROOT . '/core/lib/parsemd.lib.php' ;
2019-03-17 15:45:50 +01:00
//var_dump($phpfileval['fullname']);
2019-12-18 15:20:36 +01:00
$arrayreplacement = array (
2020-10-31 14:32:18 +01:00
'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 ),
2019-03-17 15:45:50 +01:00
);
2019-03-17 19:33:25 +01:00
dolReplaceInFile ( $destfile , $arrayreplacement );
2017-12-11 13:50:26 +01:00
}
2019-02-09 14:12:36 +01:00
// Launch doc generation
2020-10-31 14:32:18 +01:00
$currentdir = getcwd ();
chdir ( $dirofmodule );
2019-02-09 14:12:36 +01:00
2020-10-31 14:32:18 +01:00
require_once DOL_DOCUMENT_ROOT . '/core/class/utils.class.php' ;
$utils = new Utils ( $this -> db );
2019-03-12 11:51:20 +01:00
2020-10-31 14:32:18 +01:00
// Build HTML doc
2019-12-18 15:20:36 +01:00
$command = $conf -> global -> MODULEBUILDER_ASCIIDOCTOR . ' ' . $destfile . ' -n -o ' . $dirofmoduledoc . '/' . $FILENAMEDOC ;
$outfile = $dirofmoduletmp . '/out.tmp' ;
2017-12-11 13:50:26 +01:00
$resarray = $utils -> executeCLI ( $command , $outfile );
2021-02-23 22:03:23 +01:00
if ( $resarray [ 'result' ] != '0' ) {
2017-12-11 13:50:26 +01:00
$this -> error = $resarray [ 'error' ] . ' ' . $resarray [ 'output' ];
}
$result = ( $resarray [ 'result' ] == 0 ) ? 1 : 0 ;
2019-02-09 14:12:36 +01:00
2019-03-12 11:51:20 +01:00
// Build PDF doc
2019-12-18 15:20:36 +01:00
$command = $conf -> global -> MODULEBUILDER_ASCIIDOCTORPDF . ' ' . $destfile . ' -n -o ' . $dirofmoduledoc . '/' . $FILENAMEDOCPDF ;
$outfile = $dirofmoduletmp . '/outpdf.tmp' ;
2019-03-12 11:51:20 +01:00
$resarray = $utils -> executeCLI ( $command , $outfile );
2021-02-23 22:03:23 +01:00
if ( $resarray [ 'result' ] != '0' ) {
2020-10-31 14:32:18 +01:00
$this -> error = $resarray [ 'error' ] . ' ' . $resarray [ 'output' ];
2019-03-12 11:51:20 +01:00
}
$result = ( $resarray [ 'result' ] == 0 ) ? 1 : 0 ;
2019-02-09 14:12:36 +01:00
chdir ( $currentdir );
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$result = 0 ;
}
2021-02-23 22:03:23 +01:00
if ( $result > 0 ) {
2017-12-11 13:50:26 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$error ++ ;
$langs -> load ( " errors " );
$this -> error = $langs -> trans ( " ErrorFailToGenerateFile " , $outputfiledoc );
}
2020-05-21 15:05:19 +02:00
} else {
2017-12-11 13:50:26 +01:00
$error ++ ;
$langs -> load ( " errors " );
$this -> error = $langs -> trans ( " ErrorCheckVersionIsDefined " );
}
return - 1 ;
}
2018-03-09 16:52:06 +01:00
/**
2018-09-26 01:45:24 +02:00
* This saves syslog files and compresses older ones .
* Nb of archive to keep is defined into $conf -> global -> SYSLOG_FILE_SAVES
* CAN BE A CRON TASK
2018-03-21 13:30:30 +01:00
*
2018-03-21 13:56:24 +01:00
* @ return int 0 if OK , < 0 if KO
2018-03-09 16:52:06 +01:00
*/
2020-10-31 14:32:18 +01:00
public function compressSyslogs ()
{
2018-03-09 16:52:06 +01:00
global $conf ;
2019-12-18 15:20:36 +01:00
if ( empty ( $conf -> loghandlers [ 'mod_syslog_file' ])) { // File Syslog disabled
2018-03-09 16:52:06 +01:00
return 0 ;
}
2019-12-18 15:20:36 +01:00
if ( ! function_exists ( 'gzopen' )) {
2018-03-21 13:56:24 +01:00
$this -> error = 'Support for gzopen not available in this PHP' ;
2018-03-09 16:52:06 +01:00
return - 1 ;
}
dol_include_once ( '/core/lib/files.lib.php' );
2019-08-17 15:15:52 +02:00
$nbSaves = empty ( $conf -> global -> SYSLOG_FILE_SAVES ) ? 10 : intval ( $conf -> global -> SYSLOG_FILE_SAVES );
2018-03-09 16:52:06 +01:00
2018-03-21 13:56:24 +01:00
if ( empty ( $conf -> global -> SYSLOG_FILE )) {
2018-03-09 16:52:06 +01:00
$mainlogdir = DOL_DATA_ROOT ;
$mainlog = 'dolibarr.log' ;
} else {
$mainlogfull = str_replace ( 'DOL_DATA_ROOT' , DOL_DATA_ROOT , $conf -> global -> SYSLOG_FILE );
$mainlogdir = dirname ( $mainlogfull );
$mainlog = basename ( $mainlogfull );
}
$tabfiles = dol_dir_list ( DOL_DATA_ROOT , 'files' , 0 , '^(dolibarr_.+|odt2pdf)\.log$' ); // Also handle other log files like dolibarr_install.log
$tabfiles [] = array ( 'name' => $mainlog , 'path' => $mainlogdir );
2019-12-18 15:20:36 +01:00
foreach ( $tabfiles as $file ) {
2018-03-09 16:52:06 +01:00
$logname = $file [ 'name' ];
$logpath = $file [ 'path' ];
2021-02-23 22:03:23 +01:00
if ( dol_is_file ( $logpath . '/' . $logname ) && dol_filesize ( $logpath . '/' . $logname ) > 0 ) { // If log file exists and is not empty
2018-09-26 01:45:24 +02:00
// Handle already compressed files to rename them and add +1
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
$filter = '^' . preg_quote ( $logname , '/' ) . '\.([0-9]+)\.gz$' ;
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
$gzfilestmp = dol_dir_list ( $logpath , 'files' , 0 , $filter );
$gzfiles = array ();
2018-03-09 16:52:06 +01:00
2019-12-18 15:20:36 +01:00
foreach ( $gzfilestmp as $gzfile ) {
2018-09-26 01:45:24 +02:00
$tabmatches = array ();
preg_match ( '/' . $filter . '/i' , $gzfile [ 'name' ], $tabmatches );
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
$numsave = intval ( $tabmatches [ 1 ]);
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
$gzfiles [ $numsave ] = $gzfile ;
}
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
krsort ( $gzfiles , SORT_NUMERIC );
2018-03-09 16:52:06 +01:00
2019-12-18 15:20:36 +01:00
foreach ( $gzfiles as $numsave => $dummy ) {
if ( dol_is_file ( $logpath . '/' . $logname . '.' . ( $numsave + 1 ) . '.gz' )) {
2018-09-26 01:45:24 +02:00
return - 2 ;
}
2018-03-09 16:52:06 +01:00
2019-12-18 15:20:36 +01:00
if ( $numsave >= $nbSaves ) {
2018-09-26 01:45:24 +02:00
dol_delete_file ( $logpath . '/' . $logname . '.' . $numsave . '.gz' , 0 , 0 , 0 , null , false , 0 );
} else {
2019-12-18 15:20:36 +01:00
dol_move ( $logpath . '/' . $logname . '.' . $numsave . '.gz' , $logpath . '/' . $logname . '.' . ( $numsave + 1 ) . '.gz' , 0 , 1 , 0 , 0 );
2018-09-26 01:45:24 +02:00
}
2018-03-09 16:52:06 +01:00
}
2018-09-26 01:45:24 +02:00
// Compress current file and recreate it
if ( $nbSaves > 0 ) { // If $nbSaves is 1, we keep 1 archive .gz file, If 2, we keep 2 .gz files
$gzfilehandle = gzopen ( $logpath . '/' . $logname . '.1.gz' , 'wb9' );
2018-03-09 16:52:06 +01:00
2018-03-21 13:56:24 +01:00
if ( empty ( $gzfilehandle )) {
2018-09-26 01:45:24 +02:00
$this -> error = 'Failted to open file ' . $logpath . '/' . $logname . '.1.gz' ;
2018-03-09 16:52:06 +01:00
return - 3 ;
}
2018-09-26 01:45:24 +02:00
$sourcehandle = fopen ( $logpath . '/' . $logname , 'r' );
2018-03-09 16:52:06 +01:00
2018-03-21 13:56:24 +01:00
if ( empty ( $sourcehandle )) {
2018-09-26 01:45:24 +02:00
$this -> error = 'Failed to open file ' . $logpath . '/' . $logname ;
2018-03-09 16:52:06 +01:00
return - 4 ;
}
2019-12-18 15:20:36 +01:00
while ( ! feof ( $sourcehandle )) {
2018-03-09 16:52:06 +01:00
gzwrite ( $gzfilehandle , fread ( $sourcehandle , 512 * 1024 )); // Read 512 kB at a time
}
fclose ( $sourcehandle );
gzclose ( $gzfilehandle );
2018-09-26 01:45:24 +02:00
2019-12-18 15:20:36 +01:00
@ chmod ( $logpath . '/' . $logname . '.1.gz' , octdec ( empty ( $conf -> global -> MAIN_UMASK ) ? '0664' : $conf -> global -> MAIN_UMASK ));
2018-03-09 16:52:06 +01:00
}
2018-09-26 01:45:24 +02:00
dol_delete_file ( $logpath . '/' . $logname , 0 , 0 , 0 , null , false , 0 );
2018-03-09 16:52:06 +01:00
2018-09-26 01:45:24 +02:00
// Create empty file
$newlog = fopen ( $logpath . '/' . $logname , 'a+' );
fclose ( $newlog );
//var_dump($logpath.'/'.$logname." - ".octdec(empty($conf->global->MAIN_UMASK)?'0664':$conf->global->MAIN_UMASK));
2019-12-18 15:20:36 +01:00
@ chmod ( $logpath . '/' . $logname , octdec ( empty ( $conf -> global -> MAIN_UMASK ) ? '0664' : $conf -> global -> MAIN_UMASK ));
2018-03-09 16:52:06 +01:00
}
}
2018-03-21 13:56:24 +01:00
$this -> output = 'Archive log files (keeping last SYSLOG_FILE_SAVES=' . $nbSaves . ' files) done.' ;
2018-03-09 16:52:06 +01:00
return 0 ;
2020-10-31 14:32:18 +01:00
}
2018-10-04 13:10:48 +02:00
/** Backup the db OR just a table without mysqldump binary , with PHP only ( does not require any exec permission )
* Author : David Walsh ( http :// davidwalsh . name / backup - mysql - database - php )
* Updated and enhanced by Stephen Larroque ( lrq3000 ) and by the many commentators from the blog
* Note about foreign keys constraints : for Dolibarr , since there are a lot of constraints and when imported the tables will be inserted in the dumped order , not in constraints order , then we ABSOLUTELY need to use SET FOREIGN_KEY_CHECKS = 0 ; when importing the sql dump .
* Note2 : db2SQL by Howard Yeend can be an alternative , by using SHOW FIELDS FROM and SHOW KEYS FROM we could generate a more precise dump ( eg : by getting the type of the field and then precisely outputting the right formatting - in quotes , numeric or null - instead of trying to guess like we are doing now ) .
*
* @ param string $outputfile Output file name
* @ param string $tables Table name or '*' for all
* @ return int < 0 if KO , > 0 if OK
*/
2019-02-25 22:50:19 +01:00
public function backupTables ( $outputfile , $tables = '*' )
2018-10-04 13:10:48 +02:00
{
global $db , $langs ;
global $errormsg ;
// Set to UTF-8
if ( is_a ( $db , 'DoliDBMysqli' )) {
/** @var DoliDBMysqli $db */
$db -> db -> set_charset ( 'utf8' );
} else {
/** @var DoliDB $db */
$db -> query ( 'SET NAMES utf8' );
$db -> query ( 'SET CHARACTER SET utf8' );
}
//get all of the tables
2021-02-23 22:03:23 +01:00
if ( $tables == '*' ) {
2018-10-04 13:10:48 +02:00
$tables = array ();
$result = $db -> query ( 'SHOW FULL TABLES WHERE Table_type = \'BASE TABLE\'' );
2021-02-23 22:03:23 +01:00
while ( $row = $db -> fetch_row ( $result )) {
2018-10-04 13:10:48 +02:00
$tables [] = $row [ 0 ];
}
2020-05-21 15:05:19 +02:00
} else {
2019-01-27 11:55:16 +01:00
$tables = is_array ( $tables ) ? $tables : explode ( ',' , $tables );
2018-10-04 13:10:48 +02:00
}
//cycle through
$handle = fopen ( $outputfile , 'w+' );
2021-02-23 22:03:23 +01:00
if ( fwrite ( $handle , '' ) === false ) {
2018-10-04 13:10:48 +02:00
$langs -> load ( " errors " );
2019-01-27 11:55:16 +01:00
dol_syslog ( " Failed to open file " . $outputfile , LOG_ERR );
2019-12-18 15:20:36 +01:00
$errormsg = $langs -> trans ( " ErrorFailedToWriteInDir " );
2018-10-04 13:10:48 +02:00
return - 1 ;
}
// Print headers and global mysql config vars
$sqlhead = '' ;
$sqlhead .= " -- " . $db :: LABEL . " dump via php with Dolibarr " . DOL_VERSION . "
--
-- Host : " . $db->db ->host_info. " Database : " . $db->database_name . "
-- ------------------------------------------------------
-- Server version " . $db->db ->server_info. "
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */ ;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */ ;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */ ;
/*!40101 SET NAMES utf8 */ ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */ ;
/*!40103 SET TIME_ZONE='+00:00' */ ;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */ ;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */ ;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */ ;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */ ;
" ;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_disable_fk " )) {
$sqlhead .= " SET FOREIGN_KEY_CHECKS=0; \n " ;
}
2018-10-04 13:10:48 +02:00
//$sqlhead .= "SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";\n";
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_use_transaction " )) {
$sqlhead .= " SET AUTOCOMMIT=0; \n START TRANSACTION; \n " ;
}
2018-10-04 13:10:48 +02:00
fwrite ( $handle , $sqlhead );
$ignore = '' ;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_sql_ignore " )) {
$ignore = 'IGNORE ' ;
}
2018-10-04 13:10:48 +02:00
$delayed = '' ;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_delayed " )) {
$delayed = 'DELAYED ' ;
}
2018-10-04 13:10:48 +02:00
// Process each table and print their definition + their datas
2021-02-23 22:03:23 +01:00
foreach ( $tables as $table ) {
2018-10-04 13:10:48 +02:00
// Saving the table structure
fwrite ( $handle , " \n -- \n -- Table structure for table ` " . $table . " ` \n -- \n " );
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_drop " )) {
fwrite ( $handle , " DROP TABLE IF EXISTS ` " . $table . " `; \n " ); // Dropping table if exists prior to re create it
}
2019-01-27 11:55:16 +01:00
fwrite ( $handle , " /*!40101 SET @saved_cs_client = @@character_set_client */; \n " );
fwrite ( $handle , " /*!40101 SET character_set_client = utf8 */; \n " );
2019-12-18 15:20:36 +01:00
$resqldrop = $db -> query ( 'SHOW CREATE TABLE ' . $table );
2018-10-04 13:10:48 +02:00
$row2 = $db -> fetch_row ( $resqldrop );
2021-02-23 22:03:23 +01:00
if ( empty ( $row2 [ 1 ])) {
2018-10-04 13:10:48 +02:00
fwrite ( $handle , " \n -- WARNING: Show create table " . $table . " return empy string when it should not. \n " );
2020-05-21 15:05:19 +02:00
} else {
2019-01-27 11:55:16 +01:00
fwrite ( $handle , $row2 [ 1 ] . " ; \n " );
2018-10-04 13:10:48 +02:00
//fwrite($handle,"/*!40101 SET character_set_client = @saved_cs_client */;\n\n");
// Dumping the data (locking the table and disabling the keys check while doing the process)
fwrite ( $handle , " \n -- \n -- Dumping data for table ` " . $table . " ` \n -- \n " );
2021-02-23 22:03:23 +01:00
if ( ! GETPOST ( " nobin_nolocks " )) {
fwrite ( $handle , " LOCK TABLES ` " . $table . " ` WRITE; \n " ); // Lock the table before inserting data (when the data will be imported back)
}
if ( GETPOST ( " nobin_disable_fk " )) {
fwrite ( $handle , " ALTER TABLE ` " . $table . " ` DISABLE KEYS; \n " );
} else {
fwrite ( $handle , " /*!40000 ALTER TABLE ` " . $table . " ` DISABLE KEYS */; \n " );
}
2018-10-04 13:10:48 +02:00
2019-12-18 15:20:36 +01:00
$sql = 'SELECT * FROM ' . $table ; // Here SELECT * is allowed because we don't have definition of columns to take
2018-10-04 13:10:48 +02:00
$result = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
while ( $row = $db -> fetch_row ( $result )) {
2018-10-04 13:10:48 +02:00
// For each row of data we print a line of INSERT
2019-01-27 11:55:16 +01:00
fwrite ( $handle , 'INSERT ' . $delayed . $ignore . 'INTO `' . $table . '` VALUES (' );
2018-10-04 13:10:48 +02:00
$columns = count ( $row );
2019-12-18 15:20:36 +01:00
for ( $j = 0 ; $j < $columns ; $j ++ ) {
2018-10-04 13:10:48 +02:00
// Processing each columns of the row to ensure that we correctly save the value (eg: add quotes for string - in fact we add quotes for everything, it's easier)
if ( $row [ $j ] == null && ! is_string ( $row [ $j ])) {
// IMPORTANT: if the field is NULL we set it NULL
$row [ $j ] = 'NULL' ;
2019-12-18 15:20:36 +01:00
} elseif ( is_string ( $row [ $j ]) && $row [ $j ] == '' ) {
2018-10-04 13:10:48 +02:00
// if it's an empty string, we set it as an empty string
$row [ $j ] = " '' " ;
2019-12-18 15:20:36 +01:00
} elseif ( is_numeric ( $row [ $j ]) && ! strcmp ( $row [ $j ], $row [ $j ] + 0 )) { // test if it's a numeric type and the numeric version ($nb+0) == string version (eg: if we have 01, it's probably not a number but rather a string, else it would not have any leading 0)
2018-10-04 13:10:48 +02:00
// if it's a number, we return it as-is
// $row[$j] = $row[$j];
} else { // else for all other cases we escape the value and put quotes around
$row [ $j ] = addslashes ( $row [ $j ]);
$row [ $j ] = preg_replace ( " # \n # " , " \\ n " , $row [ $j ]);
$row [ $j ] = " ' " . $row [ $j ] . " ' " ;
}
}
2019-01-27 11:55:16 +01:00
fwrite ( $handle , implode ( ',' , $row ) . " ); \n " );
2018-10-04 13:10:48 +02:00
}
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_disable_fk " )) {
fwrite ( $handle , " ALTER TABLE ` " . $table . " ` ENABLE KEYS; \n " ); // Enabling back the keys/index checking
}
if ( ! GETPOST ( " nobin_nolocks " )) {
fwrite ( $handle , " UNLOCK TABLES; \n " ); // Unlocking the table
}
2019-01-27 11:55:16 +01:00
fwrite ( $handle , " \n \n \n " );
2018-10-04 13:10:48 +02:00
}
}
/* Backup Procedure structure*/
/*
$result = $db -> query ( 'SHOW PROCEDURE STATUS' );
if ( $db -> num_rows ( $result ) > 0 )
{
while ( $row = $db -> fetch_row ( $result )) { $procedures [] = $row [ 1 ]; }
foreach ( $procedures as $proc )
{
fwrite ( $handle , " DELIMITER $ $\n\n " );
fwrite ( $handle , " DROP PROCEDURE IF EXISTS ' $name '.' $proc ' $ $\n " );
$resqlcreateproc = $db -> query ( " SHOW CREATE PROCEDURE ' $proc ' " );
$row2 = $db -> fetch_row ( $resqlcreateproc );
fwrite ( $handle , " \n " . $row2 [ 2 ] . " $ $\n\n " );
fwrite ( $handle , " DELIMITER ; \n \n " );
}
}
*/
/* Backup Procedure structure*/
// Write the footer (restore the previous database settings)
2019-12-18 15:20:36 +01:00
$sqlfooter = " \n \n " ;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( " nobin_use_transaction " )) {
$sqlfooter .= " COMMIT; \n " ;
}
if ( GETPOST ( " nobin_disable_fk " )) {
$sqlfooter .= " SET FOREIGN_KEY_CHECKS=1; \n " ;
}
2019-12-18 15:20:36 +01:00
$sqlfooter .= " \n \n -- Dump completed on " . date ( 'Y-m-d G-i-s' );
2018-10-04 13:10:48 +02:00
fwrite ( $handle , $sqlfooter );
fclose ( $handle );
return 1 ;
}
2018-10-04 20:23:58 +02:00
}