FIX Test that pdf is real pdf before using imagick. Report by Jonathan

Chambre <jonathan.chambre@helx.io>
This commit is contained in:
Laurent Destailleur 2026-04-23 12:09:55 +02:00
parent c9ccd54306
commit 9b6368b2a9
2 changed files with 86 additions and 4 deletions

View file

@ -2223,7 +2223,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $updatesessionor
*/
function dol_remove_file_process($filenb, $donotupdatesession = 0, $donotdeletefile = 1, $trackid = '')
{
global $db, $user, $conf, $langs, $_FILES;
global $db, $langs;
$keytodelete = $filenb;
$keytodelete--;
@ -2412,7 +2412,7 @@ function deleteFilesIntoDatabaseIndex($dir, $file, $mode = 'uploaded', $object =
$rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $dir);
if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) { // If not a temporary directory. TODO Does this test work ?
$filename = basename($file);
//$filename = basename($file);
$rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
$rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
@ -2449,12 +2449,49 @@ function deleteFilesIntoDatabaseIndex($dir, $file, $mode = 'uploaded', $object =
}
}
/**
* Check if a file is a real PDF file by checking its signature and its MIME type.
* Testing first char may be enough. No need to use the finfo_file().
*
* @param string $filePath File path to check
* @return bool True if the file is a real PDF, false otherwise.
*/
function isRealPdf(string $filePath)
{
if (!is_file($filePath) || !is_readable($filePath)) {
return false;
}
// Open file
$handle = fopen($filePath, 'rb');
if (!$handle) {
return false;
}
$header = fread($handle, 5);
fclose($handle);
if ($header !== '%PDF-') {
return false;
}
// Check using finfo_file
/*
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $filePath);
finfo_close($finfo);
if ($mime !== 'application/pdf') {
return false;
}
*/
return true;
}
/**
* Convert an image file or a PDF into another image format.
* Convert a PDF file into another image format.
* This need Imagick php extension. You can use dol_imageResizeOrCrop() for a function that need GD.
*
* @param string $fileinput Input file name
* @param string $fileinput Input full path name
* @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 $page Page number if we convert a PDF into png
@ -2466,6 +2503,14 @@ function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = ''
if (class_exists('Imagick')) {
$image = new Imagick();
try {
// Imagick may have a support for Magick Scripting Language (MSL) that allows to run execution code with some files like SVG. So we need to check
// that file is really a PDF file.
// Note: The Imagick policy options can be disabled into /etc/ImageMagick*/policy.xml.
if (!isRealPdf($fileinput)) {
dol_syslog("We try to convert a PDF file with name ".$fileinput." but it is not a real PDF file (hack attempt ?).", LOG_WARNING);
return -4;
}
$filetoconvert = $fileinput.(($page != '') ? '['.$page.']' : '');
//var_dump($filetoconvert);
$ret = $image->readImage($filetoconvert);
@ -2474,6 +2519,7 @@ function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = ''
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." conversion in /etc/ImageMagick*/policy.xml): ".$e->getMessage(), LOG_WARNING);
return 0;
}
if ($ret) {
$ret = $image->setImageFormat($ext);
if ($ret) {

View file

@ -556,4 +556,40 @@ class FilesLibTest extends CommonClassTest
print __METHOD__." result=".$result."\n";
$this->assertTrue($result, 'move of directory with directory without rename needed in directory');
}
/**
* testDolConvertFile
*
* @return void
*/
public function testDolConvertFile()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
// If imagick not installed, you can install it with
// apt install imagemagick php7.4-imagick
if (class_exists('Imagick')) {
$filepdf = dirname(__FILE__).'/imgsvgwithjs.svg';
$fileimage = $conf->admin->dir_temp.'/testdolconvert.png';
$result = dol_convert_file($filepdf, 'png', $fileimage, '0'); // Convert first page of PDF into a file _preview.png
print __METHOD__." result=".$result."\n";
$this->assertEquals(-4, $result, 'Convert of PDF file '.$filepdf.' into image should have return an error because it is not a real PDF, but this did not happen.');
$filepdf = dirname(__FILE__).'/file_pdf_with_js.pdf.jpg';
$result = dol_copy($filepdf, $conf->admin->dir_temp.'/testdolconvert.pdf');
$fileimage = $conf->admin->dir_temp.'/testdolconvert.png';
$result = dol_convert_file($filepdf, 'png', $fileimage, '0'); // Convert first page of PDF into a file _preview.png
print __METHOD__." result=".$result."\n";
$this->assertEquals(1, $result, 'Failed to convert PDF file into '.$fileimage.', error '.$result);
} else {
print __METHOD__." skipped because Imagick is not installed.\n";
}
}
}