PathVerificationTest.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php
  2. /**
  3. * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file. */
  7. namespace Test\Files;
  8. use OC\Files\Storage\Local;
  9. use OC\Files\View;
  10. use OCP\Files\InvalidPathException;
  11. /**
  12. * Class PathVerificationTest
  13. *
  14. * @group DB
  15. *
  16. * @package Test\Files
  17. */
  18. class PathVerificationTest extends \Test\TestCase {
  19. /**
  20. * @var \OC\Files\View
  21. */
  22. private $view;
  23. protected function setUp(): void {
  24. parent::setUp();
  25. $this->view = new View();
  26. self::resetOCPUtil();
  27. }
  28. protected function tearDown(): void {
  29. parent::tearDown();
  30. self::resetOCPUtil();
  31. }
  32. protected static function resetOCPUtil(): void {
  33. // Reset util cache
  34. self::invokePrivate(\OCP\Util::class, 'invalidChars', [[]]);
  35. self::invokePrivate(\OCP\Util::class, 'invalidFilenames', [[]]);
  36. }
  37. public function testPathVerificationFileNameTooLong() {
  38. $this->expectException(\OCP\Files\InvalidPathException::class);
  39. $this->expectExceptionMessage('File name is too long');
  40. $fileName = str_repeat('a', 500);
  41. $this->view->verifyPath('', $fileName);
  42. }
  43. /**
  44. * @dataProvider providesEmptyFiles
  45. */
  46. public function testPathVerificationEmptyFileName($fileName) {
  47. $this->expectException(\OCP\Files\InvalidPathException::class);
  48. $this->expectExceptionMessage('Empty filename is not allowed');
  49. $this->view->verifyPath('', $fileName);
  50. }
  51. public function providesEmptyFiles() {
  52. return [
  53. [''],
  54. [' '],
  55. ];
  56. }
  57. /**
  58. * @dataProvider providesDotFiles
  59. */
  60. public function testPathVerificationDotFiles($fileName) {
  61. $this->expectException(\OCP\Files\InvalidPathException::class);
  62. $this->expectExceptionMessage('Dot files are not allowed');
  63. $this->view->verifyPath('', $fileName);
  64. }
  65. public function providesDotFiles() {
  66. return [
  67. ['.'],
  68. ['..'],
  69. [' .'],
  70. [' ..'],
  71. ['. '],
  72. ['.. '],
  73. [' . '],
  74. [' .. '],
  75. ];
  76. }
  77. /**
  78. * @dataProvider providesAstralPlane
  79. */
  80. public function testPathVerificationAstralPlane($fileName) {
  81. $connection = \OC::$server->getDatabaseConnection();
  82. if (!$connection->supports4ByteText()) {
  83. $this->expectException(InvalidPathException::class);
  84. $this->expectExceptionMessage('File name contains at least one invalid character');
  85. } else {
  86. $this->addToAssertionCount(1);
  87. }
  88. $this->view->verifyPath('', $fileName);
  89. }
  90. public function providesAstralPlane() {
  91. return [
  92. // this is the monkey emoji - http://en.wikipedia.org/w/index.php?title=%F0%9F%90%B5&redirect=no
  93. ['🐵'],
  94. ['🐵.txt'],
  95. ['txt.💩'],
  96. ['💩🐵.txt'],
  97. ['💩🐵'],
  98. ];
  99. }
  100. /**
  101. * @dataProvider providesInvalidCharsPosix
  102. */
  103. public function testPathVerificationInvalidCharsPosix($fileName) {
  104. $this->expectException(\OCP\Files\InvalidCharacterInPathException::class);
  105. $storage = new Local(['datadir' => '']);
  106. $fileName = " 123{$fileName}456 ";
  107. $storage->verifyPath('', $fileName);
  108. }
  109. public function providesInvalidCharsPosix() {
  110. return [
  111. // posix forbidden
  112. [\chr(0)],
  113. ['/'],
  114. ['\\'],
  115. // We restrict also ascii 1-31
  116. [\chr(1)],
  117. [\chr(2)],
  118. [\chr(3)],
  119. [\chr(4)],
  120. [\chr(5)],
  121. [\chr(6)],
  122. [\chr(7)],
  123. [\chr(8)],
  124. [\chr(9)],
  125. [\chr(10)],
  126. [\chr(11)],
  127. [\chr(12)],
  128. [\chr(13)],
  129. [\chr(14)],
  130. [\chr(15)],
  131. [\chr(16)],
  132. [\chr(17)],
  133. [\chr(18)],
  134. [\chr(19)],
  135. [\chr(20)],
  136. [\chr(21)],
  137. [\chr(22)],
  138. [\chr(23)],
  139. [\chr(24)],
  140. [\chr(25)],
  141. [\chr(26)],
  142. [\chr(27)],
  143. [\chr(28)],
  144. [\chr(29)],
  145. [\chr(30)],
  146. [\chr(31)],
  147. ];
  148. }
  149. /**
  150. * @dataProvider providesValidPosixPaths
  151. */
  152. public function testPathVerificationValidPaths($fileName) {
  153. $storage = new Local(['datadir' => '']);
  154. self::invokePrivate($storage, 'verifyPosixPath', [$fileName]);
  155. // nothing thrown
  156. $this->addToAssertionCount(1);
  157. }
  158. public function providesValidPosixPaths() {
  159. return [
  160. ['simple'],
  161. ['simple.txt'],
  162. ['\''],
  163. ['`'],
  164. ['%'],
  165. ['()'],
  166. ['[]'],
  167. ['!'],
  168. ['$'],
  169. ['_'],
  170. ];
  171. }
  172. }