Skip to content

Commit

Permalink
bug #41210 [Console] Fix Windows code page support (orkan)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.4 branch.

Discussion
----------

[Console] Fix Windows code page support

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #37385, Fix #35842, Fix #36324, Fix #37495, Fix #37278
| License       | MIT

Corrects mojibake problem on Windows where an OEM code page was applied to an input string and then messed with PHP.internal_encoding setting used by the script. This caused strings with different encodings to be displayed on the console output.

Commits
-------

41452785c6 [Console] Fix Windows code page support
  • Loading branch information
nicolas-grekas committed May 13, 2021
2 parents 1ab187a + 5809712 commit 1b15ca1
Showing 1 changed file with 39 additions and 5 deletions.
44 changes: 39 additions & 5 deletions Helper/QuestionHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,6 @@ private function doAsk(OutputInterface $output, Question $question)
$inputStream = $this->inputStream ?: \STDIN;
$autocomplete = $question->getAutocompleterCallback();

if (\function_exists('sapi_windows_cp_set')) {
// Codepage used by cmd.exe on Windows to allow special characters (éàüñ).
@sapi_windows_cp_set(1252);
}

if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
$ret = false;
if ($question->isHidden()) {
Expand All @@ -127,7 +122,9 @@ private function doAsk(OutputInterface $output, Question $question)
}

if (false === $ret) {
$cp = $this->setIOCodepage();
$ret = fgets($inputStream, 4096);
$ret = $this->resetIOCodepage($cp, $ret);
if (false === $ret) {
throw new MissingInputException('Aborted.');
}
Expand Down Expand Up @@ -503,4 +500,41 @@ private function isInteractiveInput($inputStream): bool

return self::$stdinIsInteractive = 1 !== $status;
}

/**
* Sets console I/O to the host code page.
*
* @return int Previous code page in IBM/EBCDIC format
*/
private function setIOCodepage(): int
{
if (\function_exists('sapi_windows_cp_set')) {
$cp = sapi_windows_cp_get();
sapi_windows_cp_set(sapi_windows_cp_get('oem'));

return $cp;
}

return 0;
}

/**
* Sets console I/O to the specified code page and converts the user input.
*
* @param string|false $input
*
* @return string|false
*/
private function resetIOCodepage(int $cp, $input)
{
if (0 !== $cp) {
sapi_windows_cp_set($cp);

if (false !== $input && '' !== $input) {
$input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input);
}
}

return $input;
}
}

0 comments on commit 1b15ca1

Please sign in to comment.