PublicPreviewController.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
  4. *
  5. * @author Julius Härtl <jus@bitgrid.net>
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. * @author Roeland Jago Douma <roeland@famdouma.nl>
  8. * @author Kate Döen <kate.doeen@nextcloud.com>
  9. *
  10. * @license GNU AGPL version 3 or any later version
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License as
  14. * published by the Free Software Foundation, either version 3 of the
  15. * License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. *
  25. */
  26. namespace OCA\Files_Sharing\Controller;
  27. use OCP\AppFramework\Http;
  28. use OCP\AppFramework\Http\DataResponse;
  29. use OCP\AppFramework\Http\FileDisplayResponse;
  30. use OCP\AppFramework\PublicShareController;
  31. use OCP\Constants;
  32. use OCP\Files\Folder;
  33. use OCP\Files\NotFoundException;
  34. use OCP\IPreview;
  35. use OCP\IRequest;
  36. use OCP\ISession;
  37. use OCP\Share\Exceptions\ShareNotFound;
  38. use OCP\Share\IManager as ShareManager;
  39. use OCP\Share\IShare;
  40. class PublicPreviewController extends PublicShareController {
  41. /** @var ShareManager */
  42. private $shareManager;
  43. /** @var IPreview */
  44. private $previewManager;
  45. /** @var IShare */
  46. private $share;
  47. public function __construct(string $appName,
  48. IRequest $request,
  49. ShareManager $shareManger,
  50. ISession $session,
  51. IPreview $previewManager) {
  52. parent::__construct($appName, $request, $session);
  53. $this->shareManager = $shareManger;
  54. $this->previewManager = $previewManager;
  55. }
  56. protected function getPasswordHash(): ?string {
  57. return $this->share->getPassword();
  58. }
  59. public function isValidToken(): bool {
  60. try {
  61. $this->share = $this->shareManager->getShareByToken($this->getToken());
  62. return true;
  63. } catch (ShareNotFound $e) {
  64. return false;
  65. }
  66. }
  67. protected function isPasswordProtected(): bool {
  68. return $this->share->getPassword() !== null;
  69. }
  70. /**
  71. * @PublicPage
  72. * @NoCSRFRequired
  73. *
  74. * Get a preview for a shared file
  75. *
  76. * @param string $token Token of the share
  77. * @param string $file File in the share
  78. * @param int $x Width of the preview
  79. * @param int $y Height of the preview
  80. * @param bool $a Whether to not crop the preview
  81. * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array<empty>, array{}>
  82. *
  83. * 200: Preview returned
  84. * 400: Getting preview is not possible
  85. * 403: Getting preview is not allowed
  86. * 404: Share or preview not found
  87. */
  88. public function getPreview(
  89. string $token,
  90. string $file = '',
  91. int $x = 32,
  92. int $y = 32,
  93. $a = false
  94. ) {
  95. if ($token === '' || $x === 0 || $y === 0) {
  96. return new DataResponse([], Http::STATUS_BAD_REQUEST);
  97. }
  98. try {
  99. $share = $this->shareManager->getShareByToken($token);
  100. } catch (ShareNotFound $e) {
  101. return new DataResponse([], Http::STATUS_NOT_FOUND);
  102. }
  103. if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
  104. return new DataResponse([], Http::STATUS_FORBIDDEN);
  105. }
  106. $attributes = $share->getAttributes();
  107. if ($attributes !== null && $attributes->getAttribute('permissions', 'download') === false) {
  108. return new DataResponse([], Http::STATUS_FORBIDDEN);
  109. }
  110. try {
  111. $node = $share->getNode();
  112. if ($node instanceof Folder) {
  113. $file = $node->get($file);
  114. } else {
  115. $file = $node;
  116. }
  117. $f = $this->previewManager->getPreview($file, $x, $y, !$a);
  118. $response = new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
  119. $response->cacheFor(3600 * 24);
  120. return $response;
  121. } catch (NotFoundException $e) {
  122. return new DataResponse([], Http::STATUS_NOT_FOUND);
  123. } catch (\InvalidArgumentException $e) {
  124. return new DataResponse([], Http::STATUS_BAD_REQUEST);
  125. }
  126. }
  127. /**
  128. * @PublicPage
  129. * @NoCSRFRequired
  130. * @NoSameSiteCookieRequired
  131. *
  132. * Get a direct link preview for a shared file
  133. *
  134. * @param string $token Token of the share
  135. * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array<empty>, array{}>
  136. *
  137. * 200: Preview returned
  138. * 400: Getting preview is not possible
  139. * 403: Getting preview is not allowed
  140. * 404: Share or preview not found
  141. */
  142. public function directLink(string $token) {
  143. // No token no image
  144. if ($token === '') {
  145. return new DataResponse([], Http::STATUS_BAD_REQUEST);
  146. }
  147. // No share no image
  148. try {
  149. $share = $this->shareManager->getShareByToken($token);
  150. } catch (ShareNotFound $e) {
  151. return new DataResponse([], Http::STATUS_NOT_FOUND);
  152. }
  153. // No permissions no image
  154. if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
  155. return new DataResponse([], Http::STATUS_FORBIDDEN);
  156. }
  157. // Password protected shares have no direct link!
  158. if ($share->getPassword() !== null) {
  159. return new DataResponse([], Http::STATUS_FORBIDDEN);
  160. }
  161. $attributes = $share->getAttributes();
  162. if ($attributes !== null && $attributes->getAttribute('permissions', 'download') === false) {
  163. return new DataResponse([], Http::STATUS_FORBIDDEN);
  164. }
  165. try {
  166. $node = $share->getNode();
  167. if ($node instanceof Folder) {
  168. // Direct link only works for single files
  169. return new DataResponse([], Http::STATUS_BAD_REQUEST);
  170. }
  171. $f = $this->previewManager->getPreview($node, -1, -1, false);
  172. $response = new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
  173. $response->cacheFor(3600 * 24);
  174. return $response;
  175. } catch (NotFoundException $e) {
  176. return new DataResponse([], Http::STATUS_NOT_FOUND);
  177. } catch (\InvalidArgumentException $e) {
  178. return new DataResponse([], Http::STATUS_BAD_REQUEST);
  179. }
  180. }
  181. }