ViewOnly.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2019 ownCloud GmbH
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Files_Sharing;
  8. use OCP\Files\File;
  9. use OCP\Files\Folder;
  10. use OCP\Files\Node;
  11. use OCP\Files\NotFoundException;
  12. /**
  13. * Handles restricting for download of files
  14. */
  15. class ViewOnly {
  16. /** @var Folder */
  17. private $userFolder;
  18. public function __construct(Folder $userFolder) {
  19. $this->userFolder = $userFolder;
  20. }
  21. /**
  22. * @param string[] $pathsToCheck
  23. * @return bool
  24. */
  25. public function check(array $pathsToCheck): bool {
  26. // If any of elements cannot be downloaded, prevent whole download
  27. foreach ($pathsToCheck as $file) {
  28. try {
  29. $info = $this->userFolder->get($file);
  30. if ($info instanceof File) {
  31. // access to filecache is expensive in the loop
  32. if (!$this->checkFileInfo($info)) {
  33. return false;
  34. }
  35. } elseif ($info instanceof Folder) {
  36. // get directory content is rather cheap query
  37. if (!$this->dirRecursiveCheck($info)) {
  38. return false;
  39. }
  40. }
  41. } catch (NotFoundException $e) {
  42. continue;
  43. }
  44. }
  45. return true;
  46. }
  47. /**
  48. * @param Folder $dirInfo
  49. * @return bool
  50. * @throws NotFoundException
  51. */
  52. private function dirRecursiveCheck(Folder $dirInfo): bool {
  53. if (!$this->checkFileInfo($dirInfo)) {
  54. return false;
  55. }
  56. // If any of elements cannot be downloaded, prevent whole download
  57. $files = $dirInfo->getDirectoryListing();
  58. foreach ($files as $file) {
  59. if ($file instanceof File) {
  60. if (!$this->checkFileInfo($file)) {
  61. return false;
  62. }
  63. } elseif ($file instanceof Folder) {
  64. return $this->dirRecursiveCheck($file);
  65. }
  66. }
  67. return true;
  68. }
  69. /**
  70. * @param Node $fileInfo
  71. * @return bool
  72. * @throws NotFoundException
  73. */
  74. private function checkFileInfo(Node $fileInfo): bool {
  75. // Restrict view-only to nodes which are shared
  76. $storage = $fileInfo->getStorage();
  77. if (!$storage->instanceOfStorage(SharedStorage::class)) {
  78. return true;
  79. }
  80. // Extract extra permissions
  81. /** @var \OCA\Files_Sharing\SharedStorage $storage */
  82. $share = $storage->getShare();
  83. $canDownload = true;
  84. // Check if read-only and on whether permission can download is both set and disabled.
  85. $attributes = $share->getAttributes();
  86. if ($attributes !== null) {
  87. $canDownload = $attributes->getAttribute('permissions', 'download');
  88. }
  89. if ($canDownload !== null && !$canDownload) {
  90. return false;
  91. }
  92. return true;
  93. }
  94. }