From 5f38019f3cf6fc942fd3c65fddd6193946e24e7a Mon Sep 17 00:00:00 2001 From: Matt Rice <3780536+mattrice@users.noreply.github.com> Date: Fri, 18 Feb 2022 15:30:29 -0500 Subject: [PATCH] MDL-72582 core_files: Update readfile_accel error handling Correct the error handling in readfile_accel to properly log errors when working on a stored_file, rather than hiding the true error behind the incorrect "Object of class stored_file could not be converted to string." Co-authored-by: Simey Lameze Co-authored-by: Trisha Milan --- lib/filelib.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index a5d62cc0aeb..edd075ed3b3 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -2226,10 +2226,11 @@ function readfile_accel($file, $mimetype, $accelerate) { header('Content-Type: '.$mimetype); } - $lastmodified = is_object($file) ? $file->get_timemodified() : filemtime($file); + $isfileobj = is_object($file); + $lastmodified = $isfileobj ? $file->get_timemodified() : filemtime($file); header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastmodified) .' GMT'); - if (is_object($file)) { + if ($isfileobj) { header('Etag: "' . $file->get_contenthash() . '"'); if (isset($_SERVER['HTTP_IF_NONE_MATCH']) and trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $file->get_contenthash()) { header('HTTP/1.1 304 Not Modified'); @@ -2238,7 +2239,7 @@ function readfile_accel($file, $mimetype, $accelerate) { } // if etag present for stored file rely on it exclusively - if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) and (empty($_SERVER['HTTP_IF_NONE_MATCH']) or !is_object($file))) { + if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (empty($_SERVER['HTTP_IF_NONE_MATCH']) || !$isfileobj)) { // get unixtime of request header; clip extra junk off first $since = strtotime(preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"])); if ($since && $since >= $lastmodified) { @@ -2254,7 +2255,7 @@ function readfile_accel($file, $mimetype, $accelerate) { } if ($accelerate) { - if (is_object($file)) { + if ($isfileobj) { $fs = get_file_storage(); if ($fs->supports_xsendfile()) { if ($fs->xsendfile_file($file)) { @@ -2271,7 +2272,8 @@ function readfile_accel($file, $mimetype, $accelerate) { } } - $filesize = is_object($file) ? $file->get_filesize() : filesize($file); + $filesize = $isfileobj ? $file->get_filesize() : filesize($file); + $filename = $isfileobj ? $file->get_filename() : $file; header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastmodified) .' GMT'); @@ -2305,10 +2307,10 @@ function readfile_accel($file, $mimetype, $accelerate) { $ranges = false; } if ($ranges) { - if (is_object($file)) { + if ($isfileobj) { $handle = $file->get_content_file_handle(); if ($handle === false) { - throw new file_exception('storedfilecannotreadfile', $file->get_filename()); + throw new file_exception('storedfilecannotreadfile', $filename); } } else { $handle = fopen($file, 'rb'); @@ -2334,7 +2336,12 @@ function readfile_accel($file, $mimetype, $accelerate) { // We do not expect any content in the buffer when we are serving files. $buffercontents = ob_get_clean(); if ($buffercontents !== '') { - error_log('Non-empty default output handler buffer detected while serving the file ' . $file); + // Include a preview of the first 20 characters of the output buffer to help identify + // what's causing it to be non-empty. This is useful for diagnosing unexpected output + // without exposing full content. + $buffercontentspreview = substr($buffercontents, 0, 20); + debugging("Non-empty default output handler buffer detected while serving the file {$filename}. " . + "Buffer contents (first 20 characters): {$buffercontentspreview}", DEBUG_DEVELOPER); } } else { // Some handlers such as zlib output compression may have file signature buffered - flush it. @@ -2343,7 +2350,7 @@ function readfile_accel($file, $mimetype, $accelerate) { } // send the whole file content - if (is_object($file)) { + if ($isfileobj) { $file->readfile(); } else { if (readfile_allow_large($file, $filesize) === false) {