[FEATURE] Allow Storages outside the webroot
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Resource / Driver / LocalDriverTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Resource\Driver;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011-2013 Andreas Wolf <andreas.wolf@ikt-werk.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31 use \org\bovigo\vfs\vfsStream;
32 use \org\bovigo\vfs\vfsStreamWrapper;
33
34 /**
35 * Testcase for the local storage driver class of the TYPO3 VFS
36 *
37 * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
38 */
39 class LocalDriverTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase {
40
41 /**
42 * @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver
43 */
44 protected $localDriver = NULL;
45
46 /**
47 * @var array A backup of registered singleton instances
48 */
49 protected $singletonInstances = array();
50
51 /**
52 * @var array
53 */
54 protected $testDirs = array();
55
56 /**
57 * @var string
58 */
59 protected $iso88591GreaterThan127 = '';
60
61 /**
62 * @var string
63 */
64 protected $utf8Latin1Supplement = '';
65
66 /**
67 * @var string
68 */
69 protected $utf8Latin1ExtendedA = '';
70
71 /**
72 * Tear down
73 */
74 public function tearDown() {
75 foreach ($this->testDirs as $dir) {
76 chmod($dir, 0777);
77 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($dir, TRUE);
78 }
79 parent::tearDown();
80 }
81
82 /**
83 * Creates a "real" directory for doing tests. This is necessary because some file system properties (e.g. permissions)
84 * cannot be reflected by vfsStream, and some methods (like touch()) don't work there either.
85 *
86 * Created directories are automatically destroyed during tearDown()
87 *
88 * @return string
89 */
90 protected function createRealTestdir() {
91 $basedir = PATH_site . 'typo3temp/' . uniqid('fal-test-');
92 mkdir($basedir);
93 $this->testDirs[] = $basedir;
94 return $basedir;
95 }
96
97 /**
98 * Create a "real" directory together with a driverFixture configured
99 * for this directory.
100 *
101 * @return array With path to base directory and driver fixture
102 */
103 protected function prepareRealTestEnvironment() {
104 $basedir = $this->createRealTestdir();
105 $fixture = $this->createDriverFixture(array(
106 'basePath' => $basedir
107 ));
108 return array($basedir, $fixture);
109 }
110
111 /**
112 * Creates a driver fixture object, optionally using a given mount object.
113 *
114 * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
115 *
116 * @param array $driverConfiguration
117 * @param array $mockedDriverMethods
118 * @return \TYPO3\CMS\Core\Resource\Driver\LocalDriver
119 */
120 protected function createDriverFixture($driverConfiguration = array(), $mockedDriverMethods = array()) {
121 // it's important to do that here, so vfsContents could have been set before
122 if (!isset($driverConfiguration['basePath'])) {
123 $this->initializeVfs();
124 $driverConfiguration['basePath'] = $this->getMountRootUrl();
125 }
126 /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver $driver */
127 $mockedDriverMethods[] = 'isPathValid';
128 $driver = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', $mockedDriverMethods, array($driverConfiguration));
129 $driver->expects($this->any())
130 ->method('isPathValid')
131 ->will(
132 $this->returnValue(TRUE)
133 );
134
135 $driver->setStorageUid(5);
136 $driver->processConfiguration();
137 $driver->initialize();
138 return $driver;
139 }
140
141 /**
142 * @test
143 */
144 public function getDefaultFolderReturnsFolderForUserUploadPath() {
145 $fixture = $this->createDriverFixture();
146 $folderIdentifier = $fixture->getDefaultFolder();
147 $this->assertEquals('/user_upload/', $folderIdentifier);
148 }
149
150 /**
151 * @test
152 */
153 public function defaultLevelFolderFolderIsCreatedIfItDoesntExist() {
154 $fixture = $this->createDriverFixture();
155 $this->assertFileExists($this->getUrlInMount($fixture->getDefaultFolder()));
156 }
157
158 /**
159 * @test
160 */
161 public function getFolderInFolderReturnsCorrectFolderObject() {
162 $this->addToMount(array(
163 'someDir' => array(
164 'someSubdir' => array()
165 )
166 ));
167 $fixture = $this->createDriverFixture();
168 $folder = $fixture->getFolderInFolder('someSubdir', '/someDir/');
169 $this->assertEquals('/someDir/someSubdir/', $folder);
170 }
171
172 /**
173 * @test
174 */
175 public function createFolderCreatesFolderOnDisk() {
176 $this->addToMount(array('some' => array('folder' => array())));
177 $fixture = $this->createDriverFixture();
178 $fixture->createFolder('path', '/some/folder/');
179 $this->assertFileExists($this->getUrlInMount('/some/folder/'));
180 $this->assertFileExists($this->getUrlInMount('/some/folder/path'));
181 }
182
183 /**
184 * @test
185 */
186 public function createFolderReturnsFolderObject() {
187 $this->addToMount(array('some' => array('folder' => array())));
188 $fixture = $this->createDriverFixture();
189 $createdFolder = $fixture->createFolder('path', '/some/folder/');
190 $this->assertEquals('/some/folder/path/', $createdFolder);
191 }
192
193 public static function createFolderSanitizesFolderNameBeforeCreationDataProvider() {
194 return array(
195 'folder name with NULL character' => array(
196 'some' . chr(0) . 'Folder',
197 'some_Folder'
198 ),
199 'folder name with directory part' => array(
200 '../someFolder',
201 '.._someFolder'
202 )
203 );
204 }
205
206 /**
207 * @test
208 * @dataProvider createFolderSanitizesFolderNameBeforeCreationDataProvider
209 */
210 public function createFolderSanitizesFolderNameBeforeCreation($newFolderName, $expectedFolderName) {
211 $this->addToMount(array('some' => array('folder' => array())));
212 $fixture = $this->createDriverFixture();
213 $fixture->createFolder($newFolderName, '/some/folder/');
214 $this->assertFileExists($this->getUrlInMount('/some/folder/' . $expectedFolderName));
215 }
216
217 /**
218 * @test
219 */
220 public function basePathIsNormalizedWithTrailingSlash() {
221 $fixture = $this->createDriverFixture();
222 $this->assertEquals('/', substr($fixture->_call('getAbsoluteBasePath'), -1));
223 }
224
225 /**
226 * @test
227 */
228 public function noSecondSlashIsAddedIfBasePathAlreadyHasTrailingSlash() {
229 $fixture = $this->createDriverFixture();
230 $this->assertNotEquals('/', substr($fixture->_call('getAbsoluteBasePath'), -2, 1));
231 }
232
233 /**
234 * @test
235 */
236 public function getAbsolutePathReturnsCorrectPath() {
237 $this->addToMount(array(
238 'someFolder' => array(
239 'file1.ext' => 'asdfg'
240 )
241 ));
242 $fixture = $this->createDriverFixture();
243 $path = $fixture->_call('getAbsolutePath', '/someFolder/file1.ext');
244 $this->assertTrue(file_exists($path));
245 $this->assertEquals($this->getUrlInMount('/someFolder/file1.ext'), $path);
246 }
247
248 /**
249 * @test
250 */
251 public function addFileMovesFileToCorrectLocation() {
252 $this->addToMount(array('targetFolder' => array()));
253 $this->addToVfs(array(
254 'sourceFolder' => array(
255 'file' => 'asdf'
256 )
257 ));
258 $fixture = $this->createDriverFixture(
259 array(),
260 array('getMimeTypeOfFile')
261 );
262 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
263 $fixture->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'file');
264 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/file')));
265 }
266
267 /**
268 * @test
269 */
270 public function addFileUsesFilenameIfGiven() {
271 $this->addToMount(array('targetFolder' => array()));
272 $this->addToVfs(array(
273 'sourceFolder' => array(
274 'file' => 'asdf'
275 )
276 ));
277 $fixture = $this->createDriverFixture(
278 array(),
279 array('getMimeTypeOfFile')
280 );
281 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
282 $fixture->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'targetFile');
283 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/targetFile')));
284 }
285
286 /**
287 * @test
288 */
289 public function addFileFailsIfFileIsInDriverStorage() {
290 $this->setExpectedException('InvalidArgumentException', '', 1314778269);
291 $this->addToMount(array(
292 'targetFolder' => array(
293 'file' => 'asdf'
294 )
295 ));
296 $fixture = $this->createDriverFixture();
297 $fixture->addFile($this->getUrlInMount('/targetFolder/file'), '/targetFolder/', 'file');
298 }
299
300 /**
301 * @test
302 */
303 public function addFileReturnsFileIdentifier() {
304 $this->addToMount(array('targetFolder' => array()));
305 $this->addToVfs(array(
306 'sourceFolder' => array(
307 'file' => 'asdf'
308 )
309 ));
310 $fixture = $this->createDriverFixture(
311 array(),
312 array('getMimeTypeOfFile')
313 );
314 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
315 $fileIdentifier = $fixture->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'file');
316 $this->assertEquals('file', basename($fileIdentifier));
317 $this->assertEquals('/targetFolder/file', $fileIdentifier);
318 }
319
320 /**
321 * @test
322 */
323 public function existenceChecksWorkForFilesAndFolders() {
324 $this->addToMount(array(
325 'file' => 'asdf',
326 'folder' => array()
327 ));
328 $fixture = $this->createDriverFixture();
329 // Using slashes at the beginning of paths because they will be stored in the DB this way.
330 $this->assertTrue($fixture->fileExists('/file'));
331 $this->assertTrue($fixture->folderExists('/folder/'));
332 $this->assertFalse($fixture->fileExists('/nonexistingFile'));
333 $this->assertFalse($fixture->folderExists('/nonexistingFolder/'));
334 }
335
336 /**
337 * @test
338 */
339 public function existenceChecksInFolderWorkForFilesAndFolders() {
340 $this->addToMount(array(
341 'subfolder' => array(
342 'file' => 'asdf',
343 'folder' => array()
344 )
345 ));
346 $fixture = $this->createDriverFixture();
347 $this->assertTrue($fixture->fileExistsInFolder('file', '/subfolder/'));
348 $this->assertTrue($fixture->folderExistsInFolder('folder', '/subfolder/'));
349 $this->assertFalse($fixture->fileExistsInFolder('nonexistingFile', '/subfolder/'));
350 $this->assertFalse($fixture->folderExistsInFolder('nonexistingFolder', '/subfolder/'));
351 }
352
353 /**
354 * @test
355 */
356 public function getPublicUrlReturnsCorrectUriForConfiguredBaseUri() {
357 $baseUri = 'http://example.org/foobar/' . uniqid();
358 $this->addToMount(array(
359 'file.ext' => 'asdf',
360 'subfolder' => array(
361 'file2.ext' => 'asdf'
362 )
363 ));
364 $fixture = $this->createDriverFixture(array(
365 'baseUri' => $baseUri
366 ));
367 $this->assertEquals($baseUri . '/file.ext', $fixture->getPublicUrl('/file.ext'));
368 $this->assertEquals($baseUri . '/subfolder/file2.ext', $fixture->getPublicUrl('/subfolder/file2.ext'));
369 }
370
371 /**
372 * Data provider for getPublicUrlReturnsValidUrlContainingSpecialCharacters().
373 *
374 * @return array
375 */
376 public function getPublicUrlReturnsValidUrlContainingSpecialCharacters_dataProvider() {
377 return array(
378 array('/single file with some special chars äüö!.txt'),
379 array('/on subfolder/with special chars äüö!.ext'),
380 array('/who names a file like !"§$%&()=?*+~"#\'´`<>-.ext'),
381 array('no leading slash !"§$%&()=?*+~#\'"´`"<>-.txt')
382 );
383 }
384
385 /**
386 * @test
387 * @dataProvider getPublicUrlReturnsValidUrlContainingSpecialCharacters_dataProvider
388 */
389 public function getPublicUrlReturnsValidUrlContainingSpecialCharacters($fileIdentifier) {
390 $baseUri = 'http://example.org/foobar/' . uniqid();
391 $fixture = $this->createDriverFixture(array(
392 'baseUri' => $baseUri
393 ));
394 $publicUrl = $fixture->getPublicUrl($fileIdentifier);
395 $this->assertTrue(GeneralUtility::isValidUrl($publicUrl), 'getPublicUrl did not return a valid URL:' . $publicUrl);
396 }
397
398 /**
399 * @test
400 */
401 public function fileContentsCanBeWrittenAndRead() {
402 $fileContents = 'asdf';
403 $this->addToMount(array(
404 'file.ext' => $fileContents
405 ));
406 $fixture = $this->createDriverFixture();
407 $this->assertEquals($fileContents, $fixture->getFileContents('/file.ext'), 'File contents could not be read');
408 $newFileContents = 'asdfgh';
409 $fixture->setFileContents('/file.ext', $newFileContents);
410 $this->assertEquals($newFileContents, $fixture->getFileContents('/file.ext'), 'New file contents could not be read.');
411 }
412
413 /**
414 * @test
415 */
416 public function setFileContentsReturnsNumberOfBytesWrittenToFile() {
417 $fileContents = 'asdf';
418 $this->addToMount(array(
419 'file.ext' => $fileContents
420 ));
421 $fixture = $this->createDriverFixture();
422 $newFileContents = 'asdfgh';
423 $bytesWritten = $fixture->setFileContents('/file.ext', $newFileContents);
424 $this->assertEquals(strlen($newFileContents), $bytesWritten);
425 }
426
427 /**
428 * @test
429 * @see http://phpmagazin.de/vfsStream-1.1.0-nutzt-PHP-5.4-M%C3%B6glichkeiten-064406.html
430 */
431 public function newFilesCanBeCreated() {
432 if (version_compare(PHP_VERSION, '5.4.0', '<')) {
433 $this->markTestSkipped('touch() does not work with vfsStream in PHP 5.3 and below.');
434 }
435 $fixture = $this->createDriverFixture();
436 $fixture->createFile('testfile.txt', '/');
437 $this->assertTrue($fixture->fileExists('/testfile.txt'));
438 }
439
440 /**
441 * @test
442 * @see http://phpmagazin.de/vfsStream-1.1.0-nutzt-PHP-5.4-M%C3%B6glichkeiten-064406.html
443 */
444 public function createdFilesAreEmpty() {
445 if (version_compare(PHP_VERSION, '5.4.0', '<')) {
446 $this->markTestSkipped('touch() does not work with vfsStream in PHP 5.3 and below.');
447 }
448 $fixture = $this->createDriverFixture();
449 $fixture->createFile('testfile.txt', '/');
450 $this->assertTrue($fixture->fileExists('/testfile.txt'));
451 $fileData = $fixture->getFileContents('/testfile.txt');
452 $this->assertEquals(0, strlen($fileData));
453 }
454
455 /**
456 * @test
457 */
458 public function createFileFixesPermissionsOnCreatedFile() {
459 if (TYPO3_OS == 'WIN') {
460 $this->markTestSkipped('createdFilesHaveCorrectRights() tests not available on Windows');
461 }
462
463 // No one will use this as his default file create mask so we hopefully don't get any false positives
464 $testpattern = '0646';
465 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = $testpattern;
466
467 $this->addToMount(
468 array(
469 'someDir' => array()
470 )
471 );
472 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
473 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
474 mkdir($basedir . '/someDir');
475 $fixture->createFile('testfile.txt', '/someDir');
476 $this->assertEquals($testpattern, decoct(fileperms($basedir . '/someDir/testfile.txt') & 0777));
477 }
478
479 /**********************************
480 * File and directory listing
481 **********************************/
482 /**
483 * @test
484 */
485 public function getFileReturnsCorrectIdentifier() {
486 $this->addToMount(array(
487 'someDir' => array(
488 'someFile' => 'asdfg'
489 ),
490 'someFileAtRootLevel' => 'foobar'
491 ));
492 $fixture = $this->createDriverFixture(
493 array(),
494 array('getMimeTypeOfFile')
495 );
496 $subdirFileInfo = $fixture->getFileInfoByIdentifier('/someDir/someFile');
497 $this->assertEquals('/someDir/someFile', $subdirFileInfo['identifier']);
498 $rootFileInfo = $fixture->getFileInfoByIdentifier('/someFileAtRootLevel');
499 $this->assertEquals('/someFileAtRootLevel', $rootFileInfo['identifier']);
500 }
501
502 /**
503 * @test
504 */
505 public function getFileThrowsExceptionIfFileDoesNotExist() {
506 $this->setExpectedException('InvalidArgumentException', '', 1314516809);
507 $fixture = $this->createDriverFixture();
508 $fixture->getFileInfoByIdentifier('/some/file/at/a/random/path');
509 }
510
511 /**
512 * @test
513 */
514 public function getFilesInFolderReturnsEmptyArrayForEmptyDirectory() {
515 $fixture = $this->createDriverFixture();
516 $fileList = $fixture->getFilesInFolder('/');
517 $this->assertEmpty($fileList);
518 }
519
520 /**
521 * @test
522 */
523 public function getFileListReturnsAllFilesInDirectory() {
524 $dirStructure = array(
525 'aDir' => array(),
526 'file1' => 'asdfg',
527 'file2' => 'fdsa'
528 );
529 $this->addToMount($dirStructure);
530 $fixture = $this->createDriverFixture(
531 array(),
532 // Mocked because finfo() can not deal with vfs streams and throws warnings
533 array('getMimeTypeOfFile')
534 );
535 $fileList = $fixture->getFilesInFolder('/');
536 $this->assertEquals(array('/file1', '/file2'), array_keys($fileList));
537 }
538
539 /**
540 * @test
541 */
542 public function getFileListReturnsAllFilesInSubdirectoryIfRecursiveParameterIsSet() {
543 $dirStructure = array(
544 'aDir' => array(
545 'file3' => 'asdfgh',
546 'subdir' => array(
547 'file4' => 'asklfjklasjkl'
548 )
549 ),
550 'file1' => 'asdfg',
551 'file2' => 'fdsa'
552 );
553 $this->addToMount($dirStructure);
554 $fixture = $this->createDriverFixture(
555 array(),
556 // Mocked because finfo() can not deal with vfs streams and throws warnings
557 array('getMimeTypeOfFile')
558 );
559 $fileList = $fixture->getFilesInFolder('/', 0, 0, TRUE);
560 $this->assertEquals(array('/aDir/subdir/file4', '/aDir/file3', '/file1', '/file2'), array_keys($fileList));
561 }
562
563 /**
564 * @test
565 */
566 public function getFileListFailsIfDirectoryDoesNotExist() {
567 $this->setExpectedException('InvalidArgumentException', '', 1314349666);
568 $this->addToMount(array('somefile' => ''));
569 $fixture = $this->createDriverFixture();
570 $fixture->getFilesInFolder('somedir/');
571 }
572
573 /**
574 * @test
575 */
576 public function getFileInFolderCallsConfiguredCallbackFunctionWithGivenItemName() {
577 $dirStructure = array(
578 'file2' => 'fdsa'
579 );
580 // register static callback to self
581 $callback = array(
582 array(
583 get_class($this),
584 'callbackStaticTestFunction'
585 )
586 );
587 $this->addToMount($dirStructure);
588 $fixture = $this->createDriverFixture();
589 // the callback function will throw an exception used to check if it was called with correct $itemName
590 $this->setExpectedException('InvalidArgumentException', '$itemName', 1336159604);
591 $fixture->getFilesInFolder('/', 0, 0, FALSE, $callback);
592 }
593
594 /**
595 * Static callback function used to test if the filter callbacks work
596 * As it is static we are using an exception to test if it is really called and works
597 *
598 * @static
599 * @throws \InvalidArgumentException
600 * @see getFileListCallsConfiguredCallbackFunction
601 */
602 static public function callbackStaticTestFunction() {
603 list($itemName) = func_get_args();
604 if ($itemName === 'file2') {
605 throw new \InvalidArgumentException('$itemName', 1336159604);
606 }
607 }
608
609 /**
610 * @test
611 */
612 public function getFileListFiltersItemsWithGivenFilterMethods() {
613 $dirStructure = array(
614 'fileA' => 'asdfg',
615 'fileB' => 'fdsa'
616 );
617 $this->addToMount($dirStructure);
618 $fixture = $this->createDriverFixture(
619 array(),
620 // Mocked because finfo() can not deal with vfs streams and throws warnings
621 array('getMimeTypeOfFile')
622 );
623 $filterCallbacks = array(
624 array(
625 'TYPO3\CMS\Core\Tests\Unit\Resource\Driver\Fixtures\LocalDriverFilenameFilter',
626 'filterFilename',
627 ),
628 );
629 $fileList = $fixture->getFilesInFolder('/', 0, 0, FALSE, $filterCallbacks);
630 $this->assertNotContains('/fileA', array_keys($fileList));
631 }
632
633 /**
634 * @test
635 */
636 public function getFolderListReturnsAllDirectoriesInDirectory() {
637 $dirStructure = array(
638 'dir1' => array(),
639 'dir2' => array(),
640 'file' => 'asdfg'
641 );
642 $this->addToMount($dirStructure);
643 $fixture = $this->createDriverFixture();
644 $fileList = $fixture->getFoldersInFolder('/');
645 $this->assertEquals(array('/dir1/', '/dir2/'), array_keys($fileList));
646 }
647
648 /**
649 * @test
650 */
651 public function getFolderListReturnsHiddenFoldersByDefault() {
652 $dirStructure = array(
653 '.someHiddenDir' => array(),
654 'aDir' => array(),
655 'file1' => ''
656 );
657 $this->addToMount($dirStructure);
658 $fixture = $this->createDriverFixture();
659
660 $fileList = $fixture->getFoldersInFolder('/');
661
662 $this->assertEquals(array('/.someHiddenDir/', '/aDir/'), array_keys($fileList));
663 }
664
665 /**
666 * Checks if the folder names . and .. are ignored when listing subdirectories
667 *
668 * @test
669 */
670 public function getFolderListLeavesOutNavigationalEntries() {
671 // we have to add .. and . manually, as these are not included in vfsStream directory listings (as opposed
672 // to normal file listings)
673 $this->addToMount(array(
674 '..' => array(),
675 '.' => array()
676 ));
677 $fixture = $this->createDriverFixture();
678 $fileList = $fixture->getFoldersInFolder('/');
679 $this->assertEmpty($fileList);
680 }
681
682 /**
683 * @test
684 */
685 public function getFolderListFiltersItemsWithGivenFilterMethods() {
686 $dirStructure = array(
687 'folderA' => array(),
688 'folderB' => array()
689 );
690 $this->addToMount($dirStructure);
691 $fixture = $this->createDriverFixture();
692 $filterCallbacks = array(
693 array(
694 'TYPO3\CMS\Core\Tests\Unit\Resource\Driver\Fixtures\LocalDriverFilenameFilter',
695 'filterFilename',
696 ),
697 );
698 $folderList = $fixture->getFoldersInFolder('/', 0, 0, $filterCallbacks);
699 $this->assertNotContains('folderA', array_keys($folderList));
700 }
701
702 /**
703 * @test
704 */
705 public function getFolderListFailsIfDirectoryDoesNotExist() {
706 $this->setExpectedException('InvalidArgumentException', '', 1314349666);
707 $fixture = $this->createDriverFixture();
708 vfsStream::create(array($this->basedir => array('somefile' => '')));
709 $fixture->getFoldersInFolder('somedir/');
710 }
711
712 /**
713 * @test
714 */
715 public function hashReturnsCorrectHashes() {
716 $contents = '68b329da9893e34099c7d8ad5cb9c940';
717 $expectedMd5Hash = '8c67dbaf0ba22f2e7fbc26413b86051b';
718 $expectedSha1Hash = 'a60cd808ba7a0bcfa37fa7f3fb5998e1b8dbcd9d';
719 $this->addToMount(array('hashFile' => $contents));
720 $fixture = $this->createDriverFixture();
721 $this->assertEquals($expectedSha1Hash, $fixture->hash('/hashFile', 'sha1'));
722 $this->assertEquals($expectedMd5Hash, $fixture->hash('/hashFile', 'md5'));
723 }
724
725 /**
726 * @test
727 */
728 public function hashingWithUnsupportedAlgorithmFails() {
729 $this->setExpectedException('InvalidArgumentException', '', 1304964032);
730 $fixture = $this->createDriverFixture();
731 $fixture->hash('/hashFile', uniqid());
732 }
733
734 /**
735 * @test
736 * @covers TYPO3\CMS\Core\Resource\Driver\LocalDriver::getFileForLocalProcessing
737 */
738 public function getFileForLocalProcessingCreatesCopyOfFileByDefault() {
739 $fileContents = 'asdfgh';
740 $this->addToMount(array(
741 'someDir' => array(
742 'someFile' => $fileContents
743 )
744 ));
745 $fixture = $this->createDriverFixture(array(), array('copyFileToTemporaryPath'));
746 $fixture->expects($this->once())->method('copyFileToTemporaryPath');
747 $fixture->getFileForLocalProcessing('/someDir/someFile');
748 }
749
750 /**
751 * @test
752 */
753 public function getFileForLocalProcessingReturnsOriginalFilepathForReadonlyAccess() {
754 $fileContents = 'asdfgh';
755 $this->addToMount(array(
756 'someDir' => array(
757 'someFile' => $fileContents
758 )
759 ));
760 $fixture = $this->createDriverFixture();
761 $filePath = $fixture->getFileForLocalProcessing('/someDir/someFile', FALSE);
762 $this->assertEquals($filePath, $this->getUrlInMount('someDir/someFile'));
763 }
764
765 /**
766 * @test
767 */
768 public function filesCanBeCopiedToATemporaryPath() {
769 $fileContents = 'asdfgh';
770 $this->addToMount(array(
771 'someDir' => array(
772 'someFile' => $fileContents
773 )
774 ));
775 $fixture = $this->createDriverFixture();
776 $filePath = GeneralUtility::fixWindowsFilePath($fixture->_call('copyFileToTemporaryPath', '/someDir/someFile'));
777 $this->assertContains('/typo3temp/', $filePath);
778 $this->assertEquals($fileContents, file_get_contents($filePath));
779 }
780
781 /**
782 * @test
783 */
784 public function permissionsAreCorrectlyRetrievedForAllowedFile() {
785 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
786 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
787 touch($basedir . '/someFile');
788 chmod($basedir . '/someFile', 448);
789 clearstatcache();
790 $this->assertEquals(array('r' => TRUE, 'w' => TRUE), $fixture->getPermissions('/someFile'));
791 }
792
793 /**
794 * @test
795 */
796 public function permissionsAreCorrectlyRetrievedForForbiddenFile() {
797 if (function_exists('posix_getegid') && posix_getegid() === 0) {
798 $this->markTestSkipped('Test skipped if run on linux as root');
799 } elseif (TYPO3_OS === 'WIN') {
800 $this->markTestSkipped('Test skipped if run on Windows system');
801 }
802 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
803 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
804 touch($basedir . '/someForbiddenFile');
805 chmod($basedir . '/someForbiddenFile', 0);
806 clearstatcache();
807 $this->assertEquals(array('r' => FALSE, 'w' => FALSE), $fixture->getPermissions('/someForbiddenFile'));
808 }
809
810 /**
811 * @test
812 */
813 public function permissionsAreCorrectlyRetrievedForAllowedFolder() {
814 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
815 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
816 mkdir($basedir . '/someFolder');
817 chmod($basedir . '/someFolder', 448);
818 clearstatcache();
819 $this->assertEquals(array('r' => TRUE, 'w' => TRUE), $fixture->getPermissions('/someFolder'));
820 }
821
822 /**
823 * @test
824 */
825 public function permissionsAreCorrectlyRetrievedForForbiddenFolder() {
826 if (function_exists('posix_getegid') && posix_getegid() === 0) {
827 $this->markTestSkipped('Test skipped if run on linux as root');
828 } elseif (TYPO3_OS === 'WIN') {
829 $this->markTestSkipped('Test skipped if run on Windows system');
830 }
831 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
832 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
833 mkdir($basedir . '/someForbiddenFolder');
834 chmod($basedir . '/someForbiddenFolder', 0);
835 clearstatcache();
836 $result = $fixture->getPermissions('/someForbiddenFolder');
837 // Change permissions back to writable, so the sub-folder can be removed in tearDown
838 chmod($basedir . '/someForbiddenFolder', 0777);
839 $this->assertEquals(array('r' => FALSE, 'w' => FALSE), $result);
840 }
841
842 /**
843 * Dataprovider for getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser test
844 *
845 * @return array group, filemode and expected result
846 */
847 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider() {
848 $data = array();
849 // On some OS, the posix_* functions do not exits
850 if (function_exists('posix_getgid')) {
851 $data = array(
852 'current group, readable/writable' => array(
853 posix_getgid(),
854 48,
855 array('r' => TRUE, 'w' => TRUE)
856 ),
857 'current group, readable/not writable' => array(
858 posix_getgid(),
859 32,
860 array('r' => TRUE, 'w' => FALSE)
861 ),
862 'current group, not readable/not writable' => array(
863 posix_getgid(),
864 0,
865 array('r' => FALSE, 'w' => FALSE)
866 )
867 );
868 }
869 $data = array_merge_recursive($data, array(
870 'arbitrary group, readable/writable' => array(
871 vfsStream::GROUP_USER_1,
872 6,
873 array('r' => TRUE, 'w' => TRUE)
874 ),
875 'arbitrary group, readable/not writable' => array(
876 vfsStream::GROUP_USER_1,
877 436,
878 array('r' => TRUE, 'w' => FALSE)
879 ),
880 'arbitrary group, not readable/not writable' => array(
881 vfsStream::GROUP_USER_1,
882 432,
883 array('r' => FALSE, 'w' => FALSE)
884 )
885 ));
886 return $data;
887 }
888
889 /**
890 * @test
891 * @dataProvider getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider
892 */
893 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser($group, $permissions, $expectedResult) {
894 if (TYPO3_OS === 'WIN') {
895 $this->markTestSkipped('Test skipped if run on Windows system');
896 }
897 $this->addToMount(array(
898 'testfile' => 'asdfg'
899 ));
900 $fixture = $this->createDriverFixture();
901 /** @var $fileObject vfsStreamContent */
902 $fileObject = vfsStreamWrapper::getRoot()->getChild($this->mountDir)->getChild('testfile');
903 // just use an "arbitrary" user here - it is only important that
904 $fileObject->chown(vfsStream::OWNER_USER_1);
905 $fileObject->chgrp($group);
906 $fileObject->chmod($permissions);
907 $this->assertEquals($expectedResult, $fixture->getPermissions('/testfile'));
908 }
909
910 /**
911 * @test
912 */
913 public function isWithinRecognizesFilesWithinFolderAndInOtherFolders() {
914 $fixture = $this->createDriverFixture();
915 $this->assertTrue($fixture->isWithin('/someFolder/', '/someFolder/test.jpg'));
916 $this->assertTrue($fixture->isWithin('/someFolder/', '/someFolder/subFolder/test.jpg'));
917 $this->assertFalse($fixture->isWithin('/someFolder/', '/someFolderWithALongName/test.jpg'));
918 }
919
920 /**
921 * @test
922 */
923 public function isWithinAcceptsFileAndFolderObjectsAsContent() {
924 $fixture = $this->createDriverFixture();
925 $this->assertTrue($fixture->isWithin('/someFolder/', '/someFolder/test.jpg'));
926 $this->assertTrue($fixture->isWithin('/someFolder/', '/someFolder/subfolder/'));
927 }
928
929 /**********************************
930 * Copy/move file
931 **********************************/
932
933 /**
934 * @test
935 */
936 public function filesCanBeCopiedWithinStorage() {
937 $fileContents = uniqid();
938 $this->addToMount(array(
939 'someFile' => $fileContents,
940 'targetFolder' => array()
941 ));
942 $fixture = $this->createDriverFixture(
943 array(),
944 array('getMimeTypeOfFile')
945 );
946 $fixture->copyFileWithinStorage('/someFile', '/targetFolder/', 'someFile');
947 $this->assertFileEquals($this->getUrlInMount('/someFile'), $this->getUrlInMount('/targetFolder/someFile'));
948 }
949
950 /**
951 * @test
952 */
953 public function filesCanBeMovedWithinStorage() {
954 $fileContents = uniqid();
955 $this->addToMount(array(
956 'targetFolder' => array(),
957 'someFile' => $fileContents
958 ));
959 $fixture = $this->createDriverFixture();
960 $newIdentifier = $fixture->moveFileWithinStorage('/someFile', '/targetFolder/', 'file');
961 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/file')));
962 $this->assertFileNotExists($this->getUrlInMount('/someFile'));
963 $this->assertEquals('/targetFolder/file', $newIdentifier);
964 }
965
966 /**
967 * @test
968 */
969 public function fileMetadataIsChangedAfterMovingFile() {
970 $fileContents = uniqid();
971 $this->addToMount(array(
972 'targetFolder' => array(),
973 'someFile' => $fileContents
974 ));
975 $fixture = $this->createDriverFixture(
976 array(),
977 // Mocked because finfo() can not deal with vfs streams and throws warnings
978 array('getMimeTypeOfFile')
979 );
980 $newIdentifier = $fixture->moveFileWithinStorage('/someFile', '/targetFolder/', 'file');
981 $fileMetadata = $fixture->getFileInfoByIdentifier($newIdentifier);
982 $this->assertEquals($newIdentifier, $fileMetadata['identifier']);
983 }
984
985 public function renamingFiles_dataProvider() {
986 return array(
987 'file in subfolder' => array(
988 array(
989 'targetFolder' => array('file' => '')
990 ),
991 '/targetFolder/file',
992 'newFile',
993 '/targetFolder/newFile'
994 ),
995 'file in rootfolder' => array(
996 array(
997 'fileInRoot' => ''
998 ),
999 '/fileInRoot',
1000 'newFile',
1001 '/newFile'
1002 )
1003 );
1004 }
1005
1006 /**
1007 * @test
1008 * @dataProvider renamingFiles_dataProvider
1009 */
1010 public function renamingFilesChangesFilenameOnDisk(array $filesystemStructure, $oldFileIdentifier, $newFileName, $expectedNewIdentifier) {
1011 $this->addToMount($filesystemStructure);
1012 $fixture = $this->createDriverFixture();
1013 $newIdentifier = $fixture->renameFile($oldFileIdentifier, $newFileName);
1014 $this->assertFalse($fixture->fileExists($oldFileIdentifier));
1015 $this->assertTrue($fixture->fileExists($newIdentifier));
1016 $this->assertEquals($expectedNewIdentifier, $newIdentifier);
1017 }
1018
1019 /**
1020 * @test
1021 */
1022 public function renamingFilesFailsIfTargetFileExists() {
1023 $this->setExpectedException('TYPO3\\CMS\\Core\\Resource\\Exception\\ExistingTargetFileNameException', '', 1320291063);
1024 $this->addToMount(array(
1025 'targetFolder' => array('file' => '', 'newFile' => '')
1026 ));
1027 $fixture = $this->createDriverFixture();
1028 $fixture->renameFile('/targetFolder/file', 'newFile');
1029 }
1030
1031 /**
1032 * We use this data provider for testing move methods because there are some issues with the
1033 *
1034 * @return array
1035 */
1036 public function renamingFolders_dataProvider() {
1037 return array(
1038 'folder in root folder' => array(
1039 array(
1040 'someFolder' => array()
1041 ),
1042 '/someFolder/',
1043 'newFolder',
1044 '/newFolder/'
1045 ),
1046 'file in subfolder' => array(
1047 array(
1048 'subfolder' => array(
1049 'someFolder' => array()
1050 )
1051 ),
1052 '/subfolder/someFolder/',
1053 'newFolder',
1054 '/subfolder/newFolder/'
1055 )
1056 );
1057 }
1058
1059 /**
1060 * @test
1061 * @dataProvider renamingFolders_dataProvider
1062 */
1063 public function renamingFoldersChangesFolderNameOnDisk(array $filesystemStructure, $oldFolderIdentifier, $newFolderName, $expectedNewIdentifier) {
1064 $this->addToMount($filesystemStructure);
1065 $fixture = $this->createDriverFixture();
1066 $mapping = $fixture->renameFolder($oldFolderIdentifier, $newFolderName);
1067 $this->assertFalse($fixture->folderExists($oldFolderIdentifier));
1068 $this->assertTrue($fixture->folderExists($expectedNewIdentifier));
1069 $this->assertEquals($expectedNewIdentifier, $mapping[$oldFolderIdentifier]);
1070 }
1071
1072 /**
1073 * @test
1074 */
1075 public function renameFolderReturnsCorrectMappingInformationForAllFiles() {
1076 $fileContents = 'asdfg';
1077 $this->addToMount(array(
1078 'sourceFolder' => array(
1079 'subFolder' => array('file' => $fileContents),
1080 'file2' => 'asdfg'
1081 )
1082 ));
1083 $fixture = $this->createDriverFixture();
1084 $mappingInformation = $fixture->renameFolder('/sourceFolder/', 'newFolder');
1085 $this->isTrue(is_array($mappingInformation));
1086 $this->assertEquals('/newFolder/', $mappingInformation['/sourceFolder/']);
1087 $this->assertEquals('/newFolder/file2', $mappingInformation['/sourceFolder/file2']);
1088 $this->assertEquals('/newFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1089 $this->assertEquals('/newFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1090 }
1091
1092 /**
1093 * @test
1094 */
1095 public function renameFolderRevertsRenamingIfFilenameMapCannotBeCreated() {
1096 $this->setExpectedException('\\RuntimeException', '', 1334160746);
1097 $this->addToMount(array(
1098 'sourceFolder' => array(
1099 'file' => 'asdfg'
1100 )
1101 ));
1102 $fixture = $this->createDriverFixture(array(), array('createIdentifierMap'));
1103 $fixture->expects($this->atLeastOnce())->method('createIdentifierMap')->will($this->throwException(new \TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException()));
1104 $fixture->renameFolder('/sourceFolder/', 'newFolder');
1105 $this->assertFileExists($this->getUrlInMount('/sourceFolder/file'));
1106 }
1107
1108 /**
1109 * @test
1110 */
1111 public function isFolderEmptyReturnsTrueForEmptyFolder() {
1112 // This also prepares the next few tests, so add more info than required for this test
1113 $this->addToMount(array(
1114 'emptyFolder' => array()
1115 ));
1116 $fixture = $this->createDriverFixture();
1117 $this->assertTrue($fixture->isFolderEmpty('/emptyFolder/'));
1118 return $fixture;
1119 }
1120
1121 /**
1122 * @test
1123 */
1124 public function isFolderEmptyReturnsFalseIfFolderHasFile() {
1125 $this->addToMount(array(
1126 'folderWithFile' => array(
1127 'someFile' => ''
1128 )
1129 ));
1130 $fixture = $this->createDriverFixture();
1131 $this->assertFalse($fixture->isFolderEmpty('/folderWithFile/'));
1132 }
1133
1134 /**
1135 * @test
1136 */
1137 public function isFolderEmptyReturnsFalseIfFolderHasSubfolder() {
1138 $this->addToMount(array(
1139 'folderWithSubfolder' => array(
1140 'someFolder' => array()
1141 )
1142 ));
1143 $fixture = $this->createDriverFixture();
1144 $this->assertFalse($fixture->isFolderEmpty('/folderWithSubfolder/'));
1145 }
1146
1147 /**********************************
1148 * Copy/move folder
1149 **********************************/
1150 /**
1151 * @test
1152 */
1153 public function foldersCanBeMovedWithinStorage() {
1154 $fileContents = uniqid();
1155 $this->addToMount(array(
1156 'sourceFolder' => array(
1157 'file' => $fileContents,
1158 ),
1159 'targetFolder' => array(),
1160 ));
1161 $fixture = $this->createDriverFixture();
1162 /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver $fixture */
1163 $fixture->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'someFolder');
1164 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/someFolder/')));
1165 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/someFolder/file')));
1166 $this->assertFileNotExists($this->getUrlInMount('/sourceFolder'));
1167 }
1168
1169 /**
1170 * @test
1171 */
1172 public function moveFolderWithinStorageReturnsCorrectMappingInformationForAllFiles() {
1173 $fileContents = 'asdfg';
1174 $this->addToMount(array(
1175 'targetFolder' => array(),
1176 'sourceFolder' => array(
1177 'subFolder' => array('file' => $fileContents),
1178 'file' => 'asdfg'
1179 )
1180 ));
1181 $fixture = $this->createDriverFixture();
1182 $mappingInformation = $fixture->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'sourceFolder');
1183 $this->assertEquals('/targetFolder/sourceFolder/file', $mappingInformation['/sourceFolder/file']);
1184 $this->assertEquals('/targetFolder/sourceFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1185 $this->assertEquals('/targetFolder/sourceFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1186 }
1187
1188 /**
1189 * @test
1190 */
1191 public function folderCanBeRenamedWhenMoving() {
1192 $this->addToMount(array(
1193 'sourceFolder' => array(
1194 'file' => uniqid(),
1195 ),
1196 'targetFolder' => array(),
1197 ));
1198 $fixture = $this->createDriverFixture();
1199 $fixture->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolder');
1200 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/newFolder/')));
1201 }
1202
1203 /**
1204 * @test
1205 */
1206 public function copyFolderWithinStorageCopiesSingleFileToNewFolderName() {
1207 $this->addToMount(array(
1208 'sourceFolder' => array(
1209 'file' => uniqid(),
1210 ),
1211 'targetFolder' => array(),
1212 ));
1213 $fixture = $this->createDriverFixture();
1214 $fixture->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1215 $this->assertTrue(is_file($this->getUrlInMount('/targetFolder/newFolderName/file')));
1216 }
1217
1218 /**
1219 * @test
1220 */
1221 public function copyFolderWithinStorageCopiesSingleSubFolderToNewFolderName() {
1222 list($basePath, $fixture) = $this->prepareRealTestEnvironment();
1223 GeneralUtility::mkdir_deep($basePath, '/sourceFolder/subFolder');
1224 GeneralUtility::mkdir_deep($basePath, '/targetFolder');
1225
1226 $fixture->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1227 $this->isTrue(is_dir($basePath . '/targetFolder/newFolderName/subFolder'));
1228 }
1229
1230 /**
1231 * @test
1232 */
1233 public function copyFolderWithinStorageCopiesFileInSingleSubFolderToNewFolderName() {
1234 list($basePath, $fixture) = $this->prepareRealTestEnvironment();
1235 GeneralUtility::mkdir_deep($basePath, '/sourceFolder/subFolder');
1236 GeneralUtility::mkdir_deep($basePath, '/targetFolder');
1237 file_put_contents($basePath . '/sourceFolder/subFolder/file', uniqid());
1238 GeneralUtility::fixPermissions($basePath . '/sourceFolder/subFolder/file');
1239
1240 $fixture->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1241 $this->assertTrue(is_file($basePath . '/targetFolder/newFolderName/subFolder/file'));
1242 }
1243
1244 ///////////////////////
1245 // Tests concerning sanitizeFileName
1246 ///////////////////////
1247
1248 /**
1249 * Set up data for sanitizeFileName tests
1250 */
1251 public function setUpCharacterStrings() {
1252 // Generate string containing all characters for the iso8859-1 charset, charcode greater than 127
1253 $this->iso88591GreaterThan127 = '';
1254 for ($i = 0xA0; $i <= 0xFF; $i++) {
1255 $this->iso88591GreaterThan127 .= chr($i);
1256 }
1257
1258 // Generate string containing all characters for the utf-8 Latin-1 Supplement (U+0080 to U+00FF)
1259 // without U+0080 to U+009F: control characters
1260 // Based on http://www.utf8-chartable.de/unicode-utf8-table.pl
1261 $this->utf8Latin1Supplement = '';
1262 for ($i = 0xA0; $i <= 0xBF; $i++) {
1263 $this->utf8Latin1Supplement .= chr(0xC2) . chr($i);
1264 }
1265 for ($i = 0x80; $i <= 0xBF; $i++) {
1266 $this->utf8Latin1Supplement .= chr(0xC3) . chr($i);
1267 }
1268
1269 // Generate string containing all characters for the utf-8 Latin-1 Extended-A (U+0100 to U+017F)
1270 $this->utf8Latin1ExtendedA = '';
1271 for ($i = 0x80; $i <= 0xBF; $i++) {
1272 $this->utf8Latin1ExtendedA .= chr(0xC4) . chr($i);
1273 }
1274 for ($i = 0x80; $i <= 0xBF; $i++) {
1275 $this->utf8Latin1ExtendedA .= chr(0xC5) . chr($i);
1276 }
1277 }
1278
1279 /**
1280 * Data provider for sanitizeFileNameUTF8FilesystemDataProvider
1281 *
1282 * Every array splits into:
1283 * - String value fileName
1284 * - String value charset (none = '', utf-8, latin1, etc.)
1285 * - Expected result (cleaned fileName)
1286 *
1287 * @return array
1288 */
1289 public function sanitizeFileNameUTF8FilesystemDataProvider() {
1290 $this->setUpCharacterStrings();
1291 return array(
1292 // Characters ordered by ASCII table
1293 'allowed characters utf-8 (ASCII part)' => array(
1294 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1295 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1296 ),
1297 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1298 'replace special characters with _ (not allowed characters) utf-8 (ASCII part)' => array(
1299 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1300 '_____________________________'
1301 ),
1302 'utf-8 (Latin-1 Supplement)' => array(
1303 $this->utf8Latin1Supplement,
1304 '________________________________ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
1305 ),
1306 'trim leading and tailing spaces utf-8' => array(
1307 ' test.txt ',
1308 'test.txt'
1309 ),
1310 'remove tailing dot' => array(
1311 'test.txt.',
1312 'test.txt'
1313 ),
1314 );
1315 }
1316
1317 /**
1318 * @test
1319 * @dataProvider sanitizeFileNameUTF8FilesystemDataProvider
1320 */
1321 public function sanitizeFileNameUTF8Filesystem($fileName, $expectedResult) {
1322 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 1;
1323 $this->assertEquals(
1324 $expectedResult,
1325 $this->createDriverFixture()->sanitizeFileName($fileName)
1326 );
1327 }
1328
1329
1330 /**
1331 * Data provider for sanitizeFileNameNonUTF8Filesystem
1332 *
1333 * Every array splits into:
1334 * - String value fileName
1335 * - String value charset (none = '', utf-8, latin1, etc.)
1336 * - Expected result (cleaned fileName)
1337 *
1338 * @return array
1339 */
1340 public function sanitizeFileNameNonUTF8FilesystemDataProvider() {
1341 $this->setUpCharacterStrings();
1342 return array(
1343 // Characters ordered by ASCII table
1344 'allowed characters iso-8859-1' => array(
1345 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1346 'iso-8859-1',
1347 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1348 ),
1349 // Characters ordered by ASCII table
1350 'allowed characters utf-8' => array(
1351 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1352 'utf-8',
1353 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1354 ),
1355 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1356 'replace special characters with _ (not allowed characters) iso-8859-1' => array(
1357 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1358 'iso-8859-1',
1359 '_____________________________'
1360 ),
1361 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1362 'replace special characters with _ (not allowed characters) utf-8' => array(
1363 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1364 'utf-8',
1365 '_____________________________'
1366 ),
1367 'iso-8859-1 (code > 127)' => array(
1368 // http://de.wikipedia.org/wiki/ISO_8859-1
1369 // chr(0xA0) = NBSP (no-break space) => gets trimmed
1370 $this->iso88591GreaterThan127,
1371 'iso-8859-1',
1372 '_centpound_yen____c_a_____R_____-23_u___1o__1_41_23_4_AAAAAEAAAECEEEEIIIIDNOOOOOExOEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe_oeuuuueythy'
1373 ),
1374 'utf-8 (Latin-1 Supplement)' => array(
1375 // chr(0xC2) . chr(0x0A) = NBSP (no-break space) => gets trimmed
1376 $this->utf8Latin1Supplement,
1377 'utf-8',
1378 '_centpound__yen______c_a_______R_______-23__u_____1o__1_41_23_4_AAAAAEAAAECEEEEIIIIDNOOOOOExOEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe_oeuuuueythy'
1379 ),
1380 'utf-8 (Latin-1 Extended A)' => array(
1381 $this->utf8Latin1ExtendedA,
1382 'utf-8',
1383 'AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIJijJjKk__LlLlLlL_l_LlNnNnNn_n____OOooOoOoOEoeRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzs'
1384 ),
1385 'trim leading and tailing spaces iso-8859-1' => array(
1386 ' test.txt ',
1387 'iso-8859-1',
1388 'test.txt'
1389 ),
1390 'trim leading and tailing spaces utf-8' => array(
1391 ' test.txt ',
1392 'utf-8',
1393 'test.txt'
1394 ),
1395 'remove tailing dot iso-8859-1' => array(
1396 'test.txt.',
1397 'iso-8859-1',
1398 'test.txt'
1399 ),
1400 'remove tailing dot utf-8' => array(
1401 'test.txt.',
1402 'utf-8',
1403 'test.txt'
1404 ),
1405 );
1406 }
1407
1408 /**
1409 * @test
1410 * @dataProvider sanitizeFileNameNonUTF8FilesystemDataProvider
1411 */
1412 public function sanitizeFileNameNonUTF8Filesystem($fileName, $charset, $expectedResult) {
1413 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 0;
1414 $this->assertEquals(
1415 $expectedResult,
1416 $this->createDriverFixture()->sanitizeFileName($fileName, $charset)
1417 );
1418 }
1419
1420 /**
1421 * @test
1422 * @expectedException \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException
1423 */
1424 public function sanitizeFileNameThrowsExceptionOnInvalidFileName() {
1425 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 1;
1426 $this->createDriverFixture()->sanitizeFileName('');
1427 }
1428
1429 }