#!/usr/bin/env php * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file dev/build/generate_filelist_xml.php * \ingroup dev * \brief This script create a xml checksum file */ if (!defined('NOREQUIREDB')) { define('NOREQUIREDB', '1'); // Do not create database handler $db } $sapi_type = php_sapi_name(); $script_file = basename(__FILE__); $path = dirname(__FILE__).'/'; // Test if batch mode if (substr($sapi_type, 0, 3) == 'cgi') { echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; exit(1); } require_once $path."../../htdocs/master.inc.php"; require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php"; /* * Main */ $includecustom = 0; $includeconstants = array(); $buildzip = 0; if (empty($argv[1])) { print '***** '.$script_file.' *****'."\n"; print "Generate the file filelist-x.y.z[-mybuild].xml with signature of files. "; print "This includes the 3 sections:\n"; print "- dolibarr_htdocs_dir\n"; print "- dolibarr_scripts_dir\n"; print "- dolibarr_unalterable_files (only files inside the scope of the unalterable module)\n"; print "\n"; print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value] [buildzip=1]\n"; print "Example: ".$script_file." release=6.0.0 includecustom=1 includeconstant=FR:INVOICE_CAN_ALWAYS_BE_REMOVED:0 includeconstant=all:MAILING_NO_USING_PHPMAIL:1\n"; exit(1); } $i = 0; $result = array(); while ($i < $argc) { if (!empty($argv[$i])) { parse_str($argv[$i], $result); // set all params $release, $includecustom, $includeconstant, $buildzip ... } if (!empty($result["release"])) { $release = $result["release"]; } if (!empty($result["includecustom"])) { $includecustom = $result["includecustom"]; } if (!empty($result["includeconstant"])) { $includeconstants[$i] = $result["includeconstant"]; } if (!empty($result["buildzip"])) { $buildzip = 1; } if (preg_match('/includeconstant=/', strval($argv[$i]))) { $tmp = explode(':', $result['includeconstant'], 3); // $includeconstant has been set with previous parse_str() if (count($tmp) != 3) { print "Error: Bad parameter includeconstant=".$result['includeconstant'] ."\n"; exit(1); } $includeconstants[$tmp[0]][$tmp[1]] = $tmp[2]; } $i++; } if (empty($release)) { print "Error: Missing release parameter\n"; print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value]\n"; exit(2); } $savrelease = $release; // If release is auto, we take current version $tmpver = explode('-', $release, 2); if ($tmpver[0] == 'auto') { $release = DOL_VERSION; if (!empty($tmpver[1]) && $tmpver[0] == 'auto') { $release .= '-'.$tmpver[1]; } } if (empty($includecustom)) { $tmpverbis = explode('-', $release, 2); if (empty($tmpverbis[1])) { if (DOL_VERSION != $tmpverbis[0] && $savrelease != 'auto') { print 'Error: When parameter "includecustom" is not set and there is no suffix in release parameter, version declared into filefunc.in.php ('.DOL_VERSION.') must be exact same value than "release" parameter ('.$tmpverbis[0].')'."\n"; print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value]\n"; exit(3); } } else { $tmpverter = explode('-', DOL_VERSION, 2); if ($tmpverter[0] != $tmpverbis[0]) { print 'Error: When parameter "includecustom" is not set, version declared into filefunc.in.php ('.DOL_VERSION.') must have value without prefix ('.$tmpverter[0].') that is exact same value than "release" parameter ('.$tmpverbis[0].')'."\n"; print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value]\n"; exit(4); } } } else { if (!preg_match('/'.preg_quote(DOL_VERSION, '/').'-/', $release)) { print 'Error: When parameter "includecustom" is set, version declared into filefunc.inc.php ('.DOL_VERSION.') must be used with a suffix into "release" parameter (ex: '.DOL_VERSION.'-mydistrib).'."\n"; print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value]\n"; exit(5); } } print "Working on files into : ".DOL_DOCUMENT_ROOT."\n"; print "Release : ".$release."\n"; print "Include custom dir in signature : ".(empty($includecustom) ? 'no' : 'yes')."\n"; print "Include constants in signature : ".(empty($includeconstants) ? 'none' : ''); foreach ($includeconstants as $countrycode => $tmp) { foreach ($tmp as $constname => $constvalue) { print $constname.'='.$constvalue." "; } } print "\n"; //$outputfile=dirname(__FILE__).'/../htdocs/install/filelist-'.$release.'.xml'; $outputdir = dirname(dirname(dirname(__FILE__))).'/htdocs/install'; print 'Delete current files '.$outputdir.'/filelist*.xml*'."\n"; dol_delete_file($outputdir.'/filelist*.xml*', 0, 1, 1); $checksumconcat = array(); $outputfile = $outputdir.'/filelist-'.$release.'.xml'; $fp = fopen($outputfile, 'w'); if (empty($fp)) { print 'Failed to open file '.$outputfile."\n"; exit(6); } $gitcommit = 'seetag'; $branchname = preg_replace('/^(\d+\.\d+)\..*$/', '\1', $release); // Keep only x.y into x.y.z $fileforgit = dirname(dirname(dirname(__FILE__))).'/.git/refs/heads/'.$branchname; print "Try to get last commit ID from file ".$fileforgit."\n"; $fileforgitcontent = ''; if (file_exists($fileforgit)) { $fileforgitcontent = file_get_contents($fileforgit); } if (empty($fileforgitcontent)) { print "Failed to get the last commit ID. Are you on the branch for the release (branch name ".$branchname.") ?\n"; } $gitcommit = trim($fileforgitcontent); fputs($fp, ''."\n"); fputs($fp, ''."\n"); $needtoclose = 0; foreach ($includeconstants as $countrycode => $tmp) { fputs($fp, ''."\n"); foreach ($tmp as $constname => $constvalue) { $valueforchecksum = (empty($constvalue) ? '0' : $constvalue); $checksumconcat[] = $valueforchecksum; fputs($fp, ' '.$valueforchecksum.''."\n"); } fputs($fp, ''."\n\n"); } fputs($fp, ''."\n"); // Define qualified files (must be same than into generate_filelist_xml.php and in api_setup.class.php) $regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$'; $regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|escpos-php\/doc|escpos-php\/example|escpos-php\/test|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs $files = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; foreach ($files as $filetmp) { $file = $filetmp['fullname']; //$newdir = str_replace(dirname(__FILE__).'/../htdocs', '', dirname($file)); $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ''."\n"); asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); fputs($fp, ''."\n\n"); // Add the checksum for the part in scripts $checksumconcat = array(); fputs($fp, ''."\n"); $regextoinclude = '\.(php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$'; $regextoexclude = '(custom|documents|conf|install)$'; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../scripts/', 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../scripts', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ''."\n"); asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); fputs($fp, ''."\n\n"); // Add the checksum for the files into the scope of the unalterable system (record, read, export) $checksumconcat = array(); fputs($fp, ''."\n"); $regextoinclude = '(\.php|\.sql)$'; $regextoexclude = ''; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../htdocs/blockedlog', 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } // Add the SQL file $regextoinclude = 'llx_blockedlog.*(\.php|\.sql)$'; $regextoexclude = ''; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../htdocs/install/mysql/tables', 'files', 0, $regextoinclude, $regextoexclude, 'fullname'); foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } // Add the trigger file $file = dirname(__FILE__).'/../../htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php'; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } // Add the interfaces.class.php file $file = dirname(__FILE__).'/../../htdocs/core/class/interfaces.class.php'; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; //$needtoclose = 1; // close will be done in next filethat is in same dir } if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } // Add the commontrigger.class.php file $file = dirname(__FILE__).'/../../htdocs/core/class/commontrigger.class.php'; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; $needtoclose = 1; } $needtoclose = 1; // This is the last file if (filetype($file) == "file") { $md5 = md5_file($file); $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } if ($needtoclose) { fputs($fp, ' '."\n"); $needtoclose = 0; } fputs($fp, ''."\n"); asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); fputs($fp, ''."\n\n"); // End of file fputs($fp, ''."\n"); fclose($fp); if (empty($buildzip)) { print "File ".$outputfile." generated\n"; } else { if ($buildzip == '1' || $buildzip == 'zip') { $result = dol_compress_file($outputfile, $outputfile.'.zip', 'zip'); if ($result > 0) { dol_delete_file($outputfile); print "File ".$outputfile.".zip generated\n"; } } elseif ($buildzip == '2' || $buildzip == 'gz') { $result = dol_compress_file($outputfile, $outputfile.'.gz', 'gz'); if ($result > 0) { dol_delete_file($outputfile); print "File ".$outputfile.".gz generated\n"; } } } exit(0);