From 427b0d3fee9f298814e63f2cd1faa1dff04cae58 Mon Sep 17 00:00:00 2001 From: meirzamoodle Date: Fri, 11 Aug 2023 08:06:25 +0700 Subject: [PATCH] MDL-74641 repository: Handles increase bytes while extracting zip files We should not rely solely on the provided size information. Therefore the system needs to recalculate the size of each file in the zip file, whether small or big. The changes also cover the filemanager.js file if an error appears. --- lib/filestorage/zip_packer.php | 38 +++++++++++++++++++++++++++++++++- lib/form/filemanager.js | 2 +- repository/draftfiles_ajax.php | 6 +++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/filestorage/zip_packer.php b/lib/filestorage/zip_packer.php index 1f6efb6809b..482aea1096d 100644 --- a/lib/filestorage/zip_packer.php +++ b/lib/filestorage/zip_packer.php @@ -451,6 +451,17 @@ class zip_packer extends file_packer { $done = 0; } + // Get user remaining space. + $areamaxbytes = FILE_AREA_MAX_BYTES_UNLIMITED; + $context = context::instance_by_id($contextid); + if (!has_capability('moodle/user:ignoreuserquota', $context)) { + // Get current used space for this user (private files only). + $fileareainfo = file_get_file_area_info($contextid, 'user', 'private'); + $usedspace = $fileareainfo['filesize_without_references']; + $areamaxbytes = (int) $CFG->userquota - $usedspace; + } + $totalsizebytes = 0; + foreach ($ziparch as $info) { // Notify progress. if ($progress) { @@ -461,6 +472,8 @@ class zip_packer extends file_packer { $size = $info->size; $name = $info->pathname; + $realfilesize = 0; + if ($name === '' or array_key_exists($name, $processed)) { //probably filename collisions caused by filename cleaning/conversion continue; @@ -489,6 +502,17 @@ class zip_packer extends file_packer { $content = ''; while (!feof($fz)) { $content .= fread($fz, 262143); + $realfilesize += strlen($content); // Current file size. + $totalsizebytes += strlen($content); + if ($realfilesize > $size || + ($areamaxbytes != FILE_AREA_MAX_BYTES_UNLIMITED && $totalsizebytes > $areamaxbytes)) { + $processed[0] = 'cannotunzipquotaexceeded'; + // Close and unset the stream and the content. + fclose($fz); + unset($content); + // Cancel all processes. + break(2); + } } fclose($fz); if (strlen($content) !== $size) { @@ -535,7 +559,19 @@ class zip_packer extends file_packer { } while (!feof($fz)) { $content = fread($fz, 262143); - fwrite($fp, $content); + $numofbytes = fwrite($fp, $content); + $realfilesize += $numofbytes; // Current file size. + $totalsizebytes += $numofbytes; + if ($realfilesize > $size || + ($areamaxbytes != FILE_AREA_MAX_BYTES_UNLIMITED && $totalsizebytes > $areamaxbytes)) { + $processed[0] = 'cannotunzipquotaexceeded'; + // Close and remove the tmpfile. + fclose($fz); + fclose($fp); + unlink($tmpfile); + // Cancel all processes. + break(2); + } } fclose($fz); fclose($fp); diff --git a/lib/form/filemanager.js b/lib/form/filemanager.js index 524e13efb9f..8f9e5cba4d7 100644 --- a/lib/form/filemanager.js +++ b/lib/form/filemanager.js @@ -1033,7 +1033,7 @@ M.form_filemanager.init = function(Y, options) { callback: function(id, obj, args) { if (obj.error) { selectnode.removeClass('loading'); - args.scope.print_msg(obj.error, 'error'); + args.scope.print_msg(obj.error, 'error', options); } else { args.scope.selectui.hide(); args.scope.refresh(obj.filepath); diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php index 78e200d22ad..e1c7a979a36 100644 --- a/repository/draftfiles_ajax.php +++ b/repository/draftfiles_ajax.php @@ -237,7 +237,11 @@ switch ($action) { return $result !== true; }); if (count($failed) > 0) { - $return->error = get_string('cannotunzipextractfileerror', 'repository'); + if ($failed[0] == "cannotunzipquotaexceeded") { + $return->error = get_string($failed[0], 'repository'); + } else { + $return->error = get_string('cannotunzipextractfileerror', 'repository'); + } die(json_encode($return)); }