Skip to content

Commit

Permalink
Fix Xlsx Read Ignoring Comments (#3655)
Browse files Browse the repository at this point in the history
* Fix Xlsx Read Ignoring Comments

Fix #3654. Several places in Reader Xlsx make a truthy test for `$zip->locateName()`. However, zero is a legitimate result which should not be treated as false. Change all existing tests in this form to test for (in)equality to false. For the record, there is no existing exposure of this kind in Reader Ods.

* Absolute Path In Printer Settings File

Another unexpected use of an absolute path in a rels file. Easily fixed, but the test file is 7+ MB. I have asked the problem reporter to try to find a smaller file.

* Reduced Size of Test File

It was 7.8MB. I manipulated the file to replace all the comment backgrounds in column AN with a single image, much smaller than the existing ones. This reduced the file size by over 6MB. It's still larger than I'd like, but might be acceptable. (AN121 uses a different background than the others just so that I could check that they would all be copied faithfully.)
  • Loading branch information
oleibman authored Aug 22, 2023
1 parent dcf7415 commit b879cdd
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 11 deletions.
23 changes: 12 additions & 11 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
$hyperlinkReader = new Hyperlinks($docSheet);
// Locate hyperlink relations
$relationsFileName = dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels';
if ($zip->locateName($relationsFileName)) {
if ($zip->locateName($relationsFileName) !== false) {
$relsWorksheet = $this->loadZip($relationsFileName, Namespaces::RELATIONSHIPS);
$hyperlinkReader->readHyperlinks($relsWorksheet);
}
Expand All @@ -1066,7 +1066,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
if (!$this->readDataOnly) {
// Locate comment relations
$commentRelations = dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels';
if ($zip->locateName($commentRelations)) {
if ($zip->locateName($commentRelations) !== false) {
$relsWorksheet = $this->loadZip($commentRelations, Namespaces::RELATIONSHIPS);
foreach ($relsWorksheet->Relationship as $elex) {
$ele = self::getAttributes($elex);
Expand Down Expand Up @@ -1128,7 +1128,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
$drowingImages = [];
$VMLDrawingsRelations = dirname($relPath) . '/_rels/' . basename($relPath) . '.rels';
$vmlDrawingContents[$relName] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $relPath));
if ($zip->locateName($VMLDrawingsRelations)) {
if ($zip->locateName($VMLDrawingsRelations) !== false) {
$relsVMLDrawing = $this->loadZip($VMLDrawingsRelations, Namespaces::RELATIONSHIPS);
foreach ($relsVMLDrawing->Relationship as $elex) {
$ele = self::getAttributes($elex);
Expand Down Expand Up @@ -1192,7 +1192,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
if (isset($drowingImages[$fillImageRelId])) {
$objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
$objDrawing->setName($fillImageTitle);
$imagePath = str_replace('../', 'xl/', $drowingImages[$fillImageRelId]);
$imagePath = str_replace(['../', '/xl/'], 'xl/', $drowingImages[$fillImageRelId]);
$objDrawing->setPath(
'zip://' . File::realpath($filename) . '#' . $imagePath,
true,
Expand Down Expand Up @@ -1249,7 +1249,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
if ($vmlHfRidAttr !== null && isset($vmlHfRidAttr['id'])) {
$vmlHfRid = (string) $vmlHfRidAttr['id'][0];
}
if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels') !== false) {
$relsWorksheet = $this->loadZipNoNamespace(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels', Namespaces::RELATIONSHIPS);
$vmlRelationship = '';

Expand Down Expand Up @@ -1328,7 +1328,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
if (substr($drawingFilename, 0, 8) === '/xl//xl/') {
$drawingFilename = substr($drawingFilename, 5);
}
if ($zip->locateName($drawingFilename)) {
if ($zip->locateName($drawingFilename) !== false) {
$relsWorksheet = $this->loadZipNoNamespace($drawingFilename, Namespaces::RELATIONSHIPS);
$drawings = [];
foreach ($relsWorksheet->Relationship as $ele) {
Expand Down Expand Up @@ -2095,7 +2095,7 @@ private static function getLockValue(SimpleXmlElement $protection, string $key):
private function readFormControlProperties(Spreadsheet $excel, string $dir, string $fileWorksheet, Worksheet $docSheet, array &$unparsedLoadedData): void
{
$zip = $this->zip;
if (!$zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels') === false) {
return;
}

Expand All @@ -2122,7 +2122,7 @@ private function readFormControlProperties(Spreadsheet $excel, string $dir, stri
private function readPrinterSettings(Spreadsheet $excel, string $dir, string $fileWorksheet, Worksheet $docSheet, array &$unparsedLoadedData): void
{
$zip = $this->zip;
if (!$zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels') === false) {
return;
}

Expand All @@ -2142,8 +2142,9 @@ private function readPrinterSettings(Spreadsheet $excel, string $dir, string $fi
$rId = $rId . 'ps'; // rIdXXX, add 'ps' suffix to avoid identical resource identifier collision with unparsed vmlDrawing
}
$unparsedPrinterSettings[$rId] = [];
$unparsedPrinterSettings[$rId]['filePath'] = self::dirAdd("$dir/$fileWorksheet", $printerSettings['Target']);
$unparsedPrinterSettings[$rId]['relFilePath'] = (string) $printerSettings['Target'];
$target = (string) str_replace('/xl/', '../', (string) $printerSettings['Target']);
$unparsedPrinterSettings[$rId]['filePath'] = self::dirAdd("$dir/$fileWorksheet", $target);
$unparsedPrinterSettings[$rId]['relFilePath'] = $target;
$unparsedPrinterSettings[$rId]['content'] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $unparsedPrinterSettings[$rId]['filePath']));
}
unset($unparsedPrinterSettings);
Expand Down Expand Up @@ -2238,7 +2239,7 @@ private function readTablesInTablesFile(
$tablePartRel = (string) $relation['id'];
$relationsFileName = dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels';

if ($zip->locateName($relationsFileName)) {
if ($zip->locateName($relationsFileName) !== false) {
$relsTableReferences = $this->loadZip($relationsFileName, Namespaces::RELATIONSHIPS);
foreach ($relsTableReferences->Relationship as $relationship) {
$relationshipAttributes = self::getAttributes($relationship, '');
Expand Down
47 changes: 47 additions & 0 deletions tests/PhpSpreadsheetTests/Reader/Xlsx/CommentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,51 @@ public function testIssue2316(): void
self::assertStringContainsString('若為宅配物流僅能選「純配送」', $commentString);
self::assertSame('Anderson Chen 陳宗棠', $comment->getAuthor());
}

public function testIssue3654(): void
{
// Reader was ignoring comments.
$filename = 'tests/data/Reader/XLSX/issue.3654.xlsx';
$reader = new Xlsx();
$spreadsheet = $reader->load($filename);

$sheet = $spreadsheet->getActiveSheet();
$expectedComments = [
'X4', 'AD4', 'AN4',
'X5', 'AD5', 'AN5',
'AN6', // X6 and AD6 are uncommented on original
'X7', 'AD7', 'AN7',
'X8', 'AD8', 'AN8',
'X9', 'AD9', 'AN9',
'X10', 'AD10', 'AN10',
'X11', 'AD11', 'AN11',
'X12', 'AD12', 'AN12',
];
self::assertEquals($expectedComments, array_keys($sheet->getComments()));
self::assertStringContainsString('.png', $sheet->getComment('X4')->getBackgroundImage()->getPath());
self::assertStringContainsString('.jpeg', $sheet->getComment('AN12')->getBackgroundImage()->getPath());
$spreadsheet->disconnectWorksheets();
}

public function testIssue3654c(): void
{
// Reader was ignoring comments.
$filename = 'tests/data/Reader/XLSX/issue.3654c.xlsx';
$reader = new Xlsx();
$spreadsheet = $reader->load($filename);

$sheet = $spreadsheet->getActiveSheet();
$comments = $sheet->getComments();
self::assertCount(326, $comments);
self::assertStringContainsString('.png', $sheet->getComment('X4')->getBackgroundImage()->getPath());
self::assertStringContainsString('.jpeg', $sheet->getComment('AN12')->getBackgroundImage()->getPath());

// Spreadsheet generated by Flexcel. Make sure we managed
// to locate printerSettings since it used an unexpected link.
$pageSetupRel = $spreadsheet->getUnparsedLoadedData()['sheets']['Worksheet']['pageSetupRelId'] ?? '';
self::assertSame('flId1ps', $pageSetupRel);
$pageSetupPath = $spreadsheet->getUnparsedLoadedData()['sheets']['Worksheet']['printerSettings'][substr($pageSetupRel, 3)]['filePath'] ?? '';
self::assertSame('xl/printerSettings/printerSettings1.bin', $pageSetupPath);
$spreadsheet->disconnectWorksheets();
}
}
Binary file added tests/data/Reader/XLSX/issue.3654.xlsx
Binary file not shown.
Binary file added tests/data/Reader/XLSX/issue.3654c.xlsx
Binary file not shown.

0 comments on commit b879cdd

Please sign in to comment.