aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/Files/FilenameValidatorTest.php88
-rw-r--r--tests/lib/Files/PathVerificationTest.php51
-rw-r--r--tests/lib/Files/Storage/CommonTest.php67
3 files changed, 107 insertions, 99 deletions
diff --git a/tests/lib/Files/FilenameValidatorTest.php b/tests/lib/Files/FilenameValidatorTest.php
index 42705a23f02..223e86ccd0a 100644
--- a/tests/lib/Files/FilenameValidatorTest.php
+++ b/tests/lib/Files/FilenameValidatorTest.php
@@ -13,9 +13,11 @@ use OC\Files\FilenameValidator;
use OCP\Files\EmptyFileNameException;
use OCP\Files\FileNameTooLongException;
use OCP\Files\InvalidCharacterInPathException;
+use OCP\Files\InvalidDirectoryException;
use OCP\Files\InvalidPathException;
use OCP\Files\ReservedWordException;
use OCP\IConfig;
+use OCP\IDBConnection;
use OCP\IL10N;
use OCP\L10N\IFactory;
use PHPUnit\Framework\MockObject\MockObject;
@@ -26,6 +28,7 @@ class FilenameValidatorTest extends TestCase {
protected IFactory&MockObject $l10n;
protected IConfig&MockObject $config;
+ protected IDBConnection&MockObject $database;
protected LoggerInterface&MockObject $logger;
protected function setUp(): void {
@@ -41,6 +44,8 @@ class FilenameValidatorTest extends TestCase {
$this->config = $this->createMock(IConfig::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->database = $this->createMock(IDBConnection::class);
+ $this->database->method('supports4ByteText')->willReturn(true);
}
/**
@@ -62,7 +67,7 @@ class FilenameValidatorTest extends TestCase {
'getForbiddenExtensions',
'getForbiddenFilenames',
])
- ->setConstructorArgs([$this->l10n, $this->config, $this->logger])
+ ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger])
->getMock();
$validator->method('getForbiddenBasenames')
@@ -101,7 +106,7 @@ class FilenameValidatorTest extends TestCase {
'getForbiddenFilenames',
'getForbiddenCharacters',
])
- ->setConstructorArgs([$this->l10n, $this->config, $this->logger])
+ ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger])
->getMock();
$validator->method('getForbiddenBasenames')
@@ -122,6 +127,9 @@ class FilenameValidatorTest extends TestCase {
'valid name' => [
'a: b.txt', ['.htaccess'], [], [], [], null
],
+ 'forbidden name in the middle is ok' => [
+ 'a.htaccess.txt', ['.htaccess'], [], [], null
+ ],
'valid name with some more parameters' => [
'a: b.txt', ['.htaccess'], [], ['exe'], ['~'], null
],
@@ -155,10 +163,13 @@ class FilenameValidatorTest extends TestCase {
'', [], [], [], [], EmptyFileNameException::class
],
'reserved unix name "."' => [
- '.', [], [], [], [], InvalidPathException::class
+ '.', [], [], [], [], InvalidDirectoryException::class
],
'reserved unix name ".."' => [
- '..', [], [], [], [], ReservedWordException::class
+ '..', [], [], [], [], InvalidDirectoryException::class
+ ],
+ 'weird but valid tripple dot name' => [
+ '...', [], [], [], null // is valid
],
'too long filename "."' => [
str_repeat('a', 251), [], [], [], [], FileNameTooLongException::class
@@ -172,13 +183,80 @@ class FilenameValidatorTest extends TestCase {
}
/**
+ * @dataProvider data4ByteUnicode
+ */
+ public function testDatabaseDoesNotSupport4ByteText($filename): void {
+ $database = $this->createMock(IDBConnection::class);
+ $database->expects($this->once())
+ ->method('supports4ByteText')
+ ->willReturn(false);
+ $this->expectException(InvalidCharacterInPathException::class);
+ $validator = new FilenameValidator($this->l10n, $database, $this->config, $this->logger);
+ $validator->validateFilename($filename);
+ }
+
+ public function data4ByteUnicode(): array {
+ return [
+ ['plane 1 πͺ…'],
+ ['emoji πŸ˜Άβ€πŸŒ«οΈ'],
+
+ ];
+ }
+
+ /**
+ * @dataProvider dataInvalidAsciiCharacters
+ */
+ public function testInvalidAsciiCharactersAreAlwaysForbidden(string $filename): void {
+ $this->expectException(InvalidPathException::class);
+ $validator = new FilenameValidator($this->l10n, $this->database, $this->config, $this->logger);
+ $validator->validateFilename($filename);
+ }
+
+ public function dataInvalidAsciiCharacters(): array {
+ return [
+ [\chr(0)],
+ [\chr(1)],
+ [\chr(2)],
+ [\chr(3)],
+ [\chr(4)],
+ [\chr(5)],
+ [\chr(6)],
+ [\chr(7)],
+ [\chr(8)],
+ [\chr(9)],
+ [\chr(10)],
+ [\chr(11)],
+ [\chr(12)],
+ [\chr(13)],
+ [\chr(14)],
+ [\chr(15)],
+ [\chr(16)],
+ [\chr(17)],
+ [\chr(18)],
+ [\chr(19)],
+ [\chr(20)],
+ [\chr(21)],
+ [\chr(22)],
+ [\chr(23)],
+ [\chr(24)],
+ [\chr(25)],
+ [\chr(26)],
+ [\chr(27)],
+ [\chr(28)],
+ [\chr(29)],
+ [\chr(30)],
+ [\chr(31)],
+ ];
+ }
+
+ /**
* @dataProvider dataIsForbidden
*/
public function testIsForbidden(string $filename, array $forbiddenNames, array $forbiddenBasenames, bool $expected): void {
/** @var FilenameValidator&MockObject */
$validator = $this->getMockBuilder(FilenameValidator::class)
->onlyMethods(['getForbiddenFilenames', 'getForbiddenBasenames'])
- ->setConstructorArgs([$this->l10n, $this->config, $this->logger])
+ ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger])
->getMock();
$validator->method('getForbiddenBasenames')
diff --git a/tests/lib/Files/PathVerificationTest.php b/tests/lib/Files/PathVerificationTest.php
index 4addd583354..0fd0c330ea5 100644
--- a/tests/lib/Files/PathVerificationTest.php
+++ b/tests/lib/Files/PathVerificationTest.php
@@ -107,57 +107,6 @@ class PathVerificationTest extends \Test\TestCase {
}
/**
- * @dataProvider providesInvalidCharsPosix
- */
- public function testPathVerificationInvalidCharsPosix($fileName) {
- $this->expectException(\OCP\Files\InvalidCharacterInPathException::class);
-
- $storage = new Local(['datadir' => '']);
-
- $fileName = " 123{$fileName}456 ";
- self::invokePrivate($storage, 'verifyPosixPath', [$fileName]);
- }
-
- public function providesInvalidCharsPosix() {
- return [
- [\chr(0)],
- [\chr(1)],
- [\chr(2)],
- [\chr(3)],
- [\chr(4)],
- [\chr(5)],
- [\chr(6)],
- [\chr(7)],
- [\chr(8)],
- [\chr(9)],
- [\chr(10)],
- [\chr(11)],
- [\chr(12)],
- [\chr(13)],
- [\chr(14)],
- [\chr(15)],
- [\chr(16)],
- [\chr(17)],
- [\chr(18)],
- [\chr(19)],
- [\chr(20)],
- [\chr(21)],
- [\chr(22)],
- [\chr(23)],
- [\chr(24)],
- [\chr(25)],
- [\chr(26)],
- [\chr(27)],
- [\chr(28)],
- [\chr(29)],
- [\chr(30)],
- [\chr(31)],
- ['/'],
- ['\\'],
- ];
- }
-
- /**
* @dataProvider providesValidPosixPaths
*/
public function testPathVerificationValidPaths($fileName) {
diff --git a/tests/lib/Files/Storage/CommonTest.php b/tests/lib/Files/Storage/CommonTest.php
index bd22d93fb69..321894cc23b 100644
--- a/tests/lib/Files/Storage/CommonTest.php
+++ b/tests/lib/Files/Storage/CommonTest.php
@@ -9,7 +9,10 @@ namespace Test\Files\Storage;
use OC\Files\Storage\Wrapper\Jail;
use OC\Files\Storage\Wrapper\Wrapper;
+use OCP\Files\IFilenameValidator;
+use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidPathException;
+use OCP\ITempManager;
use PHPUnit\Framework\MockObject\MockObject;
/**
@@ -20,65 +23,43 @@ use PHPUnit\Framework\MockObject\MockObject;
* @package Test\Files\Storage
*/
class CommonTest extends Storage {
- /**
- * @var string tmpDir
- */
- private $tmpDir;
- private array $invalidCharsBackup;
+ private string $tmpDir;
+ private IFilenameValidator&MockObject $filenameValidator;
protected function setUp(): void {
parent::setUp();
- $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder();
+ $this->filenameValidator = $this->createMock(IFilenameValidator::class);
+ $this->overwriteService(IFilenameValidator::class, $this->filenameValidator);
+ $this->tmpDir = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
$this->instance = new \OC\Files\Storage\CommonTest(['datadir' => $this->tmpDir]);
- $this->invalidCharsBackup = \OC::$server->getConfig()->getSystemValue('forbidden_chars', []);
}
protected function tearDown(): void {
\OC_Helper::rmdirr($this->tmpDir);
- \OC::$server->getConfig()->setSystemValue('forbidden_chars', $this->invalidCharsBackup);
+ $this->restoreService(IFilenameValidator::class);
parent::tearDown();
}
- /**
- * @dataProvider dataVerifyPath
- */
- public function testVerifyPath(string $filename, array $additionalChars, bool $throws) {
- /** @var \OC\Files\Storage\CommonTest|MockObject $instance */
- $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class)
- ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink'])
- ->setConstructorArgs([['datadir' => $this->tmpDir]])
- ->getMock();
- $instance->method('copyFromStorage')
- ->willThrowException(new \Exception('copy'));
+ public function testVerifyPath() {
+ $this->filenameValidator
+ ->expects($this->once())
+ ->method('validateFilename')
+ ->with('invalid:char.txt')
+ ->willThrowException(new InvalidCharacterInPathException());
+ $this->expectException(InvalidPathException::class);
- \OC::$server->getConfig()->setSystemValue('forbidden_chars', $additionalChars);
-
- if ($throws) {
- $this->expectException(InvalidPathException::class);
- } else {
- $this->expectNotToPerformAssertions();
- }
- $instance->verifyPath('/', $filename);
+ $this->instance->verifyPath('/', 'invalid:char.txt');
}
- public function dataVerifyPath(): array {
- return [
- // slash is always forbidden
- 'invalid slash' => ['a/b.txt', [], true],
- // backslash is also forbidden
- 'invalid backslash' => ['a\\b.txt', [], true],
- // by default colon is not forbidden
- 'valid name' => ['a: b.txt', [], false],
- // colon can be added to the list of forbidden character
- 'invalid custom character' => ['a: b.txt', [':'], true],
- // make sure to not split the list entries as they migh contain Unicode sequences
- // in this example the "face in clouds" emoji contains the clouds emoji so only having clouds is ok
- 'valid unicode sequence' => ['🌫️.txt', ['πŸ˜Άβ€πŸŒ«οΈ'], false],
- // This is the reverse: clouds are forbidden -> so is also the face in the clouds emoji
- 'valid unicode sequence' => ['πŸ˜Άβ€πŸŒ«οΈ.txt', ['🌫️'], true],
- ];
+ public function testVerifyPathSucceed() {
+ $this->filenameValidator
+ ->expects($this->once())
+ ->method('validateFilename')
+ ->with('valid-char.txt');
+
+ $this->instance->verifyPath('/', 'valid-char.txt');
}
public function testMoveFromStorageWrapped() {