From 1ca7697ad215529e42a90ead591c6ec1370a049b Mon Sep 17 00:00:00 2001 From: enured <enis.nuredini@uzh.ch> Date: Tue, 6 Dec 2022 13:20:59 +0100 Subject: [PATCH] F15111: Implemented new special column name _saveZip. New feature to generate and save zip with given sources. refs #15111 --- Documentation/Report.rst | 29 ++++++++++++++++++++++ extension/Classes/Core/Constants.php | 3 +++ extension/Classes/Core/Report/Download.php | 17 ++++++++++--- extension/Classes/Core/Report/Report.php | 19 ++++++++++---- 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/Documentation/Report.rst b/Documentation/Report.rst index 5d40a5800..8a5c7845a 100644 --- a/Documentation/Report.rst +++ b/Documentation/Report.rst @@ -639,6 +639,8 @@ Summary: +------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | _savePdf | :ref:`column-save-pdf` - pre render PDF files | +------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| _saveZip | :ref:`column-save-zip` - Generate and save zip file. | ++------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | _excel | :ref:`excel-export` - creates Excel exports based on QFQ Report queries, optional with pre uploaded Excel template files | +------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | _yank | :ref:`copyToClipboard`. Shortcut version of the link interface | @@ -1569,6 +1571,33 @@ Example:: SELECT "d:fileadmin/result.pdf|F:fileadmin/_temp_/test.pdf|U:id=test&--orientation=landscape" AS _savePdf +.. _column-save-zip: + +Column: _saveZip +^^^^^^^^^^^^^^^^ + +Generated ZIP can be stored directly on the server with this functionality. The link query consists of the following parameters: + +* One or more element sources (such as ``F:``, ``U:``, ``p:``, see :ref:`download-parameter-files`), including possible wkhtmltopdf parameters +* Any element sources given with ``F:`` is accepted for insert in zip file. +* Element sources given with ``U:`` or ``p:`` will first generated as pdf files before they are added to zip. Generated pdf files will be named "file-#.pdf". +* The export filename and path as ``d:`` - for security reasons, this path has to start with *fileadmin/* and end with *.zip*. + +Tips: + +* Please note that this option does not render anything in the front end, but is executed each time it is parsed. + You may want to add a check to prevent multiple execution. +* It is not advised to generate the filename with user input for security reasons. +* If the target file already exists it will be overwriten. To save individual files, choose a new filename, + for example by adding a timestamp. + +Example:: + + SELECT "d:fileadmin/result.zip|F:fileadmin/_temp_/test.pdf" AS _saveZip + SELECT "d:fileadmin/result.zip|F:fileadmin/_temp_/test.pdf|U:id=test&--orientation=landscape" AS _saveZip + SELECT "d:fileadmin/result.zip|F:fileadmin/_temp_/test.pdf|F:fileadmin/_temp_/test2.xlsx|U:id=test&--orientation=landscape" AS _saveZip + + .. _column-thumbnail: Column: _thumbnail diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php index edb255cf8..99157da3e 100644 --- a/extension/Classes/Core/Constants.php +++ b/extension/Classes/Core/Constants.php @@ -247,6 +247,7 @@ const ERROR_TOO_MANY_PARAMETER = 1409; const ERROR_INVALID_SAVE_PDF_FILENAME = 1410; const ERROR_TWIG_COLUMN_NOT_UNIQUE = 1411; const ERROR_DOUBLE_DEFINITION = 1412; +const ERROR_INVALID_SAVE_ZIP_FILENAME = 1413; // Upload const ERROR_UPLOAD = 1500; @@ -1729,6 +1730,7 @@ const COLUMN_YANK = 'yank'; const COLUMN_PDF = 'pdf'; const COLUMN_SAVE_PDF = 'savePdf'; +const COLUMN_SAVE_ZIP = 'saveZip'; const COLUMN_FILE = 'file'; const COLUMN_ZIP = 'zip'; const COLUMN_MONITOR = 'monitor'; @@ -1790,6 +1792,7 @@ const DOWNLOAD_MODE_FILE = 'file'; const DOWNLOAD_MODE_PDF = 'pdf'; const DOWNLOAD_MODE_QFQPDF = 'qfqpdf'; const DOWNLOAD_MODE_SAVE_PDF = 'save-pdf'; +const DOWNLOAD_MODE_SAVE_ZIP = 'save-zip'; const DOWNLOAD_MODE_EXCEL = 'excel'; const DOWNLOAD_MODE_ZIP = 'zip'; const DOWNLOAD_MODE_THUMBNAIL = 'thumbnail'; diff --git a/extension/Classes/Core/Report/Download.php b/extension/Classes/Core/Report/Download.php index f84b9a2d8..f04565ee0 100644 --- a/extension/Classes/Core/Report/Download.php +++ b/extension/Classes/Core/Report/Download.php @@ -529,6 +529,11 @@ class Download { case TOKEN_URL_PARAM: case TOKEN_PAGE: case TOKEN_UID: + // Fake download mode pdf if saveZip is used + if ($downloadMode === DOWNLOAD_MODE_SAVE_ZIP) { + $downloadMode = DOWNLOAD_MODE_PDF; + } + $urlParam = OnString::splitParam($value, $rcArgs, $rcSipEncode); $urlParamString = KeyValueStringParser::unparse($urlParam, '=', '&'); if ($rcSipEncode) { @@ -584,7 +589,7 @@ class Download { * @return string ZIP filename - has to be deleted later. * @throws \DownloadException */ - private function zipFiles(array $files) { + private function zipFiles(array $files, $downloadMode = DOWNLOAD_MODE_ZIP) { $zipFile = HelperFile::tempnam(); if (false === $zipFile) { @@ -599,6 +604,11 @@ class Download { $len = strlen(TMP_FILE_PREFIX); $ii = 1; + $extension = ''; + // If download mode saveZip is given, then set extension for these on the fly generated pdfs + if ($downloadMode === DOWNLOAD_MODE_SAVE_ZIP) { + $extension = '.pdf'; + } foreach ($files as $item) { // a) $item: fileadmin/dog.jpg, b) $item: fileamdmin/doc.jpg:directory1/directory2/dog.jpg $arr = explode(PARAM_TOKEN_DELIMITER, $item); @@ -608,7 +618,7 @@ class Download { // If the final filename is a QFQ tempfile and still contains TMP_FILE_PREFIX: remove the prefix and replace it by 'file-?' if (substr($localName, 0, $len) == TMP_FILE_PREFIX) { - $localName = 'file-' . $ii; + $localName = 'file-' . $ii . $extension; $ii++; } @@ -740,7 +750,8 @@ class Download { // Export, Concat File(s) switch ($downloadMode) { case DOWNLOAD_MODE_ZIP: - $filename = $this->zipFiles($srcFiles); + case DOWNLOAD_MODE_SAVE_ZIP: + $filename = $this->zipFiles($srcFiles, $downloadMode); if (empty($vars[DOWNLOAD_EXPORT_FILENAME])) { $vars[DOWNLOAD_EXPORT_FILENAME] = basename($filename); } diff --git a/extension/Classes/Core/Report/Report.php b/extension/Classes/Core/Report/Report.php index 3d515622b..a2fcc6f13 100644 --- a/extension/Classes/Core/Report/Report.php +++ b/extension/Classes/Core/Report/Report.php @@ -1142,21 +1142,30 @@ class Report { $content .= $this->link->renderLink($linkValue); break; + case COLUMN_SAVE_ZIP: case COLUMN_SAVE_PDF: $tokenGiven = []; $vars = $this->link->fillParameter(array(), $columnValue, $tokenGiven); - $vars[DOWNLOAD_MODE] = DOWNLOAD_MODE_PDF; + if ($columnName === COLUMN_SAVE_ZIP) { + $vars[DOWNLOAD_MODE] = DOWNLOAD_MODE_SAVE_ZIP; + $extension = '.zip'; + $errorCode = ERROR_INVALID_SAVE_ZIP_FILENAME; + } else { + $vars[DOWNLOAD_MODE] = DOWNLOAD_MODE_PDF; + $extension = '.pdf'; + $errorCode = ERROR_INVALID_SAVE_PDF_FILENAME; + } $vars[SIP_DOWNLOAD_PARAMETER] = implode(PARAM_DELIMITER, $vars[NAME_COLLECT_ELEMENTS]); - // Save file with specified export filename + // Save file with specified export5715 filename $pathFileName = $vars[DOWNLOAD_EXPORT_FILENAME]; $sanitizedFileName = Sanitize::safeFilename($pathFileName, false, true); if ($pathFileName == '' || substr($pathFileName, 0, strlen("fileadmin/")) !== "fileadmin/" || - substr($pathFileName, -4) !== '.pdf') { - throw new \UserReportException("savePdf filenames need to be in the fileadmin/ directory and end in .pdf for security reasons.", ERROR_INVALID_SAVE_PDF_FILENAME); + substr($pathFileName, -4) !== $extension) { + throw new \UserReportException("'$columnName' filenames need to be in the fileadmin/ directory and end in '$extension' for security reasons.", $errorCode); } elseif ($pathFileName !== $sanitizedFileName) { - throw new \UserReportException("The provided filename '$pathFileName' does not meet sanitize criteria. Use '$sanitizedFileName' instead.", ERROR_INVALID_SAVE_PDF_FILENAME); + throw new \UserReportException("The provided filename '$pathFileName' does not meet sanitize criteria. Use '$sanitizedFileName' instead.", $errorCode); } else { $vars[DOWNLOAD_EXPORT_FILENAME] = $sanitizedFileName; $download = new Download(); -- GitLab