Commit | Line | Data |
---|---|---|
79c966cf PS |
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 | /** | |
18 | * Unit tests for /lib/filestorage/zip_packer.php and zip_archive.php | |
19 | * | |
20 | * @package core_files | |
21 | * @category phpunit | |
22 | * @copyright 2012 Petr Skoda | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
27 | ||
28 | ||
8252b7c2 | 29 | class core_files_zip_packer_testcase extends advanced_testcase { |
79c966cf PS |
30 | protected $testfile; |
31 | protected $files; | |
32 | ||
33 | protected function setUp() { | |
34 | parent::setUp(); | |
35 | ||
36 | $this->testfile = __DIR__.'/fixtures/test.txt'; | |
37 | ||
38 | $fs = get_file_storage(); | |
39 | $context = context_system::instance(); | |
40 | if (!$file = $fs->get_file($context->id, 'phpunit', 'data', 0, '/', 'test.txt')) { | |
41 | $file = $fs->create_file_from_pathname( | |
42 | array('contextid'=>$context->id, 'component'=>'phpunit', 'filearea'=>'data', 'itemid'=>0, 'filepath'=>'/', 'filename'=>'test.txt'), | |
43 | $this->testfile); | |
44 | } | |
45 | ||
46 | $this->files = array( | |
47 | 'test.test' => $this->testfile, | |
48 | 'testíček.txt' => $this->testfile, | |
49 | 'Prüfung.txt' => $this->testfile, | |
50 | '测试.txt' => $this->testfile, | |
51 | '試験.txt' => $this->testfile, | |
52 | 'Žluťoučký/Koníček.txt' => $file, | |
53 | ); | |
54 | } | |
55 | ||
56 | public function test_get_packer() { | |
57 | $this->resetAfterTest(false); | |
58 | $packer = get_file_packer(); | |
59 | $this->assertInstanceOf('zip_packer', $packer); | |
60 | ||
61 | $packer = get_file_packer('application/zip'); | |
62 | $this->assertInstanceOf('zip_packer', $packer); | |
63 | } | |
64 | ||
65 | /** | |
66 | * @depends test_get_packer | |
67 | */ | |
68 | public function test_list_files() { | |
69 | $this->resetAfterTest(false); | |
6fb8ae95 PS |
70 | |
71 | $files = array( | |
72 | __DIR__.'/fixtures/test_moodle_22.zip', | |
73 | __DIR__.'/fixtures/test_moodle.zip', | |
74 | __DIR__.'/fixtures/test_tc_8.zip', | |
75 | __DIR__.'/fixtures/test_7zip_927.zip', | |
76 | __DIR__.'/fixtures/test_winzip_165.zip', | |
77 | __DIR__.'/fixtures/test_winrar_421.zip', | |
81d9f3d5 | 78 | __DIR__.'/fixtures/test_thumbsdb.zip', |
6fb8ae95 PS |
79 | ); |
80 | ||
81 | if (function_exists('normalizer_normalize')) { | |
5f15f7c9 | 82 | // Unfortunately there is no way to standardise UTF-8 strings without INTL extension. |
6fb8ae95 PS |
83 | $files[] = __DIR__.'/fixtures/test_infozip_3.zip'; |
84 | $files[] = __DIR__.'/fixtures/test_osx_1074.zip'; | |
81d9f3d5 | 85 | $files[] = __DIR__.'/fixtures/test_osx_compress.zip'; |
6fb8ae95 | 86 | } |
79c966cf PS |
87 | |
88 | $packer = get_file_packer('application/zip'); | |
89 | ||
6fb8ae95 PS |
90 | foreach ($files as $archive) { |
91 | $archivefiles = $packer->list_files($archive); | |
92 | $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); | |
93 | $this->assertTrue(count($this->files) === count($archivefiles) or count($this->files) === count($archivefiles) - 1); // Some zippers create empty dirs. | |
5f15f7c9 | 94 | foreach ($archivefiles as $file) { |
6fb8ae95 PS |
95 | if ($file->pathname === 'Žluťoučký/') { |
96 | // Some zippers create empty dirs. | |
97 | continue; | |
98 | } | |
99 | $this->assertArrayHasKey($file->pathname, $this->files, "File $file->pathname not extracted properly: ".basename($archive).' '); | |
100 | } | |
79c966cf PS |
101 | } |
102 | ||
5f15f7c9 | 103 | // Windows packer supports only DOS encoding. |
6fb8ae95 PS |
104 | $archive = __DIR__.'/fixtures/test_win8_de.zip'; |
105 | $archivefiles = $packer->list_files($archive); | |
106 | $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); | |
107 | $this->assertEquals(2, count($archivefiles)); | |
5f15f7c9 | 108 | foreach ($archivefiles as $file) { |
6fb8ae95 PS |
109 | $this->assertTrue($file->pathname === 'Prüfung.txt' or $file->pathname === 'test.test'); |
110 | } | |
111 | ||
112 | $zip_archive = new zip_archive(); | |
113 | $zip_archive->open(__DIR__.'/fixtures/test_win8_cz.zip', file_archive::OPEN, 'cp852'); | |
114 | $archivefiles = $zip_archive->list_files(); | |
115 | $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); | |
116 | $this->assertEquals(3, count($archivefiles)); | |
5f15f7c9 | 117 | foreach ($archivefiles as $file) { |
6fb8ae95 | 118 | $this->assertTrue($file->pathname === 'Žluťoučký/Koníček.txt' or $file->pathname === 'testíček.txt' or $file->pathname === 'test.test'); |
79c966cf | 119 | } |
6fb8ae95 | 120 | $zip_archive->close(); |
01b4040a PS |
121 | |
122 | // Empty archive extraction. | |
123 | $archive = __DIR__.'/fixtures/empty.zip'; | |
124 | $archivefiles = $packer->list_files($archive); | |
125 | $this->assertSame(array(), $archivefiles); | |
79c966cf PS |
126 | } |
127 | ||
128 | /** | |
129 | * @depends test_list_files | |
130 | */ | |
131 | public function test_archive_to_pathname() { | |
132 | global $CFG; | |
133 | ||
134 | $this->resetAfterTest(false); | |
135 | ||
136 | $packer = get_file_packer('application/zip'); | |
137 | $archive = "$CFG->tempdir/archive.zip"; | |
138 | ||
01b4040a | 139 | $this->assertFileNotExists($archive); |
79c966cf PS |
140 | $result = $packer->archive_to_pathname($this->files, $archive); |
141 | $this->assertTrue($result); | |
01b4040a | 142 | $this->assertFileExists($archive); |
79c966cf PS |
143 | |
144 | $archivefiles = $packer->list_files($archive); | |
145 | $this->assertTrue(is_array($archivefiles)); | |
146 | $this->assertEquals(count($this->files), count($archivefiles)); | |
5f15f7c9 | 147 | foreach ($archivefiles as $file) { |
79c966cf PS |
148 | $this->assertArrayHasKey($file->pathname, $this->files); |
149 | } | |
f6b49abf PS |
150 | |
151 | // Test invalid files parameter. | |
152 | $archive = "$CFG->tempdir/archive2.zip"; | |
01b4040a | 153 | $this->assertFileNotExists($archive); |
f6b49abf | 154 | |
01b4040a | 155 | $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); |
f6b49abf | 156 | $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt'); |
1017426c | 157 | |
01b4040a | 158 | $result = $packer->archive_to_pathname($files, $archive, false); |
f6b49abf | 159 | $this->assertFalse($result); |
01b4040a PS |
160 | $this->assertDebuggingCalled(); |
161 | $this->assertFileNotExists($archive); | |
162 | ||
f6b49abf | 163 | $result = $packer->archive_to_pathname($files, $archive); |
f6b49abf | 164 | $this->assertTrue($result); |
01b4040a PS |
165 | $this->assertFileExists($archive); |
166 | $this->assertDebuggingCalled(); | |
167 | $archivefiles = $packer->list_files($archive); | |
168 | $this->assertSame(array(), $archivefiles); | |
169 | unlink($archive); | |
f6b49abf | 170 | |
01b4040a PS |
171 | $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); |
172 | $this->assertFileExists(__DIR__.'/fixtures/test.txt'); | |
173 | $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt', 'test.txt'=>__DIR__.'/fixtures/test.txt', 'ytest.txt'=>__DIR__.'/xx/yy/yy.txt'); | |
174 | $result = $packer->archive_to_pathname($files, $archive); | |
175 | $this->assertTrue($result); | |
176 | $this->assertFileExists($archive); | |
177 | $archivefiles = $packer->list_files($archive); | |
178 | $this->assertCount(1, $archivefiles); | |
179 | $this->assertEquals('test.txt', $archivefiles[0]->pathname); | |
180 | $dms = $this->getDebuggingMessages(); | |
181 | $this->assertCount(2, $dms); | |
182 | $this->resetDebugging(); | |
183 | unlink($archive); | |
79c966cf PS |
184 | } |
185 | ||
186 | /** | |
187 | * @depends test_archive_to_pathname | |
188 | */ | |
189 | public function test_archive_to_storage() { | |
190 | $this->resetAfterTest(false); | |
191 | ||
192 | $packer = get_file_packer('application/zip'); | |
193 | $fs = get_file_storage(); | |
194 | $context = context_system::instance(); | |
195 | ||
196 | $this->assertFalse($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); | |
197 | $result = $packer->archive_to_storage($this->files, $context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); | |
198 | $this->assertInstanceOf('stored_file', $result); | |
199 | $this->assertTrue($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); | |
200 | ||
201 | $archivefiles = $result->list_files($packer); | |
202 | $this->assertTrue(is_array($archivefiles)); | |
203 | $this->assertEquals(count($this->files), count($archivefiles)); | |
5f15f7c9 | 204 | foreach ($archivefiles as $file) { |
79c966cf PS |
205 | $this->assertArrayHasKey($file->pathname, $this->files); |
206 | } | |
207 | } | |
208 | ||
209 | /** | |
210 | * @depends test_archive_to_storage | |
211 | */ | |
212 | public function test_extract_to_pathname() { | |
213 | global $CFG; | |
214 | ||
215 | $this->resetAfterTest(false); | |
216 | ||
217 | $packer = get_file_packer('application/zip'); | |
218 | $fs = get_file_storage(); | |
219 | $context = context_system::instance(); | |
220 | ||
221 | $target = "$CFG->tempdir/test/"; | |
222 | $testcontent = file_get_contents($this->testfile); | |
223 | ||
224 | @mkdir($target, $CFG->directorypermissions); | |
225 | $this->assertTrue(is_dir($target)); | |
226 | ||
227 | $archive = "$CFG->tempdir/archive.zip"; | |
01b4040a | 228 | $this->assertFileExists($archive); |
79c966cf PS |
229 | $result = $packer->extract_to_pathname($archive, $target); |
230 | $this->assertTrue(is_array($result)); | |
231 | $this->assertEquals(count($this->files), count($result)); | |
5f15f7c9 | 232 | foreach ($this->files as $file => $unused) { |
79c966cf | 233 | $this->assertTrue($result[$file]); |
01b4040a | 234 | $this->assertFileExists($target.$file); |
79c966cf PS |
235 | $this->assertSame($testcontent, file_get_contents($target.$file)); |
236 | } | |
237 | ||
238 | $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); | |
239 | $this->assertNotEmpty($archive); | |
240 | $result = $packer->extract_to_pathname($archive, $target); | |
241 | $this->assertTrue(is_array($result)); | |
242 | $this->assertEquals(count($this->files), count($result)); | |
5f15f7c9 | 243 | foreach ($this->files as $file => $unused) { |
79c966cf | 244 | $this->assertTrue($result[$file]); |
01b4040a | 245 | $this->assertFileExists($target.$file); |
79c966cf PS |
246 | $this->assertSame($testcontent, file_get_contents($target.$file)); |
247 | } | |
248 | } | |
249 | ||
e462f46b FM |
250 | /** |
251 | * @depends test_archive_to_storage | |
252 | */ | |
253 | public function test_extract_to_pathname_onlyfiles() { | |
254 | global $CFG; | |
255 | ||
256 | $this->resetAfterTest(false); | |
257 | ||
258 | $packer = get_file_packer('application/zip'); | |
259 | $fs = get_file_storage(); | |
260 | $context = context_system::instance(); | |
261 | ||
262 | $target = "$CFG->tempdir/onlyfiles/"; | |
263 | $testcontent = file_get_contents($this->testfile); | |
264 | ||
265 | @mkdir($target, $CFG->directorypermissions); | |
266 | $this->assertTrue(is_dir($target)); | |
267 | ||
268 | $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist'); | |
269 | $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles); | |
270 | $donotextract = array_diff(array_keys($this->files), $onlyfiles); | |
271 | ||
272 | $archive = "$CFG->tempdir/archive.zip"; | |
01b4040a | 273 | $this->assertFileExists($archive); |
e462f46b FM |
274 | $result = $packer->extract_to_pathname($archive, $target, $onlyfiles); |
275 | $this->assertTrue(is_array($result)); | |
276 | $this->assertEquals(count($willbeextracted), count($result)); | |
277 | ||
5f15f7c9 | 278 | foreach ($willbeextracted as $file) { |
e462f46b | 279 | $this->assertTrue($result[$file]); |
01b4040a | 280 | $this->assertFileExists($target.$file); |
e462f46b FM |
281 | $this->assertSame($testcontent, file_get_contents($target.$file)); |
282 | } | |
5f15f7c9 | 283 | foreach ($donotextract as $file) { |
e462f46b | 284 | $this->assertFalse(isset($result[$file])); |
01b4040a | 285 | $this->assertFileNotExists($target.$file); |
e462f46b FM |
286 | } |
287 | ||
288 | } | |
289 | ||
79c966cf PS |
290 | /** |
291 | * @depends test_archive_to_storage | |
292 | */ | |
293 | public function test_extract_to_storage() { | |
294 | global $CFG; | |
295 | ||
01b4040a | 296 | $this->resetAfterTest(false); |
79c966cf PS |
297 | |
298 | $packer = get_file_packer('application/zip'); | |
299 | $fs = get_file_storage(); | |
300 | $context = context_system::instance(); | |
301 | ||
302 | $testcontent = file_get_contents($this->testfile); | |
303 | ||
304 | $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); | |
305 | $this->assertNotEmpty($archive); | |
306 | $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); | |
307 | $this->assertTrue(is_array($result)); | |
308 | $this->assertEquals(count($this->files), count($result)); | |
5f15f7c9 | 309 | foreach ($this->files as $file => $unused) { |
79c966cf PS |
310 | $this->assertTrue($result[$file]); |
311 | $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); | |
312 | $this->assertInstanceOf('stored_file', $stored_file); | |
313 | $this->assertSame($testcontent, $stored_file->get_content()); | |
314 | } | |
315 | ||
316 | $archive = "$CFG->tempdir/archive.zip"; | |
01b4040a | 317 | $this->assertFileExists($archive); |
79c966cf PS |
318 | $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); |
319 | $this->assertTrue(is_array($result)); | |
320 | $this->assertEquals(count($this->files), count($result)); | |
5f15f7c9 | 321 | foreach ($this->files as $file => $unused) { |
79c966cf PS |
322 | $this->assertTrue($result[$file]); |
323 | $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); | |
324 | $this->assertInstanceOf('stored_file', $stored_file); | |
325 | $this->assertSame($testcontent, $stored_file->get_content()); | |
326 | } | |
01b4040a PS |
327 | unlink($archive); |
328 | } | |
329 | ||
330 | /** | |
331 | * @depends test_extract_to_storage | |
332 | */ | |
333 | public function test_add_files() { | |
334 | global $CFG; | |
335 | ||
336 | $this->resetAfterTest(false); | |
337 | ||
338 | $packer = get_file_packer('application/zip'); | |
339 | $archive = "$CFG->tempdir/archive.zip"; | |
340 | ||
341 | $this->assertFileNotExists($archive); | |
342 | $packer->archive_to_pathname(array(), $archive); | |
343 | $this->assertFileExists($archive); | |
344 | ||
345 | $zip_archive = new zip_archive(); | |
346 | $zip_archive->open($archive, file_archive::OPEN); | |
347 | $this->assertEquals(0, $zip_archive->count()); | |
348 | ||
349 | $zip_archive->add_file_from_string('test.txt', 'test'); | |
350 | $zip_archive->close(); | |
351 | $zip_archive->open($archive, file_archive::OPEN); | |
352 | $this->assertEquals(1, $zip_archive->count()); | |
353 | ||
354 | $zip_archive->add_directory('test2'); | |
355 | $zip_archive->close(); | |
356 | $zip_archive->open($archive, file_archive::OPEN); | |
357 | $files = $zip_archive->list_files(); | |
358 | $this->assertCount(2, $files); | |
359 | $this->assertEquals('test.txt', $files[0]->pathname); | |
360 | $this->assertEquals('test2/', $files[1]->pathname); | |
361 | ||
362 | $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt'); | |
363 | $this->assertFalse($result); | |
364 | $zip_archive->close(); | |
365 | $zip_archive->open($archive, file_archive::OPEN); | |
366 | $this->assertEquals(2, $zip_archive->count()); | |
96846ef1 | 367 | $zip_archive->close(); |
01b4040a PS |
368 | |
369 | unlink($archive); | |
370 | } | |
371 | ||
372 | /** | |
373 | * @depends test_add_files | |
374 | */ | |
375 | public function test_open_archive() { | |
376 | global $CFG; | |
377 | ||
378 | $this->resetAfterTest(true); | |
379 | ||
380 | $archive = "$CFG->tempdir/archive.zip"; | |
381 | ||
382 | $this->assertFileNotExists($archive); | |
383 | ||
384 | $zip_archive = new zip_archive(); | |
385 | $result = $zip_archive->open($archive, file_archive::OPEN); | |
386 | $this->assertFalse($result); | |
387 | $this->assertDebuggingCalled(); | |
388 | ||
389 | $zip_archive = new zip_archive(); | |
390 | $result = $zip_archive->open($archive, file_archive::CREATE); | |
391 | $this->assertTrue($result); | |
392 | $zip_archive->add_file_from_string('test.txt', 'test'); | |
393 | $zip_archive->close(); | |
394 | $zip_archive->open($archive, file_archive::OPEN); | |
395 | $this->assertEquals(1, $zip_archive->count()); | |
396 | ||
397 | $zip_archive = new zip_archive(); | |
398 | $result = $zip_archive->open($archive, file_archive::OVERWRITE); | |
399 | $this->assertTrue($result); | |
400 | $zip_archive->add_file_from_string('test2.txt', 'test'); | |
401 | $zip_archive->close(); | |
402 | $zip_archive->open($archive, file_archive::OPEN); | |
403 | $this->assertEquals(1, $zip_archive->count()); | |
96846ef1 | 404 | $zip_archive->close(); |
01b4040a PS |
405 | |
406 | unlink($archive); | |
407 | $zip_archive = new zip_archive(); | |
408 | $result = $zip_archive->open($archive, file_archive::OVERWRITE); | |
409 | $this->assertTrue($result); | |
410 | $zip_archive->add_file_from_string('test2.txt', 'test'); | |
411 | $zip_archive->close(); | |
412 | $zip_archive->open($archive, file_archive::OPEN); | |
413 | $this->assertEquals(1, $zip_archive->count()); | |
96846ef1 PS |
414 | $zip_archive->close(); |
415 | ||
416 | unlink($archive); | |
79c966cf PS |
417 | } |
418 | } |