1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_files\local\archive_writer; 18 19 use advanced_testcase; 20 use context_module; 21 use core_files\archive_writer; 22 use ZipArchive; 23 24 /** 25 * Unit tests for \core_files\local\archive_writer\zip_writer. 26 * 27 * @package core_files 28 * @category test 29 * @copyright 2020 Mark Nelson <mdjnelson@gmail.com> 30 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License 31 * @covers \core_files\local\archive_writer\zip_writer 32 */ 33 class zip_writer_test extends advanced_testcase { 34 35 /** 36 * Test add_file_from_filepath(). 37 */ 38 public function test_add_file_from_filepath(): void { 39 global $CFG; 40 41 $pathtofileinzip = '/some/made/up/name.txt'; 42 $filetoadd = $CFG->dirroot . '/files/tests/fixtures/awesome_file.txt'; 43 44 $zipwriter = archive_writer::get_file_writer('test.zip', archive_writer::ZIP_WRITER); 45 $zipwriter->add_file_from_filepath($pathtofileinzip, $filetoadd); 46 $zipwriter->finish(); 47 48 $pathtozip = $zipwriter->get_path_to_zip(); 49 $zip = new ZipArchive(); 50 $opened = $zip->open($pathtozip); 51 $this->assertTrue($opened); 52 53 $pathtofileinzip = $zipwriter->sanitise_filepath($pathtofileinzip); 54 55 $this->assertEquals("Hey, this is an awesome text file. Hello! :)", $zip->getFromName($pathtofileinzip)); 56 } 57 58 /** 59 * Test add_file_from_string(). 60 */ 61 public function test_add_file_from_string(): void { 62 $pathtofileinzip = "/path/to/my/awesome/file.txt"; 63 $mycontent = "This is some real awesome content, ya dig?"; 64 65 $zipwriter = archive_writer::get_file_writer('test.zip', archive_writer::ZIP_WRITER); 66 $zipwriter->add_file_from_string($pathtofileinzip, $mycontent); 67 $zipwriter->finish(); 68 69 $pathtozip = $zipwriter->get_path_to_zip(); 70 $zip = new ZipArchive(); 71 $opened = $zip->open($pathtozip); 72 $this->assertTrue($opened); 73 74 $pathtofileinzip = $zipwriter->sanitise_filepath($pathtofileinzip); 75 76 $this->assertEquals($mycontent, $zip->getFromName($pathtofileinzip)); 77 } 78 79 /** 80 * Test add_file_from_stream(). 81 */ 82 public function test_add_file_from_stream(): void { 83 $this->resetAfterTest(true); 84 $this->setAdminUser(); 85 86 $course = $this->getDataGenerator()->create_course(); 87 $assign = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); 88 89 // Add a file to the intro. 90 $filerecord = [ 91 'contextid' => context_module::instance($assign->cmid)->id, 92 'component' => 'mod_assign', 93 'filearea' => 'intro', 94 'itemid' => 0, 95 'filepath' => '/', 96 'filename' => 'fileintro.txt', 97 ]; 98 $fs = get_file_storage(); 99 $storedfile = $fs->create_file_from_string($filerecord, 'Contents for the assignment, yeow!'); 100 101 $pathtofileinzip = $storedfile->get_filepath() . $storedfile->get_filename(); 102 103 $zipwriter = archive_writer::get_file_writer('test.zip', archive_writer::ZIP_WRITER); 104 $zipwriter->add_file_from_stream($pathtofileinzip, $storedfile->get_content_file_handle()); 105 $zipwriter->finish(); 106 107 $pathtozip = $zipwriter->get_path_to_zip(); 108 $zip = new ZipArchive(); 109 $opened = $zip->open($pathtozip); 110 $this->assertTrue($opened); 111 112 $pathtofileinzip = $zipwriter->sanitise_filepath($pathtofileinzip); 113 114 $this->assertEquals($storedfile->get_content(), $zip->getFromName($pathtofileinzip)); 115 } 116 117 /** 118 * Test add_file_from_stored_file(). 119 */ 120 public function test_add_file_from_stored_file(): void { 121 $this->resetAfterTest(true); 122 $this->setAdminUser(); 123 124 $course = $this->getDataGenerator()->create_course(); 125 $assign = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); 126 127 // Add a file to the intro. 128 $filerecord = [ 129 'contextid' => context_module::instance($assign->cmid)->id, 130 'component' => 'mod_assign', 131 'filearea' => 'intro', 132 'itemid' => 0, 133 'filepath' => '/', 134 'filename' => 'fileintro.txt', 135 ]; 136 $fs = get_file_storage(); 137 $storedfile = $fs->create_file_from_string($filerecord, 'Contents for the assignment, yeow!'); 138 139 $pathtofileinzip = $storedfile->get_filepath() . $storedfile->get_filename(); 140 141 $zipwriter = archive_writer::get_file_writer('test.zip', archive_writer::ZIP_WRITER); 142 $zipwriter->add_file_from_stored_file($pathtofileinzip, $storedfile); 143 $zipwriter->finish(); 144 145 $pathtozip = $zipwriter->get_path_to_zip(); 146 $zip = new ZipArchive(); 147 $opened = $zip->open($pathtozip); 148 $this->assertTrue($opened); 149 150 $pathtofileinzip = $zipwriter->sanitise_filepath($pathtofileinzip); 151 152 $this->assertEquals($storedfile->get_content(), $zip->getFromName($pathtofileinzip)); 153 } 154 155 /** 156 * Test sanitise_filepath(). 157 * 158 * @param string $providedfilepath The provided file path. 159 * @param string $expectedfilepath The expected file path. 160 * @dataProvider sanitise_filepath_provider 161 */ 162 public function test_sanitise_filepath(string $providedfilepath, string $expectedfilepath): void { 163 $zipwriter = archive_writer::get_stream_writer('path/to/file.txt', archive_writer::ZIP_WRITER); 164 $this->assertEquals($expectedfilepath, $zipwriter->sanitise_filepath($providedfilepath)); 165 } 166 167 /** 168 * Data provider for test_sanitise_filepath. 169 * 170 * @return array 171 */ 172 public function sanitise_filepath_provider(): array { 173 return [ 174 ['a../../file/path', 'a../file/path'], 175 ['a./file/path', 'a./file/path'], 176 ['../file/path', 'file/path'], 177 ['foo/bar/', 'foo/bar/'], 178 ['\\\\\\a\\\\\\file\\\\\\path', 'a/file/path'], 179 ['//a//file/////path////', 'a/file/path/'] 180 ]; 181 } 182 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body