diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index bc0d957ac..0e4ded346 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -5,6 +5,7 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ +use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; @@ -13,7 +14,6 @@ use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory; -use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\WebPage\Page; use Combodo\iTop\Application\WebPage\WebPage; @@ -55,6 +55,8 @@ class CSVBulkExport extends TabularBulkExport $this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('charset', 'UTF-8', true, 'raw_data')); $this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true); + $this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER); + $sDateFormatRadio = utils::ReadParam('csv_date_format_radio', ''); switch ($sDateFormatRadio) { case 'default': @@ -223,6 +225,10 @@ class CSVBulkExport extends TabularBulkExport $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); + $oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security')); + $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity)); + $oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport()); + $oP->add_ready_script( <<GetAsCSV($sAttCode), '"'); } + + // If the option to ignore Excel sanitization is not set or explicitly set to false, apply sanitization + if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + return ExportHelper::SanitizeField($sRet, $this->aStatusInfo['text_qualifier'] ?? ''); + } + + // The option to ignore Excel sanitization is explicitly set to true: return the raw value without sanitization return $sRet; } @@ -337,6 +350,12 @@ EOF $sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']); } } + + // If the option to ignore Excel sanitization is not set or absent, sanitize the field + if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + $sField = ExportHelper::SanitizeField($sField, $this->aStatusInfo['text_qualifier']); + } + if ($this->aStatusInfo['charset'] != 'UTF-8') { // Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string // and thus to convert field by field and not the whole row or file at once (see ticket N°991) diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index 6f4632962..8cf9be44e 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -5,13 +5,13 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ +use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory; -use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\WebPage\Page; use Combodo\iTop\Application\WebPage\WebPage; @@ -63,6 +63,8 @@ class ExcelBulkExport extends TabularBulkExport // Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise $this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data'); } + + $this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER); } public function EnumFormParts() @@ -121,6 +123,10 @@ class ExcelBulkExport extends TabularBulkExport $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); + $oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security')); + $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity)); + $oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport()); + $oP->add_ready_script( <<aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + return ExportHelper::SanitizeField($sRet, ''); + } + return $sRet; } diff --git a/css/backoffice/application/bulk/_all.scss b/css/backoffice/application/bulk/_all.scss index 495ed376f..fcd615d40 100644 --- a/css/backoffice/application/bulk/_all.scss +++ b/css/backoffice/application/bulk/_all.scss @@ -4,3 +4,4 @@ */ @import "bulk-modify"; +@import "bulk-export"; diff --git a/css/backoffice/application/bulk/_bulk-export.scss b/css/backoffice/application/bulk/_bulk-export.scss new file mode 100644 index 000000000..b595b6c82 --- /dev/null +++ b/css/backoffice/application/bulk/_bulk-export.scss @@ -0,0 +1,10 @@ +/* + * @copyright Copyright (C) 2010-2026 Combodo SAS + * @license http://opensource.org/licenses/AGPL-3.0 + */ + +#form_part_csv_options:has(#ibo-sanitize-excel-export--input:checked), #form_part_xlsx_options:has(#ibo-sanitize-excel-export--input:checked){ + #ibo-sanitize-excel-export--alert { + display: none; + } +} \ No newline at end of file diff --git a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig index 59cfee2bd..e5eb1308e 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig @@ -11,7 +11,7 @@