From 1a03e46f966e8cf7ea6f4e5e2d92b786b281ae99 Mon Sep 17 00:00:00 2001 From: Frode Petterson Date: Sun, 16 Jan 2022 23:28:25 +0100 Subject: [PATCH] MDL-73588 curl: Fix expected CURLOPT_FILE behavior After cbf9dfb the CURLOPT_FILE no longer behaves as expected. All redirect responses are appended to the same stream resource. This fix reverts back to the old behavior by setting the stream pointer back to the beginning for each subsequent redirect. --- lib/filelib.php | 10 ++++++++++ lib/tests/filelib_test.php | 31 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/filelib.php b/lib/filelib.php index 6a430e02796..7877e3596f9 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3778,6 +3778,16 @@ class curl { return $this->error; } + // If the response body is written to a seekable stream resource, reset the stream pointer to avoid + // appending multiple response bodies to the same resource. + if (!empty($this->options['CURLOPT_FILE'])) { + $streammetadata = stream_get_meta_data($this->options['CURLOPT_FILE']); + if ($streammetadata['seekable']) { + ftruncate($this->options['CURLOPT_FILE'], 0); + rewind($this->options['CURLOPT_FILE']); + } + } + curl_setopt($curl, CURLOPT_URL, $redirecturl); $ret = curl_exec($curl); diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 7eb82c82743..bf6b6040592 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -145,6 +145,9 @@ class core_filelib_testcase extends advanced_testcase { $contents = download_file_content("$testurl?redir=2"); $this->assertSame('done', $contents); + $contents = download_file_content("$testurl?redir=2&verbose=1"); + $this->assertSame('done', $contents); + $response = download_file_content("$testurl?redir=2", null, null, true); $this->assertInstanceOf('stdClass', $response); $this->assertSame('200', $response->status); @@ -153,6 +156,14 @@ class core_filelib_testcase extends advanced_testcase { $this->assertSame('done', $response->results); $this->assertSame('', $response->error); + $response = download_file_content("$testurl?redir=2&verbose=1", null, null, true); + $this->assertInstanceOf('stdClass', $response); + $this->assertSame('200', $response->status); + $this->assertTrue(is_array($response->headers)); + $this->assertMatchesRegularExpression('|^HTTP/1\.[01] 200 OK$|', rtrim($response->response_code)); + $this->assertSame('done', $response->results); + $this->assertSame('', $response->error); + // Commented out this block if there are performance problems. /* $contents = download_file_content("$testurl?redir=6"); @@ -327,6 +338,17 @@ class core_filelib_testcase extends advanced_testcase { $this->assertSame('done', file_get_contents($tofile)); @unlink($tofile); + $curl = new curl(); + $tofile = "$CFG->tempdir/test.html"; + @unlink($tofile); + $fp = fopen($tofile, 'w'); + $result = $curl->get("$testurl?redir=1&verbose=1", array(), array('CURLOPT_FILE' => $fp)); + $this->assertTrue($result); + fclose($fp); + $this->assertFileExists($tofile); + $this->assertSame('done', file_get_contents($tofile)); + @unlink($tofile); + $curl = new curl(); $tofile = "$CFG->tempdir/test.html"; @unlink($tofile); @@ -335,6 +357,15 @@ class core_filelib_testcase extends advanced_testcase { $this->assertFileExists($tofile); $this->assertSame('done', file_get_contents($tofile)); @unlink($tofile); + + $curl = new curl(); + $tofile = "$CFG->tempdir/test.html"; + @unlink($tofile); + $result = $curl->download_one("$testurl?redir=1&verbose=1", array(), array('filepath' => $tofile)); + $this->assertTrue($result); + $this->assertFileExists($tofile); + $this->assertSame('done', file_get_contents($tofile)); + @unlink($tofile); } /**