forked from PHPOffice/PhpSpreadsheet
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unexpected Charset Possible for Currency Symbol
We do not recommend it, but users can call the Php function `setlocale` and that might affect the character used as currency symbol. A problem arises when the caller to setlocale does not specify a character set - in that case, Php will attempt to return its `localeconv()` values in a single-byte character set rather than UTF-8. This is particularly problematic for currency symbols. PhpSpreadsheet till now has accepted such a character, and that can lead to corrupt spreadsheets. It is changed to validate the currency symbol as UTF-8, and fall back to a different choice if not (e.g. EUR rather than 0x80, which is how the euro symbol is depicted in Win-1252). An additional problem arises because Linux systems seem to return the alternate symbol with a trailing blank, but Windows systems do not. To allow callers to get a consistent result, a parameter is added to `getCurrencyCode` which will trim or not (default) the currency code.
- Loading branch information
Showing
3 changed files
with
87 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
tests/PhpSpreadsheetTests/Shared/StringHelperLocaleTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace PhpOffice\PhpSpreadsheetTests\Shared; | ||
|
||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper; | ||
use PHPUnit\Framework\Attributes; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
// separate processes due to setLocale | ||
#[Attributes\RunTestsInSeparateProcesses] | ||
class StringHelperLocaleTest extends TestCase | ||
{ | ||
/** | ||
* @var false|string | ||
*/ | ||
private $currentLocale; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->currentLocale = setlocale(LC_ALL, '0'); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
if (is_string($this->currentLocale)) { | ||
setlocale(LC_ALL, $this->currentLocale); | ||
} | ||
StringHelper::setCurrencyCode(null); | ||
} | ||
|
||
public function testCurrency(): void | ||
{ | ||
if (!setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu.utf8')) { | ||
self::markTestSkipped('Unable to set German UTF8 locale for testing.'); | ||
} | ||
$result = StringHelper::getCurrencyCode(); | ||
self::assertSame('€', $result); | ||
if (!setlocale(LC_ALL, 'en_us')) { | ||
self::markTestSkipped('Unable to set US locale for testing.'); | ||
} | ||
$result = StringHelper::getCurrencyCode(); | ||
self::assertSame('€', $result, 'result persists despite locale change'); | ||
StringHelper::setCurrencyCode(null); | ||
$result = StringHelper::getCurrencyCode(); | ||
self::assertSame('$', $result, 'locale now used'); | ||
StringHelper::setCurrencyCode(null); | ||
if (!setlocale(LC_ALL, 'deu_deu', 'de_DE')) { | ||
self::markTestSkipped('Unable to set German single-byte locale for testing.'); | ||
} | ||
// Seems like Linux returns trailing blank, Win doesn't | ||
$result = StringHelper::getCurrencyCode(true); // trim if alt symbol is used | ||
self::assertSame('EUR', $result, 'non-UTF8 result ignored'); | ||
} | ||
} |