mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-15 12:36:32 +00:00
Handle Surrogates If Read
It is probably very anal of me to do this. Excel does it. I can't see it happening in the wild.
This commit is contained in:
@@ -305,7 +305,7 @@ class StringHelper
|
||||
*/
|
||||
public static function controlCharacterOOXML2PHP(string $textValue): string
|
||||
{
|
||||
return Preg::replaceCallback('/_x[0-9A-F]{4}_/', self::toOutChar(...), $textValue);
|
||||
return Preg::replaceCallback('/_x[0-9A-F]{4}_(_xD[CDEF][0-9A-F]{2}_)?/', self::toOutChar(...), $textValue);
|
||||
}
|
||||
|
||||
private static function toHexVal(string $char): int
|
||||
@@ -322,12 +322,27 @@ class StringHelper
|
||||
{
|
||||
/** @var string */
|
||||
$chars = $match[0];
|
||||
$t = ((self::toHexVal($chars[2]) << 12)
|
||||
$h = ((self::toHexVal($chars[2]) << 12)
|
||||
| (self::toHexVal($chars[3]) << 8)
|
||||
| (self::toHexVal($chars[4]) << 4)
|
||||
| (self::toHexVal($chars[5])));
|
||||
if (strlen($chars) === 7) { // no low surrogate
|
||||
if ($chars[2] === 'D' && in_array($chars[3], ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F'], true)) {
|
||||
return mb_chr(0xFFFD, 'UTF-8');
|
||||
}
|
||||
|
||||
return mb_chr($t, 'UTF-8');
|
||||
return mb_chr($h, 'UTF-8');
|
||||
}
|
||||
if ($chars[2] !== 'D' || !in_array($chars[3], ['8', '9', 'A', 'B'], true)) {
|
||||
return mb_chr($h, 'UTF-8') . mb_chr(0xFFFD, 'UTF-8');
|
||||
}
|
||||
$l = ((self::toHexVal($chars[9]) << 12)
|
||||
| (self::toHexVal($chars[10]) << 8)
|
||||
| (self::toHexVal($chars[11]) << 4)
|
||||
| (self::toHexVal($chars[12])));
|
||||
$result = 0x10000 + ($h - 0xD800) * 0x400 + ($l - 0xDC00);
|
||||
|
||||
return mb_chr($result, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,7 @@ class UnderscoreTest extends AbstractFunctional
|
||||
if ($data === false) {
|
||||
self::fail('Unable to read file');
|
||||
} else {
|
||||
self::assertStringContainsString('count="4"', $data);
|
||||
self::assertStringContainsString('count="7"', $data);
|
||||
self::assertStringContainsString(
|
||||
"<t>line_x000D_\nwith_x000D_\nbreaks</t>",
|
||||
$data
|
||||
@@ -82,6 +82,9 @@ class UnderscoreTest extends AbstractFunctional
|
||||
$data
|
||||
);
|
||||
self::assertStringContainsString('<t>_xC1EF_</t>', $data);
|
||||
self::assertStringContainsString('<t>_xD801__xDC05_</t>', $data);
|
||||
self::assertStringContainsString('<t>_xD801__x0038_</t>', $data);
|
||||
self::assertStringContainsString('<t>_x0039__xDC05_</t>', $data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +105,12 @@ class UnderscoreTest extends AbstractFunctional
|
||||
self::assertSame($expected, $sheet->getCell('A3')->getValue());
|
||||
$expected = '쇯';
|
||||
self::assertSame($expected, $sheet->getCell('A4')->getValue());
|
||||
$expected = '𐐅';
|
||||
self::assertSame($expected, $sheet->getCell('A5')->getValue(), 'outside BMP');
|
||||
$expected = '�8';
|
||||
self::assertSame($expected, $sheet->getCell('A6')->getValue(), 'high surrogate without low');
|
||||
$expected = '9�';
|
||||
self::assertSame($expected, $sheet->getCell('A7')->getValue(), 'low surrogate without high');
|
||||
}
|
||||
|
||||
public function testX000dNotPreserved(): void
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user