From be68682fd176124372f135578dfd1f68813ddd64 Mon Sep 17 00:00:00 2001 From: Marek Zajac Date: Wed, 5 May 2021 17:24:58 +0200 Subject: [PATCH] [Console] Fix Windows code page support --- .../Console/Helper/QuestionHelper.php | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 72880f6a69cca..92a4c7d0fb525 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -110,11 +110,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()) { @@ -514,7 +509,10 @@ private function isInteractiveInput($inputStream): bool private function readInput($inputStream, Question $question) { if (!$question->isMultiline()) { - return fgets($inputStream, 4096); + $cp = $this->setIOCodepage(); + $ret = fgets($inputStream, 4096); + + return $this->resetIOCodepage($cp, $ret); } $multiLineStreamReader = $this->cloneInputStream($inputStream); @@ -523,6 +521,7 @@ private function readInput($inputStream, Question $question) } $ret = ''; + $cp = $this->setIOCodepage(); while (false !== ($char = fgetc($multiLineStreamReader))) { if (\PHP_EOL === "{$ret}{$char}") { break; @@ -530,7 +529,37 @@ private function readInput($inputStream, Question $question) $ret .= $char; } - return $ret; + return $this->resetIOCodepage($cp, $ret); + } + + /** + * Set 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; + } + + /** + * Set console I/O to the specified code page and convert the user input. + */ + private function resetIOCodepage(int $cp, string $input): string + { + if (\function_exists('sapi_windows_cp_set') && 0 < $cp) { + sapi_windows_cp_set($cp); + $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input); + } + + return $input; } /**