Update.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Bjoern Schiessle <bjoern@schiessle.org>
  6. * @author Björn Schießle <bjoern@schiessle.org>
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Julius Härtl <jus@bitgrid.net>
  9. * @author Roeland Jago Douma <roeland@famdouma.nl>
  10. * @author Thomas Müller <thomas.mueller@tmit.eu>
  11. *
  12. * @license AGPL-3.0
  13. *
  14. * This code is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License, version 3,
  16. * as published by the Free Software Foundation.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License, version 3,
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>
  25. *
  26. */
  27. namespace OC\Encryption;
  28. use InvalidArgumentException;
  29. use OC\Files\Filesystem;
  30. use OC\Files\Mount;
  31. use OC\Files\View;
  32. use OCP\Encryption\Exceptions\GenericEncryptionException;
  33. use Psr\Log\LoggerInterface;
  34. /**
  35. * update encrypted files, e.g. because a file was shared
  36. */
  37. class Update {
  38. /** @var View */
  39. protected $view;
  40. /** @var Util */
  41. protected $util;
  42. /** @var \OC\Files\Mount\Manager */
  43. protected $mountManager;
  44. /** @var Manager */
  45. protected $encryptionManager;
  46. /** @var string */
  47. protected $uid;
  48. /** @var File */
  49. protected $file;
  50. /** @var LoggerInterface */
  51. protected $logger;
  52. /**
  53. * @param string $uid
  54. */
  55. public function __construct(
  56. View $view,
  57. Util $util,
  58. Mount\Manager $mountManager,
  59. Manager $encryptionManager,
  60. File $file,
  61. LoggerInterface $logger,
  62. $uid
  63. ) {
  64. $this->view = $view;
  65. $this->util = $util;
  66. $this->mountManager = $mountManager;
  67. $this->encryptionManager = $encryptionManager;
  68. $this->file = $file;
  69. $this->logger = $logger;
  70. $this->uid = $uid;
  71. }
  72. /**
  73. * hook after file was shared
  74. *
  75. * @param array $params
  76. */
  77. public function postShared($params) {
  78. if ($this->encryptionManager->isEnabled()) {
  79. if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
  80. $path = Filesystem::getPath($params['fileSource']);
  81. [$owner, $ownerPath] = $this->getOwnerPath($path);
  82. $absPath = '/' . $owner . '/files/' . $ownerPath;
  83. $this->update($absPath);
  84. }
  85. }
  86. }
  87. /**
  88. * hook after file was unshared
  89. *
  90. * @param array $params
  91. */
  92. public function postUnshared($params) {
  93. if ($this->encryptionManager->isEnabled()) {
  94. if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
  95. $path = Filesystem::getPath($params['fileSource']);
  96. [$owner, $ownerPath] = $this->getOwnerPath($path);
  97. $absPath = '/' . $owner . '/files/' . $ownerPath;
  98. $this->update($absPath);
  99. }
  100. }
  101. }
  102. /**
  103. * inform encryption module that a file was restored from the trash bin,
  104. * e.g. to update the encryption keys
  105. *
  106. * @param array $params
  107. */
  108. public function postRestore($params) {
  109. if ($this->encryptionManager->isEnabled()) {
  110. $path = Filesystem::normalizePath('/' . $this->uid . '/files/' . $params['filePath']);
  111. $this->update($path);
  112. }
  113. }
  114. /**
  115. * inform encryption module that a file was renamed,
  116. * e.g. to update the encryption keys
  117. *
  118. * @param array $params
  119. */
  120. public function postRename($params) {
  121. $source = $params['oldpath'];
  122. $target = $params['newpath'];
  123. if (
  124. $this->encryptionManager->isEnabled() &&
  125. dirname($source) !== dirname($target)
  126. ) {
  127. [$owner, $ownerPath] = $this->getOwnerPath($target);
  128. $absPath = '/' . $owner . '/files/' . $ownerPath;
  129. $this->update($absPath);
  130. }
  131. }
  132. /**
  133. * get owner and path relative to data/<owner>/files
  134. *
  135. * @param string $path path to file for current user
  136. * @return array ['owner' => $owner, 'path' => $path]
  137. * @throw \InvalidArgumentException
  138. */
  139. protected function getOwnerPath($path) {
  140. $info = Filesystem::getFileInfo($path);
  141. $owner = Filesystem::getOwner($path);
  142. $view = new View('/' . $owner . '/files');
  143. $path = $view->getPath($info->getId());
  144. if ($path === null) {
  145. throw new InvalidArgumentException('No file found for ' . $info->getId());
  146. }
  147. return [$owner, $path];
  148. }
  149. /**
  150. * notify encryption module about added/removed users from a file/folder
  151. *
  152. * @param string $path relative to data/
  153. * @throws Exceptions\ModuleDoesNotExistsException
  154. */
  155. public function update($path) {
  156. $encryptionModule = $this->encryptionManager->getEncryptionModule();
  157. // if the encryption module doesn't encrypt the files on a per-user basis
  158. // we have nothing to do here.
  159. if ($encryptionModule->needDetailedAccessList() === false) {
  160. return;
  161. }
  162. // if a folder was shared, get a list of all (sub-)folders
  163. if ($this->view->is_dir($path)) {
  164. $allFiles = $this->util->getAllFiles($path);
  165. } else {
  166. $allFiles = [$path];
  167. }
  168. foreach ($allFiles as $file) {
  169. $usersSharing = $this->file->getAccessList($file);
  170. try {
  171. $encryptionModule->update($file, $this->uid, $usersSharing);
  172. } catch (GenericEncryptionException $e) {
  173. // If the update of an individual file fails e.g. due to a corrupt key we should continue the operation and just log the failure
  174. $this->logger->error('Failed to update encryption module for ' . $this->uid . ' ' . $file, [ 'exception' => $e ]);
  175. }
  176. }
  177. }
  178. }