diff --git a/libraries/src/Http/Transport/SocketTransport.php b/libraries/src/Http/Transport/SocketTransport.php index 4124d2e8c0036..5abbe0cfb6010 100644 --- a/libraries/src/Http/Transport/SocketTransport.php +++ b/libraries/src/Http/Transport/SocketTransport.php @@ -230,29 +230,29 @@ protected function connect(UriInterface $uri, $timeout = null) } // Capture PHP errors - $php_errormsg = ''; - $track_errors = ini_get('track_errors'); - ini_set('track_errors', true); + // PHP sends a warning if the uri does not exist; we silence it and throw an exception instead. + set_error_handler(static function ($errno, $err) { + throw new \Exception($err); + }, \E_WARNING); - // PHP sends a warning if the uri does not exists; we silence it and throw an exception instead. - // Attempt to connect to the server - $connection = @fsockopen($host, $port, $errno, $err, $timeout); + try { + // Attempt to connect to the server + $connection = fsockopen($host, $port, $errno, $err, $timeout); - if (!$connection) { - if (!$php_errormsg) { + if (!$connection) { // Error but nothing from php? Create our own - $php_errormsg = sprintf('Could not connect to resource %s: %s (error code %d)', $uri, $err, $errno); - } - - // Restore error tracking to give control to the exception handler - ini_set('track_errors', $track_errors); + if (!$err) { + $err = sprintf('Could not connect to host: %s:%s', $host, $port); + } - throw new \RuntimeException($php_errormsg); + throw new \Exception($err); + } + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } finally { + restore_error_handler(); } - // Restore error tracking to what it was before. - ini_set('track_errors', $track_errors); - // Since the connection was successful let's store it in case we need to use it later. $this->connections[$key] = $connection; diff --git a/libraries/src/Http/Transport/StreamTransport.php b/libraries/src/Http/Transport/StreamTransport.php index 130004d569ce5..233f5b7806568 100644 --- a/libraries/src/Http/Transport/StreamTransport.php +++ b/libraries/src/Http/Transport/StreamTransport.php @@ -143,28 +143,25 @@ public function request($method, UriInterface $uri, $data = null, array $headers } // Capture PHP errors - $php_errormsg = ''; - $track_errors = ini_get('track_errors'); - ini_set('track_errors', true); + // PHP sends a warning if the uri does not exist; we silence it and throw an exception instead. + set_error_handler(static function ($errno, $err) { + throw new \Exception($err); + }, \E_WARNING); - // Open the stream for reading. - $stream = @fopen((string) $uri, 'r', false, $context); + try { + // Open the stream for reading. + $stream = fopen((string) $uri, 'r', false, $context); - if (!$stream) { - if (!$php_errormsg) { + if (!$stream) { // Error but nothing from php? Create our own - $php_errormsg = sprintf('Could not connect to resource: %s', $uri); + throw new \Exception(sprintf('Could not connect to resource: %s', $uri)); } - - // Restore error tracking to give control to the exception handler - ini_set('track_errors', $track_errors); - - throw new \RuntimeException($php_errormsg); + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } finally { + restore_error_handler(); } - // Restore error tracking to what it was before. - ini_set('track_errors', $track_errors); - // Get the metadata for the stream, including response headers. $metadata = stream_get_meta_data($stream); diff --git a/libraries/src/Installer/InstallerHelper.php b/libraries/src/Installer/InstallerHelper.php index 4d556e6d08590..54782b8710b43 100644 --- a/libraries/src/Installer/InstallerHelper.php +++ b/libraries/src/Installer/InstallerHelper.php @@ -69,10 +69,6 @@ abstract class InstallerHelper */ public static function downloadPackage($url, $target = false) { - // Capture PHP errors - $track_errors = ini_get('track_errors'); - ini_set('track_errors', true); - // Set user agent $version = new Version(); ini_set('user_agent', $version->getUserAgent('Installer')); @@ -134,9 +130,6 @@ public static function downloadPackage($url, $target = false) // Write buffer to file File::write($target, $body); - // Restore error tracking to what it was before - ini_set('track_errors', $track_errors); - // Bump the max execution time because not using built in php zip libs are slow if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); diff --git a/libraries/src/Language/Language.php b/libraries/src/Language/Language.php index b3444d5b37f15..7c120eb358de6 100644 --- a/libraries/src/Language/Language.php +++ b/libraries/src/Language/Language.php @@ -707,11 +707,18 @@ protected function loadLanguage($fileName, $extension = 'unknown') */ protected function parse($fileName) { - $strings = LanguageHelper::parseIniFile($fileName, $this->debug); - - // Debug the ini file if needed. - if ($this->debug === true && is_file($fileName)) { - $this->debugFile($fileName); + try { + $strings = LanguageHelper::parseIniFile($fileName, $this->debug); + } catch (\RuntimeException $e) { + $strings = []; + + // Debug the ini file if needed. + if ($this->debug && is_file($fileName)) { + if (!$this->debugFile($fileName)) { + // We didn't find any errors but there's a parser warning. + $this->errorfiles[$fileName] = 'PHP parser errors :' . $e->getMessage(); + } + } } return $strings; @@ -738,10 +745,7 @@ public function debugFile(string $filename): int // Initialise variables for manually parsing the file for common errors. $reservedWord = ['YES', 'NO', 'NULL', 'FALSE', 'ON', 'OFF', 'NONE', 'TRUE']; - $debug = $this->getDebug(); - $this->debug = false; $errors = []; - $php_errormsg = null; // Open the file as a stream. $file = new \SplFileObject($filename); @@ -792,13 +796,8 @@ public function debugFile(string $filename): int // Check if we encountered any errors. if (\count($errors)) { $this->errorfiles[$filename] = $errors; - } elseif ($php_errormsg) { - // We didn't find any errors but there's probably a parse notice. - $this->errorfiles['PHP' . $filename] = 'PHP parser errors :' . $php_errormsg; } - $this->debug = $debug; - return \count($errors); } diff --git a/libraries/src/Language/LanguageHelper.php b/libraries/src/Language/LanguageHelper.php index ebe4044120b91..78743e2c726a1 100644 --- a/libraries/src/Language/LanguageHelper.php +++ b/libraries/src/Language/LanguageHelper.php @@ -401,6 +401,7 @@ public static function getContentLanguages( * @return array The strings parsed. * * @since 3.9.0 + * @throws \RuntimeException On debug */ public static function parseIniFile($fileName, $debug = false) { @@ -409,30 +410,31 @@ public static function parseIniFile($fileName, $debug = false) return []; } - // Capture hidden PHP errors from the parsing. - if ($debug === true) { - // See https://www.php.net/manual/en/reserved.variables.phperrormsg.php - $php_errormsg = null; - - $trackErrors = ini_get('track_errors'); - ini_set('track_errors', true); - } - // This was required for https://github.com/joomla/joomla-cms/issues/17198 but not sure what server setup // issue it is solving $disabledFunctions = explode(',', ini_get('disable_functions')); $isParseIniFileDisabled = \in_array('parse_ini_file', array_map('trim', $disabledFunctions)); - if (!\function_exists('parse_ini_file') || $isParseIniFileDisabled) { - $contents = file_get_contents($fileName); - $strings = @parse_ini_string($contents); - } else { - $strings = @parse_ini_file($fileName); - } + // Capture hidden PHP errors from the parsing. + set_error_handler(static function ($errno, $err) { + throw new \Exception($err); + }, \E_WARNING); + + try { + if (!\function_exists('parse_ini_file') || $isParseIniFileDisabled) { + $contents = file_get_contents($fileName); + $strings = parse_ini_string($contents); + } else { + $strings = parse_ini_file($fileName); + } + } catch (\Exception $e) { + if ($debug) { + throw new \RuntimeException($e->getMessage()); + } - // Restore error tracking to what it was before. - if ($debug === true) { - ini_set('track_errors', $trackErrors); + return []; + } finally { + restore_error_handler(); } return \is_array($strings) ? $strings : [];