diff --git a/CHANGELOG.md b/CHANGELOG.md index ae12a517fb..629f9cc364 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ backwards-incompatible changes that will affect existing usage. +## 11.0.4 - 2025-02-20 + +- Increase psalm strictness ([#925](https://github.com/php-curl-class/php-curl-class/pull/925)) + ## 11.0.3 - 2025-02-19 - Use default for Psalm ensureOverrideAttribute ([#923](https://github.com/php-curl-class/php-curl-class/pull/923)) diff --git a/src/Curl/BaseCurl.php b/src/Curl/BaseCurl.php index f2032b004e..54d4a5072e 100644 --- a/src/Curl/BaseCurl.php +++ b/src/Curl/BaseCurl.php @@ -404,10 +404,11 @@ public function unsetProxy() public function verbose($on = true, $output = 'STDERR') { if ($output === 'STDERR') { - if (!defined('STDERR')) { - define('STDERR', fopen('php://stderr', 'wb')); + if (defined('STDERR')) { + $output = STDERR; + } else { + $output = fopen('php://stderr', 'wb'); } - $output = STDERR; } // Turn off CURLINFO_HEADER_OUT for verbose to work. This has the side diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index d4b6c70fd4..8c1a9e94cd 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -6,7 +6,7 @@ class Curl extends BaseCurl { - public const VERSION = '11.0.3'; + public const VERSION = '11.0.4'; public const DEFAULT_TIMEOUT = 30; public $curl = null; @@ -430,8 +430,10 @@ public function fastDownload($url, $filename, $connections = 4) $curl->downloadCompleteCallback = function ($instance, $tmpfile) use ($part_file_name) { $fh = fopen($part_file_name, 'wb'); - stream_copy_to_stream($tmpfile, $fh); - fclose($fh); + if ($fh !== false) { + stream_copy_to_stream($tmpfile, $fh); + fclose($fh); + } }; $multi_curl->addCurl($curl); @@ -447,6 +449,9 @@ public function fastDownload($url, $filename, $connections = 4) // Combine downloaded chunks into a single file. $main_file_handle = fopen($filename, 'w'); + if ($main_file_handle === false) { + return false; + } foreach ($part_file_names as $part_file_name) { if (!is_file($part_file_name)) { @@ -1031,7 +1036,7 @@ public function setHeaders($headers) } } else { foreach ($headers as $header) { - list($key, $value) = explode(':', $header, 2); + list($key, $value) = array_pad(explode(':', $header, 2), 2, ''); $key = trim($key); $value = trim($value); $this->headers[$key] = $value; @@ -1404,7 +1409,7 @@ public function diagnose($return = false) if (isset($this->responseHeaders['Content-Length'])) { echo 'Response content length (from content-length header): ' . $response_header_length . "\n"; } else { - echo 'Response content length (calculated): ' . $response_calculated_length . "\n"; + echo 'Response content length (calculated): ' . (string)$response_calculated_length . "\n"; } if ( @@ -1859,13 +1864,15 @@ private function downloadComplete($fh) // Fix "PHP Notice: Use of undefined constant STDOUT" when reading the // PHP script from stdin. Using null causes "Warning: curl_setopt(): // supplied argument is not a valid File-Handle resource". - if (!defined('STDOUT')) { - define('STDOUT', fopen('php://stdout', 'w')); + if (defined('STDOUT')) { + $output = STDOUT; + } else { + $output = fopen('php://stdout', 'w'); } // Reset CURLOPT_FILE with STDOUT to avoid: "curl_exec(): CURLOPT_FILE // resource has gone away, resetting to default". - $this->setFile(STDOUT); + $this->setFile($output); // Reset CURLOPT_RETURNTRANSFER to tell cURL to return subsequent // responses as the return value of curl_exec(). Without this, @@ -1881,13 +1888,16 @@ private function downloadComplete($fh) */ private function parseHeaders($raw_headers) { - $raw_headers = preg_split('/\r\n/', (string) $raw_headers, -1, PREG_SPLIT_NO_EMPTY); $http_headers = new CaseInsensitiveArray(); + $raw_headers = preg_split('/\r\n/', (string) $raw_headers, -1, PREG_SPLIT_NO_EMPTY); + if ($raw_headers === false) { + return ['', $http_headers]; + } $raw_headers_count = count($raw_headers); for ($i = 1; $i < $raw_headers_count; $i++) { if (strpos($raw_headers[$i], ':') !== false) { - list($key, $value) = explode(':', $raw_headers[$i], 2); + list($key, $value) = array_pad(explode(':', $raw_headers[$i], 2), 2, ''); $key = trim($key); $value = trim($value); // Use isset() as array_key_exists() and ArrayAccess are not compatible. diff --git a/src/Curl/MultiCurl.php b/src/Curl/MultiCurl.php index 6baa347d5a..ba87f99aab 100644 --- a/src/Curl/MultiCurl.php +++ b/src/Curl/MultiCurl.php @@ -127,7 +127,10 @@ public function addDownload($url, $mixed_filename) } else { $curl->fileHandle = fopen('php://temp', 'wb'); $curl->downloadCompleteCallback = function ($instance, $fh) use ($filename) { - file_put_contents($filename, stream_get_contents($fh)); + $contents = stream_get_contents($fh); + if ($contents !== false) { + file_put_contents($filename, $contents); + } }; } } @@ -462,7 +465,7 @@ public function setHeaders($headers) } } else { foreach ($headers as $header) { - list($key, $value) = explode(':', $header, 2); + list($key, $value) = array_pad(explode(':', $header, 2), 2, ''); $key = trim($key); $value = trim($value); $this->headers[$key] = $value; @@ -946,7 +949,13 @@ private function waitUntilRequestQuotaAvailable() $sleep_seconds = $sleep_until - microtime(true); // Avoid using time_sleep_until() as it appears to be less precise and not sleep long enough. - usleep((int) $sleep_seconds * 1000000); + // Avoid using usleep(): "Values larger than 1000000 (i.e. sleeping for + // more than a second) may not be supported by the operating system. + // Use sleep() instead." + $sleep_seconds_int = (int)$sleep_seconds; + if ($sleep_seconds_int >= 1) { + sleep($sleep_seconds_int); + } // Ensure that enough time has passed as usleep() may not have waited long enough. $this->currentStartTime = microtime(true); diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 867a21c21d..7b21802229 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -5,5 +5,22 @@ + + curl]]> + curl]]> + + + + + + + + + multiCurl]]> + multiCurl]]> + multiCurl]]> + multiCurl]]> + multiCurl]]> + diff --git a/tests/psalm.xml b/tests/psalm.xml index e2f098d3be..2a56ee25db 100644 --- a/tests/psalm.xml +++ b/tests/psalm.xml @@ -1,7 +1,7 @@