MDL-37802 repository: return error if unzipping files fails.
authorPaul Holden <paulh@moodle.com>
Mon, 14 Sep 2020 22:08:22 +0000 (23:08 +0100)
committerPaul Holden <paulh@moodle.com>
Fri, 25 Sep 2020 08:33:44 +0000 (09:33 +0100)
For instance, when a user tried to unzip a password protected zip
archive using the file manager.

lang/en/repository.php
lib/filestorage/tests/fixtures/passwordis1.zip [new file with mode: 0644]
lib/filestorage/tests/zip_packer_test.php
repository/draftfiles_ajax.php

index 05791e5..ddb5ecc 100644 (file)
@@ -58,6 +58,7 @@ $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['cannotunzipextractfileerror'] = 'Cannot unzip this file because one or more of it\'s files 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';
diff --git a/lib/filestorage/tests/fixtures/passwordis1.zip b/lib/filestorage/tests/fixtures/passwordis1.zip
new file mode 100644 (file)
index 0000000..0c8c4f0
Binary files /dev/null and b/lib/filestorage/tests/fixtures/passwordis1.zip differ
index 860b8af..4b36265 100644 (file)
@@ -525,6 +525,24 @@ class core_files_zip_packer_testcase extends advanced_testcase implements file_p
         unlink($archive);
     }
 
+    /**
+     * Test opening an encrypted archive
+     */
+    public function test_open_encrypted_archive() {
+        $this->resetAfterTest();
+
+        // The archive contains a single encrypted "hello.txt" file.
+        $archive = __DIR__ . '/fixtures/passwordis1.zip';
+
+        /** @var zip_packer $packer */
+        $packer = get_file_packer('application/zip');
+        $result = $packer->extract_to_pathname($archive, make_temp_directory('zip'));
+
+        $this->assertIsArray($result);
+        $this->assertArrayHasKey('hello.txt', $result);
+        $this->assertEquals('Can not read file from zip archive', $result['hello.txt']);
+    }
+
     /**
      * Tests the progress reporting.
      */
index 5433a46..8f7a6af 100644 (file)
@@ -227,8 +227,20 @@ switch ($action) {
         $temppath = $fs->get_unused_dirname($usercontext->id, 'user', 'draft', $draftid, $filepath. pathinfo($filename, PATHINFO_FILENAME). '/');
         $donotremovedirs = array();
         $doremovedirs = array($temppath);
+
         // Extract archive and move all files from $temppath to $filepath
-        if ($file->extract_to_storage($zipper, $usercontext->id, 'user', 'draft', $draftid, $temppath, $USER->id) !== false) {
+        if (($processed = $file->extract_to_storage($zipper, $usercontext->id, 'user', 'draft', $draftid, $temppath, $USER->id))
+                !== false) {
+
+            // Find all failures within the processed files, and return an error if any are found.
+            $failed = array_filter($processed, static function($result): bool {
+                return $result !== true;
+            });
+            if (count($failed) > 0) {
+                $return->error = get_string('cannotunzipextractfileerror',  'repository');
+                die(json_encode($return));
+            }
+
             $extractedfiles = $fs->get_directory_files($usercontext->id, 'user', 'draft', $draftid, $temppath, true);
             $xtemppath = preg_quote($temppath, '|');
             foreach ($extractedfiles as $file) {