From c98428aab38a68a8502024e09c2b9bf87ddce91b Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Mon, 14 Sep 2020 23:08:22 +0100 Subject: [PATCH] MDL-37802 repository: return error if unzipping files fails. For instance, when a user tried to unzip a password protected zip archive using the file manager. --- lang/en/repository.php | 1 + .../tests/fixtures/passwordis1.zip | Bin 0 -> 232 bytes lib/filestorage/tests/zip_packer_test.php | 18 ++++++++++++++++++ repository/draftfiles_ajax.php | 14 +++++++++++++- 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 lib/filestorage/tests/fixtures/passwordis1.zip diff --git a/lang/en/repository.php b/lang/en/repository.php index 05791e5c19c..ddb5eccefe0 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -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 index 0000000000000000000000000000000000000000..0c8c4f037e42456d20e8b5e63971d8b6d14c1cb8 GIT binary patch literal 232 zcmWIWW@h1H;ACK6U~cR1yT{XEXaHoZ05KNO{T{;LXl~Y*BzWBa<96E=NcJox;Gt2*g_&K`bOEu|k}L=9~a;RyL4AMj-SD J(#;?a0{|AXH(me$ literal 0 HcmV?d00001 diff --git a/lib/filestorage/tests/zip_packer_test.php b/lib/filestorage/tests/zip_packer_test.php index 860b8afb504..4b36265e2b9 100644 --- a/lib/filestorage/tests/zip_packer_test.php +++ b/lib/filestorage/tests/zip_packer_test.php @@ -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. */ diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php index 5433a461657..8f7a6af0492 100644 --- a/repository/draftfiles_ajax.php +++ b/repository/draftfiles_ajax.php @@ -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) {