Merge branch '5.1'
* 5.1: [HttpClient][CurlHttpClient] Fix http_version option usage [HttpClient] fix parsing response headers in CurlResponse [PropertyAccess] Remove inflector component [Console] Do not check for "stty" using "exec" if that function is disabled [Console] always use stty when possible to ask hidden questions
This commit is contained in:
commit
901e938da3
@ -36,6 +36,7 @@ class QuestionHelper extends Helper
|
||||
private $inputStream;
|
||||
private static $shell;
|
||||
private static $stty = true;
|
||||
private static $stdinIsInteractive;
|
||||
|
||||
/**
|
||||
* Asks a question to the user.
|
||||
@ -418,10 +419,16 @@ class QuestionHelper extends Helper
|
||||
|
||||
if (self::$stty && Terminal::hasSttyAvailable()) {
|
||||
$sttyMode = shell_exec('stty -g');
|
||||
|
||||
shell_exec('stty -echo');
|
||||
} elseif ($this->isInteractiveInput($inputStream)) {
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
}
|
||||
|
||||
$value = fgets($inputStream, 4096);
|
||||
|
||||
if (self::$stty && Terminal::hasSttyAvailable()) {
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
}
|
||||
|
||||
if (false === $value) {
|
||||
throw new MissingInputException('Aborted.');
|
||||
@ -434,19 +441,6 @@ class QuestionHelper extends Helper
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (false !== $shell = $this->getShell()) {
|
||||
$readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
|
||||
$command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword' 2> /dev/null", $shell, $readCmd);
|
||||
$sCommand = shell_exec($command);
|
||||
$value = $trimmable ? rtrim($sCommand) : $sCommand;
|
||||
$output->writeln('');
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an attempt.
|
||||
*
|
||||
@ -472,56 +466,35 @@ class QuestionHelper extends Helper
|
||||
throw $e;
|
||||
} catch (\Exception $error) {
|
||||
}
|
||||
|
||||
$attempts = $attempts ?? -(int) $this->askForever();
|
||||
}
|
||||
|
||||
throw $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid unix shell.
|
||||
*
|
||||
* @return string|bool The valid shell name, false in case no valid shell is found
|
||||
*/
|
||||
private function getShell()
|
||||
private function isInteractiveInput($inputStream): bool
|
||||
{
|
||||
if (null !== self::$shell) {
|
||||
return self::$shell;
|
||||
if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$shell = false;
|
||||
|
||||
if (file_exists('/usr/bin/env')) {
|
||||
// handle other OSs with bash/zsh/ksh/csh if available to hide the answer
|
||||
$test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
|
||||
foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) {
|
||||
if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
|
||||
self::$shell = $sh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$shell;
|
||||
}
|
||||
|
||||
private function askForever(): bool
|
||||
{
|
||||
$inputStream = $this->inputStream ?: fopen('php://stdin', 'r');
|
||||
|
||||
if ('php://stdin' !== (stream_get_meta_data($inputStream)['url'] ?? null)) {
|
||||
return true;
|
||||
if (null !== self::$stdinIsInteractive) {
|
||||
return self::$stdinIsInteractive;
|
||||
}
|
||||
|
||||
if (\function_exists('stream_isatty')) {
|
||||
return stream_isatty($inputStream);
|
||||
return self::$stdinIsInteractive = stream_isatty(fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
if (\function_exists('posix_isatty')) {
|
||||
return posix_isatty($inputStream);
|
||||
return self::$stdinIsInteractive = posix_isatty(fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!\function_exists('exec')) {
|
||||
return self::$stdinIsInteractive = true;
|
||||
}
|
||||
|
||||
exec('stty 2> /dev/null', $output, $status);
|
||||
|
||||
return self::$stdinIsInteractive = 1 !== $status;
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,11 @@ class Terminal
|
||||
return self::$stty;
|
||||
}
|
||||
|
||||
// skip check if exec function is disabled
|
||||
if (!\function_exists('exec')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
exec('stty 2>&1', $output, $exitcode);
|
||||
|
||||
return self::$stty = 0 === $exitcode;
|
||||
|
@ -138,12 +138,12 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
|
||||
CURLOPT_CERTINFO => $options['capture_peer_cert_chain'],
|
||||
];
|
||||
|
||||
if (\defined('CURL_VERSION_HTTP2') && (CURL_VERSION_HTTP2 & self::$curlVersion['features']) && ('https:' === $scheme || 2.0 === (float) $options['http_version'])) {
|
||||
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
||||
} elseif (1.0 === (float) $options['http_version']) {
|
||||
if (1.0 === (float) $options['http_version']) {
|
||||
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
||||
} elseif (1.1 === (float) $options['http_version']) {
|
||||
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
||||
} elseif (\defined('CURL_VERSION_HTTP2') && (CURL_VERSION_HTTP2 & self::$curlVersion['features']) && ('https:' === $scheme || 2.0 === (float) $options['http_version'])) {
|
||||
$curlopts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
||||
}
|
||||
|
||||
if (isset($options['auth_ntlm'])) {
|
||||
|
@ -46,7 +46,6 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
|
||||
$this->multi = $multi;
|
||||
|
||||
if (\is_resource($ch) || $ch instanceof \CurlHandle) {
|
||||
unset($multi->handlesActivity[(int) $ch]);
|
||||
$this->handle = $ch;
|
||||
$this->debugBuffer = fopen('php://temp', 'w+');
|
||||
if (0x074000 === $curlVersion) {
|
||||
@ -77,7 +76,17 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger): int {
|
||||
return self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
|
||||
if (0 !== substr_compare($data, "\r\n", -2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$len = 0;
|
||||
|
||||
foreach (explode("\r\n", substr($data, 0, -2)) as $data) {
|
||||
$len += 2 + self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
|
||||
}
|
||||
|
||||
return $len;
|
||||
});
|
||||
|
||||
if (null === $options) {
|
||||
@ -365,10 +374,10 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
|
||||
return \strlen($data); // Ignore HTTP trailers
|
||||
}
|
||||
|
||||
if ("\r\n" !== $data) {
|
||||
if ('' !== $data) {
|
||||
try {
|
||||
// Regular header line: add it to the list
|
||||
self::addResponseHeaders([substr($data, 0, -2)], $info, $headers);
|
||||
self::addResponseHeaders([$data], $info, $headers);
|
||||
} catch (TransportException $e) {
|
||||
$multi->handlesActivity[$id][] = null;
|
||||
$multi->handlesActivity[$id][] = $e;
|
||||
@ -378,7 +387,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
|
||||
|
||||
if (0 !== strpos($data, 'HTTP/')) {
|
||||
if (0 === stripos($data, 'Location:')) {
|
||||
$location = trim(substr($data, 9, -2));
|
||||
$location = trim(substr($data, 9));
|
||||
}
|
||||
|
||||
return \strlen($data);
|
||||
|
@ -17,7 +17,6 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/inflector": "^4.4|^5.0",
|
||||
"symfony/polyfill-php80": "^1.15",
|
||||
"symfony/property-info": "^5.1.1"
|
||||
},
|
||||
|
Reference in New Issue
Block a user