Skip to content

Commit 994b072

Browse files
authored
Merge pull request #4540 from oleibman/issue4537
Don't Use htmlspecialchars When Formatting Xml
2 parents 1439211 + e005fdb commit 994b072

File tree

5 files changed

+143
-6
lines changed

5 files changed

+143
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2929

3030
### Fixed
3131

32+
- Do not use htmlspecialchars when formatting XML. [Issue #4537](https://github.com/PHPOffice/PhpSpreadsheet/issues/4537) [PR #4540](https://github.com/PHPOffice/PhpSpreadsheet/pull/4540)
3233
- Writer Html/Pdf support RTL alignment of tables. [Issue #1104](https://github.com/PHPOffice/PhpSpreadsheet/issues/1104) [PR #4535](https://github.com/PHPOffice/PhpSpreadsheet/pull/4535)
3334
- Xlsx Reader use dynamic arrays if spreadsheet did so. [PR #4533](https://github.com/PHPOffice/PhpSpreadsheet/pull/4533)
3435
- Ods Reader Nested table-row. [Issue #4528](https://github.com/PHPOffice/PhpSpreadsheet/issues/4528) [Issue #2507](https://github.com/PHPOffice/PhpSpreadsheet/issues/2507) [PR #4531](https://github.com/PHPOffice/PhpSpreadsheet/pull/4531)

src/PhpSpreadsheet/Shared/XMLWriter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,6 @@ public function writeRawData($rawTextData): bool
9191
$rawTextData = implode("\n", $rawTextData);
9292
}
9393

94-
return $this->writeRaw(htmlspecialchars($rawTextData ?? ''));
94+
return $this->text($rawTextData ?? '');
9595
}
9696
}

src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use PhpOffice\PhpSpreadsheet\Cell\DataType;
1111
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
1212
use PhpOffice\PhpSpreadsheet\RichText\RichText;
13-
use PhpOffice\PhpSpreadsheet\Settings;
1413
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
1514
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
1615
use PhpOffice\PhpSpreadsheet\Style\Conditional;
@@ -1440,10 +1439,7 @@ private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, Ri
14401439
$objWriter->writeElement(
14411440
't',
14421441
StringHelper::controlCharacterPHP2OOXML(
1443-
htmlspecialchars(
1444-
$cellValue,
1445-
Settings::htmlEntityFlags()
1446-
)
1442+
$cellValue
14471443
)
14481444
);
14491445
$objWriter->endElement();
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Ods;
6+
7+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8+
use PhpOffice\PhpSpreadsheet\Reader\Ods as OdsReader;
9+
use PhpOffice\PhpSpreadsheet\RichText\RichText;
10+
use PhpOffice\PhpSpreadsheet\RichText\TextElement;
11+
use PhpOffice\PhpSpreadsheet\Shared\File;
12+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
13+
use PhpOffice\PhpSpreadsheet\Writer\Ods as OdsWriter;
14+
use PHPUnit\Framework\TestCase;
15+
16+
class Issue4537Test extends TestCase
17+
{
18+
private string $outputFilename = '';
19+
20+
protected function tearDown(): void
21+
{
22+
if ($this->outputFilename !== '') {
23+
unlink($this->outputFilename);
24+
$this->outputFilename = '';
25+
}
26+
}
27+
28+
public function testBackgroundImage(): void
29+
{
30+
$this->outputFilename = File::temporaryFilename();
31+
$testString = "\"He\": '<?>'";
32+
$spreadsheet = new Spreadsheet();
33+
$sheet = $spreadsheet->getActiveSheet();
34+
$sheet->getCell('A1')->setValueExplicit($testString, DataType::TYPE_INLINE);
35+
$sheet->getCell('A2')->setValue($testString);
36+
$richText = new RichText();
37+
$richText->addText(new TextElement($testString));
38+
$sheet->getCell('A3')->setValue($richText);
39+
$writer = new OdsWriter($spreadsheet);
40+
$writer->save($this->outputFilename);
41+
$spreadsheet->disconnectWorksheets();
42+
43+
$reader = new OdsReader();
44+
$reloadedSpreadsheet = $reader->load($this->outputFilename);
45+
$rsheet = $reloadedSpreadsheet->getActiveSheet();
46+
self::assertSame($testString, $rsheet->getCell('A1')->getValueString());
47+
self::assertSame($testString, $rsheet->getCell('A2')->getValueString());
48+
self::assertSame($testString, $rsheet->getCell('A3')->getValueString());
49+
$reloadedSpreadsheet->disconnectWorksheets();
50+
51+
$file = 'zip://';
52+
$file .= $this->outputFilename;
53+
$file .= '#content.xml';
54+
$data = file_get_contents($file);
55+
// expected does not escape apostrophes
56+
$expected = '<text:p>&quot;He&quot;: \'&lt;?&gt;\'</text:p>';
57+
if ($data === false) {
58+
self::fail('Unable to read content file');
59+
} else {
60+
$count = substr_count($data, $expected);
61+
self::assertSame(3, $count);
62+
}
63+
}
64+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
9+
use PhpOffice\PhpSpreadsheet\RichText\RichText;
10+
use PhpOffice\PhpSpreadsheet\RichText\TextElement;
11+
use PhpOffice\PhpSpreadsheet\Shared\File;
12+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
13+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
14+
use PHPUnit\Framework\TestCase;
15+
16+
class Issue4537Test extends TestCase
17+
{
18+
private string $outputFilename = '';
19+
20+
protected function tearDown(): void
21+
{
22+
if ($this->outputFilename !== '') {
23+
unlink($this->outputFilename);
24+
$this->outputFilename = '';
25+
}
26+
}
27+
28+
public function testBackgroundImage(): void
29+
{
30+
$this->outputFilename = File::temporaryFilename();
31+
$testString = "\"He\": '<?>'";
32+
$spreadsheet = new Spreadsheet();
33+
$sheet = $spreadsheet->getActiveSheet();
34+
$sheet->getCell('A1')->setValueExplicit($testString, DataType::TYPE_INLINE);
35+
$sheet->getCell('A2')->setValue($testString);
36+
$richText = new RichText();
37+
$richText->addText(new TextElement($testString));
38+
$sheet->getCell('A3')->setValue($richText);
39+
$writer = new XlsxWriter($spreadsheet);
40+
$writer->save($this->outputFilename);
41+
$spreadsheet->disconnectWorksheets();
42+
43+
$reader = new XlsxReader();
44+
$reloadedSpreadsheet = $reader->load($this->outputFilename);
45+
$rsheet = $reloadedSpreadsheet->getActiveSheet();
46+
self::assertSame($testString, $rsheet->getCell('A1')->getValueString());
47+
self::assertSame($testString, $rsheet->getCell('A2')->getValueString());
48+
self::assertSame($testString, $rsheet->getCell('A3')->getValueString());
49+
$reloadedSpreadsheet->disconnectWorksheets();
50+
51+
$file = 'zip://';
52+
$file .= $this->outputFilename;
53+
$file .= '#xl/worksheets/sheet1.xml';
54+
$data = file_get_contents($file);
55+
// expected, and expected1/2 below, do not escape apostrophes
56+
$expected = 't="inlineStr"><is><t>&quot;He&quot;: \'&lt;?&gt;\'</t></is>';
57+
if ($data === false) {
58+
self::fail('Unable to read worksheets file');
59+
} else {
60+
self::assertStringContainsString($expected, $data, 'inline string');
61+
}
62+
63+
$file = 'zip://';
64+
$file .= $this->outputFilename;
65+
$file .= '#xl/sharedStrings.xml';
66+
$data = file_get_contents($file);
67+
$expected1 = '<t>&quot;He&quot;: \'&lt;?&gt;\'</t>';
68+
$expected2 = '<t xml:space="preserve">&quot;He&quot;: \'&lt;?&gt;\'</t>';
69+
if ($data === false) {
70+
self::fail('Unable to read sharedStrings file');
71+
} else {
72+
self::assertStringContainsString($expected1, $data, 'string');
73+
self::assertStringContainsString($expected2, $data, 'rich text');
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)