MDL-65115 repository: Prevent unzipping if it will exceed allowed quota
authorMihail Geshoski <mihail@moodle.com>
Tue, 14 Jul 2020 07:49:14 +0000 (15:49 +0800)
committerJenkins <jenkins@worker08.test.in.moodle.com>
Tue, 8 Sep 2020 06:54:26 +0000 (08:54 +0200)
lang/en/repository.php
lib/form/filemanager.js
repository/draftfiles_ajax.php

index 8452614..05791e5 100644 (file)
@@ -57,6 +57,8 @@ $string['cannotdelete'] = 'Cannot delete this file.';
 $string['cannotdownload'] = 'Cannot download this file';
 $string['cannotdownloaddir'] = 'Cannot download this folder';
 $string['cannotinitplugin'] = 'Call plugin_init failed';
+$string['cannotunzipcontentunreadable'] = 'Cannot unzip this file because the contents of the file cannot be read.';
+$string['cannotunzipquotaexceeded'] = 'Cannot unzip this file because the maximum size allowed in this draft area will be exceeded.';
 $string['cleancache'] = 'Clean my cache files';
 $string['close'] = 'Close';
 $string['commonrepositorysettings'] = 'Common repository settings';
index 168c110..036233b 100644 (file)
@@ -991,14 +991,21 @@ M.form_filemanager.init = function(Y, options) {
                 }
                 params['filepath'] = fileinfo.filepath;
                 params['filename'] = fileinfo.fullname;
+                // The unlimited value of areamaxbytes is -1, it is defined by FILE_AREA_MAX_BYTES_UNLIMITED.
+                params['areamaxbytes'] = this.areamaxbytes ? this.areamaxbytes : -1;
                 selectnode.addClass('loading');
                 this.request({
                     action: 'unzip',
                     scope: this,
                     params: params,
                     callback: function(id, obj, args) {
-                        args.scope.selectui.hide();
-                        args.scope.refresh(obj.filepath);
+                        if (obj.error) {
+                            selectnode.removeClass('loading');
+                            args.scope.print_msg(obj.error, 'error');
+                        } else {
+                            args.scope.selectui.hide();
+                            args.scope.refresh(obj.filepath);
+                        }
                     }
                 });
             }, this);
index d00d068..5433a46 100644 (file)
@@ -200,12 +200,28 @@ switch ($action) {
     case 'unzip':
         $filename = required_param('filename', PARAM_FILE);
         $filepath = required_param('filepath', PARAM_PATH);
+        $areamaxbytes = required_param('areamaxbytes', PARAM_INT);
 
+        $return = new stdClass();
         $zipper = get_file_packer('application/zip');
-
         $fs = get_file_storage();
-
         $file = $fs->get_file($usercontext->id, 'user', 'draft', $draftid, $filepath, $filename);
+        // Get the total size of the content in the archive.
+        $filecontentsize = $file->get_total_content_size($zipper);
+
+        // Return an error if the returned size of the content is NULL.
+        // This means the utility class was unable to read the content of the archive.
+        if (is_null($filecontentsize)) {
+            $return->error = get_string('cannotunzipcontentunreadable', 'repository');
+            die(json_encode($return));
+        }
+
+        // Check whether the maximum size allowed in this draft area will be exceeded with unzipping the file.
+        // If the maximum size allowed is exceeded, return an error before attempting to unzip.
+        if (file_is_draft_area_limit_reached($draftid, $areamaxbytes, $filecontentsize)) {
+            $return->error = get_string('cannotunzipquotaexceeded', 'repository');
+            die(json_encode($return));
+        }
 
         // Find unused name for directory to extract the archive.
         $temppath = $fs->get_unused_dirname($usercontext->id, 'user', 'draft', $draftid, $filepath. pathinfo($filename, PATHINFO_FILENAME). '/');
@@ -233,7 +249,6 @@ switch ($action) {
                     $donotremovedirs[] = $realpath;
                 }
             }
-            $return = new stdClass();
             $return->filepath = $filepath;
         } else {
             $return = false;