diff --git a/Documentation/Installation.rst b/Documentation/Installation.rst index 463e928f1cb2aca711a2d2e94ffd1c8d7d55cbfc..ea4c94e38e855552a3212c62f139386f848b4060 100644 --- a/Documentation/Installation.rst +++ b/Documentation/Installation.rst @@ -46,6 +46,8 @@ The following features are only tested / supported on linux hosts: * PDF decrypt (used for merge with pdfunite) - command `qpdf`. * PDF decrypt (used for merge with pdfunite) - command `gs` - in case `qpdf` is not successful. * Mime type detection for uploads - command `file`. +* Split PDF into JPG - command `convert`. +* Repair PDF - command `pdftocairo`. .. _`preparation`: @@ -401,7 +403,11 @@ Extension Manager: QFQ Configuration +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | cmdInkscape | inkscape | If inkscape is not available, specify an empty string. | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| cmdConvert | convert | GraphicsMagics 'convert' is recommended. | +| cmdConvert | convert | Image-/GraphicsMagics 'convert' is recommended. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| cmdPdf2svg | pdf2svg | Convert PDF to SVG. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| cmdPdftocairo | pdftocairo | Poppler based. | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | cmdWkhtmltopdf | /usr/bin/wkhtmltopdf | PathFilename of wkhtmltopdf. Optional variables like LD_LIBRARY_PATH=... | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php index 453bdbce67a573bd9b0efe41f3669e74862ece38..67386fa3c848d0d9b986f05b279d317e51ad01c4 100644 --- a/extension/Classes/Core/Constants.php +++ b/extension/Classes/Core/Constants.php @@ -259,7 +259,7 @@ const ERROR_IO_CHMOD = 1314; const ERROR_IO_READ_FILE = 1315; const ERROR_IO_WRITE_FILE = 1316; -const ERROR_PDF2SVG = 1320; +const ERROR_PDF_SPLIT = 1320; const ERROR_PDF2JPEG = 1321; //Report @@ -647,6 +647,8 @@ const SYSTEM_SHOW_ID_IN_FORM_TITLE = 'showIdInFormTitle'; const SYSTEM_CMD_WKHTMLTOPDF = 'cmdWkhtmltopdf'; const SYSTEM_CMD_INKSCAPE = 'cmdInkscape'; const SYSTEM_CMD_CONVERT = 'cmdConvert'; +const SYSTEM_CMD_PDF2SVG = 'cmdPdf2svg'; +const SYSTEM_CMD_PDFTOCAIRO = 'cmdPdftocairo'; const SYSTEM_CMD_QPDF = 'cmdQpdf'; const SYSTEM_CMD_GS = 'cmdGs'; const SYSTEM_CMD_PDFUNITE = 'cmdPdfunite'; diff --git a/extension/Classes/Core/Helper/HelperFile.php b/extension/Classes/Core/Helper/HelperFile.php index a9b1935276d6c9d7bcfc8286bd722dc84045514a..0a766480f2c6201f7c64136a968fbc62a94f71a2 100644 --- a/extension/Classes/Core/Helper/HelperFile.php +++ b/extension/Classes/Core/Helper/HelperFile.php @@ -336,7 +336,7 @@ class HelperFile { public static function rename($oldname, $newname) { if (false === @rename($oldname, $newname)) { - $msg = self::errorGetLastAsString() . " - rename($oldname ,$newname)"; + $msg = self::errorGetLastAsString() . " - rename($oldname, $newname)"; throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_TO_DEVELOPER => $msg]), ERROR_IO_RENAME); } diff --git a/extension/Classes/Core/Save.php b/extension/Classes/Core/Save.php index 4aa8efff81bebad23365bea5839b5abb67866bb6..2965c0914d2567396c2d0da66ed2b18d4958a9af 100644 --- a/extension/Classes/Core/Save.php +++ b/extension/Classes/Core/Save.php @@ -1262,13 +1262,10 @@ class Save { switch ($fileSplitType) { case FE_FILE_SPLIT_SVG: - $cmd = 'pdf2svg "' . $newSrc . '" "' . $fileNameDest . '" all'; + $cmd = $this->buildPdf2svg($newSrc, $fileNameDest); break; case FE_FILE_SPLIT_JPEG: - if ($fileSplitTypeOptions == '') { - $fileSplitTypeOptions = FE_FILE_SPLIT_OPTIONS_JPEG; - } - $cmd = "convert $fileSplitTypeOptions '$newSrc' '$fileNameDest'"; + $cmd = $this->buildConvertSplit($newSrc, $fileNameDest, $fileSplitTypeOptions); break; default: throw new \UserFormException("Unknown 'fileSplit' type: " . $formElement[FE_FILE_SPLIT], ERROR_UNKNOWN_TOKEN); @@ -1276,13 +1273,30 @@ class Save { // Split PDF HelperFile::chdir($tempDir); - $output = Support::qfqExec($cmd, $rc); + $cnt = 0; + do { + $output = Support::qfqExec($cmd, $rc); + $cnt++; + + if ($rc != 0) { + // Split failed + $cmdRepair = $this->buildPdftocairo($newSrc, $newSrc . '.1'); + $output .= PHP_EOL . $cmdRepair . PHP_EOL; + $output .= Support::qfqExec($cmdRepair, $rc1); + if ($rc1 != 0) { + // Repair failed too: stop here. + break; + } + HelperFile::rename($newSrc . '.1', $newSrc); + } + } while ($rc != 0 && $cnt < 2); + HelperFile::chdir($cwd); if ($rc != 0) { throw new \UserFormException( - json_encode([ERROR_MESSAGE_TO_USER => 'pdf2svg failed', ERROR_MESSAGE_TO_DEVELOPER => "[$cwd][cmd=$cmd]$output"]), - ERROR_PDF2SVG); + json_encode([ERROR_MESSAGE_TO_USER => 'pdf split failed', ERROR_MESSAGE_TO_DEVELOPER => "[$cwd][cmd=$cmd]$output"]), + ERROR_PDF_SPLIT); } $files = Helperfile::getSplitFileNames($tempDir); @@ -1326,6 +1340,54 @@ class Save { HelperFile::rmdir($tempDir); } + /** + * @param $src + * @param $dest + * @return string + * @throws \CodeException + * @throws \DbException + * @throws \UserFormException + * @throws \UserReportException + */ + private function buildPdf2svg($src, $dest) { + + $cmd = $this->store->getVar(SYSTEM_CMD_PDF2SVG, STORE_SYSTEM); + return "$cmd '$src' '$dest' all"; + } + + /** + * @param $src + * @param $dest + * @return string + * @throws \CodeException + * @throws \DbException + * @throws \UserFormException + * @throws \UserReportException + */ + private function buildPdftocairo($src, $dest) { + + $cmd = $this->store->getVar(SYSTEM_CMD_PDFTOCAIRO, STORE_SYSTEM); + return "$cmd -pdf '$src' '$dest'"; + } + + /** + * @param $src + * @param $dest + * @param $options + * @return string + * @throws \CodeException + * @throws \DbException + * @throws \UserFormException + * @throws \UserReportException + */ + private function buildConvertSplit($src, $dest, $options) { + if ($options == '') { + $options = FE_FILE_SPLIT_OPTIONS_JPEG; + } + $cmd = $this->store->getVar(SYSTEM_CMD_CONVERT, STORE_SYSTEM); + return "$cmd $options '$src' '$dest'"; + } + /** * Create/update or delete the slave record. * diff --git a/extension/Classes/Core/Store/Config.php b/extension/Classes/Core/Store/Config.php index 4b7123aff676c676e9d2f61446c6c5164f4fa28e..19ff8b920b99b049772b47706a8ea43ff418788a 100644 --- a/extension/Classes/Core/Store/Config.php +++ b/extension/Classes/Core/Store/Config.php @@ -374,6 +374,8 @@ class Config { SYSTEM_CMD_WKHTMLTOPDF => '/opt/wkhtmltox/bin/wkhtmltopdf', SYSTEM_CMD_INKSCAPE => 'inkscape', SYSTEM_CMD_CONVERT => 'convert', + SYSTEM_CMD_PDF2SVG => 'pdf2svg', + SYSTEM_CMD_PDFTOCAIRO => 'pdftocairo', SYSTEM_CMD_QPDF => 'qpdf', SYSTEM_CMD_GS => 'gs', SYSTEM_CMD_PDFUNITE => 'pdfunite', diff --git a/extension/Tests/Unit/Core/Store/StoreTest.php b/extension/Tests/Unit/Core/Store/StoreTest.php index ea15d5bbbfc4ae6fc64d08a54056691f7ed6832c..14d450ba3a447854da7851d63c701fa6172e18ed 100644 --- a/extension/Tests/Unit/Core/Store/StoreTest.php +++ b/extension/Tests/Unit/Core/Store/StoreTest.php @@ -345,6 +345,8 @@ class StoreTest extends TestCase { SYSTEM_THUMBNAIL_DIR_PUBLIC => SYSTEM_THUMBNAIL_DIR_PUBLIC_DEFAULT, SYSTEM_CMD_INKSCAPE => 'inkscape', SYSTEM_CMD_CONVERT => 'convert', + SYSTEM_CMD_PDF2SVG => 'pdf2svg', + SYSTEM_CMD_PDFTOCAIRO => 'pdftocairo', SYSTEM_CMD_WKHTMLTOPDF => '/opt/wkhtmltox/bin/wkhtmltopdf', SYSTEM_DATE_FORMAT => 'yyyy-mm-dd', SYSTEM_THROW_GENERAL_ERROR => 'no', diff --git a/extension/ext_conf_template.txt b/extension/ext_conf_template.txt index 284da08199edc8117b458ad7b4d31198df13b0fd..c8b7d4c07e53fb7c4712701e7eeedb47c4bbf983 100644 --- a/extension/ext_conf_template.txt +++ b/extension/ext_conf_template.txt @@ -22,9 +22,15 @@ thumbnailDirPublic = typo3temp/qfqThumbnail # cat=config/config; type=string; label=Command 'inkscape':Default is 'inkscape'. Will be used to convert SVG to images (png). An empty string disables `inkscape`. If it is not available, `convert` will be used instead. cmdInkscape = inkscape -# cat=config/config; type=string; label=Command 'convert':Default is 'convert'. Will be used to convert images to thumbnails. GraphicsMagics 'convert' is recommended. +# cat=config/config; type=string; label=Command 'convert':Default is 'convert'. Will be used to convert images to thumbnails and to split PDF to JPEG. cmdConvert = convert +# cat=config/config; type=string; label=Command 'pdf2svg':Default is 'pdf2svg'. Will be used to convert PDF to SVG. +cmdPdf2svg = pdf2svg + +# cat=config/config; type=string; label=Command 'pdftocairo':Default is 'pdftocairo'. Will be used to repair broken PDFs to be splitted via convert. +cmdPdftocairo = pdftocairo + # cat=config/config; type=string; label=Command 'wkhtmltopdf':Default is '/opt/wkhtmltox/bin/wkhtmltopdf'. Command to convert a HTML page to a PDF. cmdWkhtmltopdf = /opt/wkhtmltox/bin/wkhtmltopdf