EncodingTest.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace Test\Files\Storage\Wrapper;
  8. class EncodingTest extends \Test\Files\Storage\Storage {
  9. public const NFD_NAME = 'ümlaut';
  10. public const NFC_NAME = 'ümlaut';
  11. /**
  12. * @var \OC\Files\Storage\Temporary
  13. */
  14. private $sourceStorage;
  15. protected function setUp(): void {
  16. parent::setUp();
  17. $this->sourceStorage = new \OC\Files\Storage\Temporary([]);
  18. $this->instance = new \OC\Files\Storage\Wrapper\Encoding([
  19. 'storage' => $this->sourceStorage
  20. ]);
  21. }
  22. protected function tearDown(): void {
  23. $this->sourceStorage->cleanUp();
  24. parent::tearDown();
  25. }
  26. public function directoryProvider() {
  27. $a = parent::directoryProvider();
  28. $a[] = [self::NFC_NAME];
  29. return $a;
  30. }
  31. public function fileNameProvider() {
  32. $a = parent::fileNameProvider();
  33. $a[] = [self::NFD_NAME . '.txt'];
  34. return $a;
  35. }
  36. public function copyAndMoveProvider() {
  37. $a = parent::copyAndMoveProvider();
  38. $a[] = [self::NFD_NAME . '.txt', self::NFC_NAME . '-renamed.txt'];
  39. return $a;
  40. }
  41. public function accessNameProvider() {
  42. return [
  43. [self::NFD_NAME],
  44. [self::NFC_NAME],
  45. ];
  46. }
  47. /**
  48. * @dataProvider accessNameProvider
  49. */
  50. public function testFputEncoding($accessName): void {
  51. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar');
  52. $this->assertEquals('bar', $this->instance->file_get_contents($accessName));
  53. }
  54. /**
  55. * @dataProvider accessNameProvider
  56. */
  57. public function testFopenReadEncoding($accessName): void {
  58. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar');
  59. $fh = $this->instance->fopen($accessName, 'r');
  60. $data = fgets($fh);
  61. fclose($fh);
  62. $this->assertEquals('bar', $data);
  63. }
  64. /**
  65. * @dataProvider accessNameProvider
  66. */
  67. public function testFopenOverwriteEncoding($accessName): void {
  68. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar');
  69. $fh = $this->instance->fopen($accessName, 'w');
  70. $data = fputs($fh, 'test');
  71. fclose($fh);
  72. $data = $this->sourceStorage->file_get_contents(self::NFD_NAME);
  73. $this->assertEquals('test', $data);
  74. $this->assertFalse($this->sourceStorage->file_exists(self::NFC_NAME));
  75. }
  76. /**
  77. * @dataProvider accessNameProvider
  78. */
  79. public function testFileExistsEncoding($accessName): void {
  80. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar');
  81. $this->assertTrue($this->instance->file_exists($accessName));
  82. }
  83. /**
  84. * @dataProvider accessNameProvider
  85. */
  86. public function testUnlinkEncoding($accessName): void {
  87. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar');
  88. $this->assertTrue($this->instance->unlink($accessName));
  89. $this->assertFalse($this->sourceStorage->file_exists(self::NFC_NAME));
  90. $this->assertFalse($this->sourceStorage->file_exists(self::NFD_NAME));
  91. }
  92. public function testNfcHigherPriority(): void {
  93. $this->sourceStorage->file_put_contents(self::NFC_NAME, 'nfc');
  94. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'nfd');
  95. $this->assertEquals('nfc', $this->instance->file_get_contents(self::NFC_NAME));
  96. }
  97. public function encodedDirectoriesProvider() {
  98. return [
  99. [self::NFD_NAME, self::NFC_NAME],
  100. [self::NFD_NAME . '/' . self::NFD_NAME, self::NFC_NAME . '/' . self::NFC_NAME],
  101. [self::NFD_NAME . '/' . self::NFC_NAME . '/' . self::NFD_NAME, self::NFC_NAME . '/' . self::NFC_NAME . '/' . self::NFC_NAME],
  102. ];
  103. }
  104. /**
  105. * @dataProvider encodedDirectoriesProvider
  106. */
  107. public function testOperationInsideDirectory($sourceDir, $accessDir): void {
  108. $this->sourceStorage->mkdir($sourceDir);
  109. $this->instance->file_put_contents($accessDir . '/test.txt', 'bar');
  110. $this->assertTrue($this->instance->file_exists($accessDir . '/test.txt'));
  111. $this->assertEquals('bar', $this->instance->file_get_contents($accessDir . '/test.txt'));
  112. $this->sourceStorage->file_put_contents($sourceDir . '/' . self::NFD_NAME, 'foo');
  113. $this->assertTrue($this->instance->file_exists($accessDir . '/' . self::NFC_NAME));
  114. $this->assertEquals('foo', $this->instance->file_get_contents($accessDir . '/' . self::NFC_NAME));
  115. // try again to make it use cached path
  116. $this->assertEquals('bar', $this->instance->file_get_contents($accessDir . '/test.txt'));
  117. $this->assertTrue($this->instance->file_exists($accessDir . '/test.txt'));
  118. $this->assertEquals('foo', $this->instance->file_get_contents($accessDir . '/' . self::NFC_NAME));
  119. $this->assertTrue($this->instance->file_exists($accessDir . '/' . self::NFC_NAME));
  120. }
  121. public function testCacheExtraSlash(): void {
  122. $this->sourceStorage->file_put_contents(self::NFD_NAME, 'foo');
  123. $this->assertEquals(3, $this->instance->file_put_contents(self::NFC_NAME, 'bar'));
  124. $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME));
  125. clearstatcache();
  126. $this->assertEquals(5, $this->instance->file_put_contents('/' . self::NFC_NAME, 'baric'));
  127. $this->assertEquals('baric', $this->instance->file_get_contents(self::NFC_NAME));
  128. clearstatcache();
  129. $this->assertEquals(8, $this->instance->file_put_contents('/' . self::NFC_NAME, 'barbaric'));
  130. $this->assertEquals('barbaric', $this->instance->file_get_contents('//' . self::NFC_NAME));
  131. }
  132. public function sourceAndTargetDirectoryProvider() {
  133. return [
  134. [self::NFC_NAME . '1', self::NFC_NAME . '2'],
  135. [self::NFD_NAME . '1', self::NFC_NAME . '2'],
  136. [self::NFC_NAME . '1', self::NFD_NAME . '2'],
  137. [self::NFD_NAME . '1', self::NFD_NAME . '2'],
  138. ];
  139. }
  140. /**
  141. * @dataProvider sourceAndTargetDirectoryProvider
  142. */
  143. public function testCopyAndMoveEncodedFolder($sourceDir, $targetDir): void {
  144. $this->sourceStorage->mkdir($sourceDir);
  145. $this->sourceStorage->mkdir($targetDir);
  146. $this->sourceStorage->file_put_contents($sourceDir . '/test.txt', 'bar');
  147. $this->assertTrue($this->instance->copy(self::NFC_NAME . '1/test.txt', self::NFC_NAME . '2/test.txt'));
  148. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '1/test.txt'));
  149. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '2/test.txt'));
  150. $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test.txt'));
  151. $this->assertTrue($this->instance->rename(self::NFC_NAME . '1/test.txt', self::NFC_NAME . '2/test2.txt'));
  152. $this->assertFalse($this->instance->file_exists(self::NFC_NAME . '1/test.txt'));
  153. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '2/test2.txt'));
  154. $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test2.txt'));
  155. }
  156. /**
  157. * @dataProvider sourceAndTargetDirectoryProvider
  158. */
  159. public function testCopyAndMoveFromStorageEncodedFolder($sourceDir, $targetDir): void {
  160. $this->sourceStorage->mkdir($sourceDir);
  161. $this->sourceStorage->mkdir($targetDir);
  162. $this->sourceStorage->file_put_contents($sourceDir . '/test.txt', 'bar');
  163. $this->assertTrue($this->instance->copyFromStorage($this->instance, self::NFC_NAME . '1/test.txt', self::NFC_NAME . '2/test.txt'));
  164. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '1/test.txt'));
  165. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '2/test.txt'));
  166. $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test.txt'));
  167. $this->assertTrue($this->instance->moveFromStorage($this->instance, self::NFC_NAME . '1/test.txt', self::NFC_NAME . '2/test2.txt'));
  168. $this->assertFalse($this->instance->file_exists(self::NFC_NAME . '1/test.txt'));
  169. $this->assertTrue($this->instance->file_exists(self::NFC_NAME . '2/test2.txt'));
  170. $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test2.txt'));
  171. }
  172. public function testNormalizedDirectoryEntriesOpenDir(): void {
  173. $this->sourceStorage->mkdir('/test');
  174. $this->sourceStorage->mkdir('/test/' . self::NFD_NAME);
  175. $this->assertTrue($this->instance->file_exists('/test/' . self::NFC_NAME));
  176. $this->assertTrue($this->instance->file_exists('/test/' . self::NFD_NAME));
  177. $dh = $this->instance->opendir('/test');
  178. $content = [];
  179. while (($file = readdir($dh)) !== false) {
  180. if ($file != '.' and $file != '..') {
  181. $content[] = $file;
  182. }
  183. }
  184. $this->assertCount(1, $content);
  185. $this->assertEquals(self::NFC_NAME, $content[0]);
  186. }
  187. public function testNormalizedDirectoryEntriesGetDirectoryContent(): void {
  188. $this->sourceStorage->mkdir('/test');
  189. $this->sourceStorage->mkdir('/test/' . self::NFD_NAME);
  190. $this->assertTrue($this->instance->file_exists('/test/' . self::NFC_NAME));
  191. $this->assertTrue($this->instance->file_exists('/test/' . self::NFD_NAME));
  192. $content = iterator_to_array($this->instance->getDirectoryContent('/test'));
  193. $this->assertCount(1, $content);
  194. $this->assertEquals(self::NFC_NAME, $content[0]['name']);
  195. }
  196. public function testNormalizedGetMetaData(): void {
  197. $this->sourceStorage->mkdir('/test');
  198. $this->sourceStorage->mkdir('/test/' . self::NFD_NAME);
  199. $entry = $this->instance->getMetaData('/test/' . self::NFC_NAME);
  200. $this->assertEquals(self::NFC_NAME, $entry['name']);
  201. $entry = $this->instance->getMetaData('/test/' . self::NFD_NAME);
  202. $this->assertEquals(self::NFC_NAME, $entry['name']);
  203. }
  204. }