From 836c7f79ffe972563cf5e55dafe08eace61454f2 Mon Sep 17 00:00:00 2001 From: Andreas Lutro Date: Mon, 14 Jun 2021 21:30:35 +0200 Subject: [PATCH] fixes for `CURLOPT_FILE` handling (#68) * add more safeguards against invalid headers * re-open file to avoid weirdness --- src/Response.php | 9 ++++++++- src/cURL.php | 13 +++++-------- tests/functional/cURLTest.php | 2 +- tests/unit/ResponseTest.php | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Response.php b/src/Response.php index 27c5a11..0069960 100644 --- a/src/Response.php +++ b/src/Response.php @@ -70,6 +70,9 @@ public function __construct($body, $headers, $info = array()) */ protected function parseHeader($header) { + if ($header === "") { + throw new \UnexpectedValueException('Empty header string passed!'); + } $headers = explode("\r\n", trim($header)); $this->parseHeaders($headers); } @@ -83,12 +86,16 @@ protected function parseHeader($header) */ protected function parseHeaders(array $headers) { + if (count($headers) === 0) { + throw new \UnexpectedValueException('No headers passed!'); + } + $this->headers = array(); // find and set the HTTP status code and reason $firstHeader = array_shift($headers); if (!preg_match('/^HTTP\/\d(\.\d)? [0-9]{3}/', $firstHeader)) { - throw new \InvalidArgumentException('Invalid response header'); + throw new \UnexpectedValueException('Invalid response header'); } list(, $status) = explode(' ', $firstHeader, 2); $code = explode(' ', $status); diff --git a/src/cURL.php b/src/cURL.php index 19fd88b..214e176 100644 --- a/src/cURL.php +++ b/src/cURL.php @@ -313,15 +313,12 @@ protected function createResponseObject($response, Request $request) $info[CURLINFO_HTTPAUTH_AVAIL] = curl_getinfo($this->ch, CURLINFO_HTTPAUTH_AVAIL); if ($file = $request->getOption(CURLOPT_FILE)) { - // TODO: is this even possible? - if (!is_resource($file)) { - $file = fopen($file, "r"); - } - // TODO: what if resource isn't seekable? e.g. network socket? - $oldPosition = ftell($file); - fseek($file, 0); + // file may be opened write-only, and even when it isn't, + // seeking/reading seems to be buggy + $fileMeta = stream_get_meta_data($file); + $file = fopen($fileMeta['uri'], 'r'); $headers = fread($file, $headerSize); - fseek($file, $oldPosition); + fclose($file); $body = null; } else { $headers = substr($response, 0, $headerSize); diff --git a/tests/functional/cURLTest.php b/tests/functional/cURLTest.php index ac81287..c24cfee 100644 --- a/tests/functional/cURLTest.php +++ b/tests/functional/cURLTest.php @@ -169,7 +169,7 @@ public function curloptFileWorks() { $r = $this->makeCurl() ->newRequest('get', static::URL.'/success.php') - ->setOption(CURLOPT_FILE, tmpfile()) + ->setOption(CURLOPT_FILE, $fh = tmpfile()) ->send(); $this->assertEquals(200, $r->statusCode); $this->assertEquals('200 OK', $r->statusText); diff --git a/tests/unit/ResponseTest.php b/tests/unit/ResponseTest.php index 753a551..456dfc3 100644 --- a/tests/unit/ResponseTest.php +++ b/tests/unit/ResponseTest.php @@ -59,7 +59,7 @@ public function httpContinueResponsesAreHandled() /** @test */ public function throwsExceptionIfHeaderDoesntStartWithHttpStatus() { - $this->setExpectedException('InvalidArgumentException', 'Invalid response header'); + $this->setExpectedException('UnexpectedValueException', 'Invalid response header'); $this->makeResponse('', 'x-var: foo'); }