CommonTest.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. /**
  3. * ownCloud
  4. *
  5. * @author Robin Appelman
  6. * @copyright 2012 Robin Appelman icewind@owncloud.com
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  10. * License as published by the Free Software Foundation; either
  11. * version 3 of the License, or any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public
  19. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. namespace Test\Files\Storage;
  23. use OC\Files\Storage\Wrapper\Jail;
  24. use OC\Files\Storage\Wrapper\Wrapper;
  25. use OCP\Files\InvalidPathException;
  26. use PHPUnit\Framework\MockObject\MockObject;
  27. /**
  28. * Class CommonTest
  29. *
  30. * @group DB
  31. *
  32. * @package Test\Files\Storage
  33. */
  34. class CommonTest extends Storage {
  35. /**
  36. * @var string tmpDir
  37. */
  38. private $tmpDir;
  39. private array $invalidCharsBackup;
  40. protected function setUp(): void {
  41. parent::setUp();
  42. $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder();
  43. $this->instance = new \OC\Files\Storage\CommonTest(['datadir' => $this->tmpDir]);
  44. $this->invalidCharsBackup = \OC::$server->getConfig()->getSystemValue('forbidden_chars', []);
  45. }
  46. protected function tearDown(): void {
  47. \OC_Helper::rmdirr($this->tmpDir);
  48. \OC::$server->getConfig()->setSystemValue('forbidden_chars', $this->invalidCharsBackup);
  49. parent::tearDown();
  50. }
  51. /**
  52. * @dataProvider dataVerifyPath
  53. */
  54. public function testVerifyPath(string $filename, array $additionalChars, bool $throws) {
  55. /** @var \OC\Files\Storage\CommonTest|MockObject $instance */
  56. $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class)
  57. ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink'])
  58. ->setConstructorArgs([['datadir' => $this->tmpDir]])
  59. ->getMock();
  60. $instance->method('copyFromStorage')
  61. ->willThrowException(new \Exception('copy'));
  62. \OC::$server->getConfig()->setSystemValue('forbidden_chars', $additionalChars);
  63. if ($throws) {
  64. $this->expectException(InvalidPathException::class);
  65. } else {
  66. $this->expectNotToPerformAssertions();
  67. }
  68. $instance->verifyPath('/', $filename);
  69. }
  70. public function dataVerifyPath(): array {
  71. return [
  72. // slash is always forbidden
  73. 'invalid slash' => ['a/b.txt', [], true],
  74. // backslash is also forbidden
  75. 'invalid backslash' => ['a\\b.txt', [], true],
  76. // by default colon is not forbidden
  77. 'valid name' => ['a: b.txt', [], false],
  78. // colon can be added to the list of forbidden character
  79. 'invalid custom character' => ['a: b.txt', [':'], true],
  80. // make sure to not split the list entries as they migh contain Unicode sequences
  81. // in this example the "face in clouds" emoji contains the clouds emoji so only having clouds is ok
  82. 'valid unicode sequence' => ['🌫️.txt', ['😶‍🌫️'], false],
  83. // This is the reverse: clouds are forbidden -> so is also the face in the clouds emoji
  84. 'valid unicode sequence' => ['😶‍🌫️.txt', ['🌫️'], true],
  85. ];
  86. }
  87. public function testMoveFromStorageWrapped() {
  88. /** @var \OC\Files\Storage\CommonTest|MockObject $instance */
  89. $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class)
  90. ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink'])
  91. ->setConstructorArgs([['datadir' => $this->tmpDir]])
  92. ->getMock();
  93. $instance->method('copyFromStorage')
  94. ->willThrowException(new \Exception('copy'));
  95. $source = new Wrapper([
  96. 'storage' => $instance,
  97. ]);
  98. $instance->file_put_contents('foo.txt', 'bar');
  99. $instance->moveFromStorage($source, 'foo.txt', 'bar.txt');
  100. $this->assertTrue($instance->file_exists('bar.txt'));
  101. }
  102. public function testMoveFromStorageJailed() {
  103. /** @var \OC\Files\Storage\CommonTest|MockObject $instance */
  104. $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class)
  105. ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink'])
  106. ->setConstructorArgs([['datadir' => $this->tmpDir]])
  107. ->getMock();
  108. $instance->method('copyFromStorage')
  109. ->willThrowException(new \Exception('copy'));
  110. $source = new Jail([
  111. 'storage' => $instance,
  112. 'root' => 'foo'
  113. ]);
  114. $source = new Wrapper([
  115. 'storage' => $source
  116. ]);
  117. $instance->mkdir('foo');
  118. $instance->file_put_contents('foo/foo.txt', 'bar');
  119. $instance->moveFromStorage($source, 'foo.txt', 'bar.txt');
  120. $this->assertTrue($instance->file_exists('bar.txt'));
  121. }
  122. public function testMoveFromStorageNestedJail() {
  123. /** @var \OC\Files\Storage\CommonTest|MockObject $instance */
  124. $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class)
  125. ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink'])
  126. ->setConstructorArgs([['datadir' => $this->tmpDir]])
  127. ->getMock();
  128. $instance->method('copyFromStorage')
  129. ->willThrowException(new \Exception('copy'));
  130. $source = new Jail([
  131. 'storage' => $instance,
  132. 'root' => 'foo'
  133. ]);
  134. $source = new Wrapper([
  135. 'storage' => $source
  136. ]);
  137. $source = new Jail([
  138. 'storage' => $source,
  139. 'root' => 'bar'
  140. ]);
  141. $source = new Wrapper([
  142. 'storage' => $source
  143. ]);
  144. $instance->mkdir('foo');
  145. $instance->mkdir('foo/bar');
  146. $instance->file_put_contents('foo/bar/foo.txt', 'bar');
  147. $instance->moveFromStorage($source, 'foo.txt', 'bar.txt');
  148. $this->assertTrue($instance->file_exists('bar.txt'));
  149. }
  150. }