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)); }