From 09940bcde697df90423cb0b4ecb4e62ba31bfaf7 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 16 Apr 2018 14:14:31 +0200 Subject: [PATCH 1/6] List trashbin in DAV First steps for #1332 * Add a new DAV collection * List all files in the trashbin for this user * Deleting files from trashbin * Get files from trashbin (just read) Signed-off-by: Roeland Jago Douma --- apps/files_trashbin/appinfo/info.xml | 9 +- .../composer/composer/autoload_classmap.php | 6 + .../composer/composer/autoload_static.php | 6 + .../lib/AppInfo/Application.php | 13 ++ .../lib/Sabre/RootCollection.php | 58 +++++++++ apps/files_trashbin/lib/Sabre/TrashFile.php | 77 ++++++++++++ apps/files_trashbin/lib/Sabre/TrashFolder.php | 102 +++++++++++++++ .../lib/Sabre/TrashFolderFile.php | 81 ++++++++++++ .../lib/Sabre/TrashFolderFolder.php | 110 +++++++++++++++++ apps/files_trashbin/lib/Sabre/TrashHome.php | 116 ++++++++++++++++++ 10 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 apps/files_trashbin/lib/Sabre/RootCollection.php create mode 100644 apps/files_trashbin/lib/Sabre/TrashFile.php create mode 100644 apps/files_trashbin/lib/Sabre/TrashFolder.php create mode 100644 apps/files_trashbin/lib/Sabre/TrashFolderFile.php create mode 100644 apps/files_trashbin/lib/Sabre/TrashFolderFolder.php create mode 100644 apps/files_trashbin/lib/Sabre/TrashHome.php diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml index 585e61fe1e..a71443e694 100644 --- a/apps/files_trashbin/appinfo/info.xml +++ b/apps/files_trashbin/appinfo/info.xml @@ -9,13 +9,14 @@ This application enables users to restore files that were deleted from the syste To prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation. - 1.4.0 + 1.4.1 agpl Bjoern Schiessle Files_Trashbin + user-trashbin @@ -34,4 +35,10 @@ To prevent a user from running out of disk space, the Deleted files app will not OCA\Files_Trashbin\Command\CleanUp OCA\Files_Trashbin\Command\ExpireTrash + + + + OCA\Files_Trashbin\Sabre\RootCollection + + diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index 2e58c7b1c6..ad1d3db37e 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -18,6 +18,12 @@ return array( 'OCA\\Files_Trashbin\\Expiration' => $baseDir . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => $baseDir . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => $baseDir . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => $baseDir . '/../lib/Sabre/TrashFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => $baseDir . '/../lib/Sabre/TrashFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => $baseDir . '/../lib/Sabre/TrashFolderFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => $baseDir . '/../lib/Sabre/TrashFolderFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => $baseDir . '/../lib/Sabre/TrashHome.php', 'OCA\\Files_Trashbin\\Storage' => $baseDir . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index 01520e2d14..badea42dec 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -33,6 +33,12 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFile.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFolder.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => __DIR__ . '/..' . '/../lib/Sabre/TrashHome.php', 'OCA\\Files_Trashbin\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php index e9d4e6ecc1..ea27c8c16e 100644 --- a/apps/files_trashbin/lib/AppInfo/Application.php +++ b/apps/files_trashbin/lib/AppInfo/Application.php @@ -23,6 +23,7 @@ namespace OCA\Files_Trashbin\AppInfo; +use OCA\DAV\Connector\Sabre\Principal; use OCP\AppFramework\App; use OCA\Files_Trashbin\Expiration; use OCP\AppFramework\Utility\ITimeFactory; @@ -47,5 +48,17 @@ class Application extends App { $c->query(ITimeFactory::class) ); }); + + /* + * Register $principalBackend for the DAV collection + */ + $container->registerService('principalBackend', function () { + return new Principal( + \OC::$server->getUserManager(), + \OC::$server->getGroupManager(), + \OC::$server->getShareManager(), + \OC::$server->getUserSession() + ); + }); } } diff --git a/apps/files_trashbin/lib/Sabre/RootCollection.php b/apps/files_trashbin/lib/Sabre/RootCollection.php new file mode 100644 index 0000000000..226fc33e58 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/RootCollection.php @@ -0,0 +1,58 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\INode; +use Sabre\DAVACL\AbstractPrincipalCollection; +use Sabre\DAVACL\PrincipalBackend; + +class RootCollection extends AbstractPrincipalCollection { + + public function __construct(PrincipalBackend\BackendInterface $principalBackend) { + parent::__construct($principalBackend, 'principals/users'); + } + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principalInfo + * @return INode + */ + public function getChildForPrincipal(array $principalInfo) { + list(,$name) = \Sabre\Uri\split($principalInfo['uri']); + $user = \OC::$server->getUserSession()->getUser(); + if (is_null($user) || $name !== $user->getUID()) { + throw new \Sabre\DAV\Exception\Forbidden(); + } + return new TrashHome($principalInfo); + } + + public function getName() { + return 'trashbin'; + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php new file mode 100644 index 0000000000..39b788a2e2 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFile.php @@ -0,0 +1,77 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\IFile; + +class TrashFile implements IFile { + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $userId, FileInfo $data) { + $this->userId = $userId; + $this->data = $data; + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + return $this->data->getStorage()->fopen($this->data->getInternalPath().'.d'.$this->getLastModified(), 'rb'); + } + + public function getContentType() { + return $this->data->getMimetype(); + } + + public function getETag() { + return $this->data->getEtag(); + } + + public function getSize() { + return $this->data->getSize(); + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); + } + + public function getName() { + return $this->data->getName() . '.d' . $this->getLastModified(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + return $this->data->getMtime(); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php new file mode 100644 index 0000000000..2f97a73ebf --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -0,0 +1,102 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\ICollection; + +class TrashFolder implements ICollection { + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $root, string $userId, FileInfo $data) { + $this->userId = $userId; + $this->data = $data; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name) { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolderFolder($this->getName(), $this->userId, $entry); + } + return new TrashFolderFile($this->getName(), $this->userId, $entry); + } + } + } + + public function getChildren() { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolderFolder($this->getName(), $this->userId, $entry); + } + return new TrashFolderFile($this->getName(), $this->userId, $entry); + }, $entries); + + return $children; + } + + public function childExists($name) { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + return true; + } + } + + return false; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); + } + + public function getName() { + return $this->data->getName() . '.d' . $this->getLastModified(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + return $this->data->getMtime(); + } +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php new file mode 100644 index 0000000000..5a9133f3ad --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php @@ -0,0 +1,81 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\IFile; + +class TrashFolderFile implements IFile { + /** @var string */ + private $root; + + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $root, string $userId, FileInfo $data) { + $this->root = $root; + $this->userId = $userId; + $this->data = $data; + } + + public function put($data) { + throw new Forbidden(); + } + + public function get() { + return $this->data->getStorage()->fopen($this->data->getInternalPath(), 'rb'); + } + + public function getContentType() { + return $this->data->getMimetype(); + } + + public function getETag() { + return $this->data->getEtag(); + } + + public function getSize() { + return $this->data->getSize(); + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); + } + + public function getName() { + return $this->data->getName(); + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + return $this->data->getMtime(); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php new file mode 100644 index 0000000000..21c121c7d4 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -0,0 +1,110 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\ICollection; + +class TrashFolderFolder implements ICollection { + + /** @var string */ + private $root; + + + /** @var string */ + private $userId; + + /** @var FileInfo */ + private $data; + + public function __construct(string $root, string $userId, FileInfo $data) { + $this->root = $root; + $this->userId = $userId; + $this->data = $data; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name) { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry); + } + return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry); + } + } + } + + public function getChildren() { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry); + } + return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry); + }, $entries); + + return $children; + } + + public function childExists($name) { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() === $name) { + return true; + } + } + + return false; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); + } + + public function getName() { + return $this->data->getName(); + + } + + public function setName($name) { + throw new Forbidden(); + } + + function getLastModified() { + return $this->data->getMtime(); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php new file mode 100644 index 0000000000..45a95ccea8 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -0,0 +1,116 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashHome implements ICollection { + + /** + * @var array + */ + private $principalInfo; + + /** + * FilesHome constructor. + * + * @param array $principalInfo + */ + public function __construct($principalInfo) { + $this->principalInfo = $principalInfo; + } + + public function delete() { + throw new Forbidden('Permission denied to delete your trashbin'); + } + + public function getName(): string { + list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']); + return $name; + } + + public function setName($name) { + throw new Forbidden('Permission denied to rename this trashbin'); + } + + public function createFile($name, $data = null) { + throw new Forbidden('Not allowed to create files in the trashbin'); + } + + public function createDirectory($name) { + throw new Forbidden('Not allowed to create folders in the trashbin'); + } + + public function getChild($name) { + list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolder('/', $userId, $entry); + } + return new TrashFile($userId, $entry); + } + } + + throw new NotFound(); + } + + public function getChildren() { + list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); + + $children = array_map(function (FileInfo $entry) use ($userId) { + if ($entry->getMimetype() === 'httpd/unix-directory') { + return new TrashFolder('/', $userId, $entry); + } + return new TrashFile($userId, $entry); + }, $entries); + + return $children; + } + + public function childExists($name) { + list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + return true; + } + } + + return false; + } + + public function getLastModified() { + return 0; + } +} From f7ca6149d63d09f8ea0828770a243cf61295e2b9 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 16 Apr 2018 14:44:49 +0200 Subject: [PATCH 2/6] Emptry trashbin A delete on a users trashbin will empty it (the trashbin won't be deleted of course) Signed-off-by: Roeland Jago Douma --- apps/files_trashbin/lib/Sabre/TrashHome.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php index 45a95ccea8..9c460dbba2 100644 --- a/apps/files_trashbin/lib/Sabre/TrashHome.php +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -44,7 +44,7 @@ class TrashHome implements ICollection { } public function delete() { - throw new Forbidden('Permission denied to delete your trashbin'); + \OCA\Files_Trashbin\Trashbin::deleteAll(); } public function getName(): string { From cb617c4949f9b8570f65bf972c29d4cd78bc9b6e Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 16 Apr 2018 17:02:50 +0200 Subject: [PATCH 3/6] Add special restore folder Signed-off-by: Roeland Jago Douma --- .../composer/composer/autoload_classmap.php | 2 + .../composer/composer/autoload_static.php | 2 + apps/files_trashbin/lib/Sabre/ITrash.php | 27 ++++++ .../lib/Sabre/RestoreFolder.php | 86 +++++++++++++++++++ apps/files_trashbin/lib/Sabre/TrashFile.php | 6 +- apps/files_trashbin/lib/Sabre/TrashFolder.php | 8 +- .../lib/Sabre/TrashFolderFile.php | 6 +- .../lib/Sabre/TrashFolderFolder.php | 6 +- apps/files_trashbin/lib/Sabre/TrashHome.php | 6 ++ 9 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 apps/files_trashbin/lib/Sabre/ITrash.php create mode 100644 apps/files_trashbin/lib/Sabre/RestoreFolder.php diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index ad1d3db37e..fee5a3abb0 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -18,6 +18,8 @@ return array( 'OCA\\Files_Trashbin\\Expiration' => $baseDir . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => $baseDir . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => $baseDir . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\ITrash' => $baseDir . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php', 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => $baseDir . '/../lib/Sabre/TrashFile.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => $baseDir . '/../lib/Sabre/TrashFolder.php', diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index badea42dec..9b37b8955a 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -33,6 +33,8 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php', 'OCA\\Files_Trashbin\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php', + 'OCA\\Files_Trashbin\\Sabre\\ITrash' => __DIR__ . '/..' . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php', 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFile.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolder.php', diff --git a/apps/files_trashbin/lib/Sabre/ITrash.php b/apps/files_trashbin/lib/Sabre/ITrash.php new file mode 100644 index 0000000000..1c44334ffc --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/ITrash.php @@ -0,0 +1,27 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +interface ITrash { + public function restore(): bool; +} diff --git a/apps/files_trashbin/lib/Sabre/RestoreFolder.php b/apps/files_trashbin/lib/Sabre/RestoreFolder.php new file mode 100644 index 0000000000..b2416b1aeb --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/RestoreFolder.php @@ -0,0 +1,86 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\ICollection; +use Sabre\DAV\IMoveTarget; +use Sabre\DAV\INode; + + +class RestoreFolder implements ICollection, IMoveTarget { + + /** @var string */ + protected $userId; + + public function __construct(string $userId) { + $this->userId = $userId; + } + + public function createFile($name, $data = null) { + throw new Forbidden(); + } + + public function createDirectory($name) { + throw new Forbidden(); + } + + public function getChild($name) { + return null; + } + + public function delete() { + throw new Forbidden(); + } + + public function getName() { + return 'restore'; + } + + public function setName($name) { + throw new Forbidden(); + } + + public function getLastModified() { + return 0; + } + + public function getChildren() { + return []; + } + + public function childExists($name) { + return false; + } + + function moveInto($targetName, $sourcePath, INode $sourceNode) { + if (!($sourceNode instanceof ITrash)) { + return false; + } + + return $sourceNode->restore(); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php index 39b788a2e2..3e801a2757 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFile.php @@ -26,7 +26,7 @@ use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\IFile; -class TrashFile implements IFile { +class TrashFile implements IFile, ITrash { /** @var string */ private $userId; @@ -74,4 +74,8 @@ class TrashFile implements IFile { return $this->data->getMtime(); } + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); + } + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php index 2f97a73ebf..ebe7f7d487 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -26,7 +26,7 @@ use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\ICollection; -class TrashFolder implements ICollection { +class TrashFolder implements ICollection, ITrash { /** @var string */ private $userId; @@ -99,4 +99,10 @@ class TrashFolder implements ICollection { public function getLastModified() { return $this->data->getMtime(); } + + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); + } + + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php index 5a9133f3ad..b927d0a087 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php @@ -26,7 +26,7 @@ use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\IFile; -class TrashFolderFile implements IFile { +class TrashFolderFile implements IFile, ITrash { /** @var string */ private $root; @@ -78,4 +78,8 @@ class TrashFolderFile implements IFile { return $this->data->getMtime(); } + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); + } + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php index 21c121c7d4..efd208a1d8 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -26,7 +26,7 @@ use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\ICollection; -class TrashFolderFolder implements ICollection { +class TrashFolderFolder implements ICollection, ITrash { /** @var string */ private $root; @@ -107,4 +107,8 @@ class TrashFolderFolder implements ICollection { return $this->data->getMtime(); } + public function restore(): bool { + return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); + } + } diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php index 9c460dbba2..0a04755afc 100644 --- a/apps/files_trashbin/lib/Sabre/TrashHome.php +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -67,6 +67,10 @@ class TrashHome implements ICollection { public function getChild($name) { list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); + if ($name === 'restore') { + return new RestoreFolder($userId); + } + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); foreach ($entries as $entry) { @@ -93,6 +97,8 @@ class TrashHome implements ICollection { return new TrashFile($userId, $entry); }, $entries); + $children[] = new RestoreFolder($userId); + return $children; } From d5937e0fd6098b90cdfc6ea826d2ba7f1f37ad97 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Tue, 17 Apr 2018 22:22:41 +0200 Subject: [PATCH 4/6] Add propfind properties to trashbin * get original filename (without the weird timestamp) * get original location Signed-off-by: Roeland Jago Douma --- apps/files_trashbin/appinfo/info.xml | 3 + .../composer/composer/autoload_classmap.php | 1 + .../composer/composer/autoload_static.php | 1 + apps/files_trashbin/lib/Sabre/ITrash.php | 4 ++ .../lib/Sabre/PropfindPlugin.php | 63 +++++++++++++++++++ apps/files_trashbin/lib/Sabre/TrashFile.php | 9 +++ apps/files_trashbin/lib/Sabre/TrashFolder.php | 16 +++-- .../lib/Sabre/TrashFolderFile.php | 18 +++++- .../lib/Sabre/TrashFolderFolder.php | 26 ++++++-- 9 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 apps/files_trashbin/lib/Sabre/PropfindPlugin.php diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml index a71443e694..4ca60c0e26 100644 --- a/apps/files_trashbin/appinfo/info.xml +++ b/apps/files_trashbin/appinfo/info.xml @@ -40,5 +40,8 @@ To prevent a user from running out of disk space, the Deleted files app will not OCA\Files_Trashbin\Sabre\RootCollection + + OCA\Files_Trashbin\Sabre\PropfindPlugin + diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index fee5a3abb0..89e06f32c6 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -19,6 +19,7 @@ return array( 'OCA\\Files_Trashbin\\Helper' => $baseDir . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => $baseDir . '/../lib/Hooks.php', 'OCA\\Files_Trashbin\\Sabre\\ITrash' => $baseDir . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => $baseDir . '/../lib/Sabre/PropfindPlugin.php', 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php', 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => $baseDir . '/../lib/Sabre/TrashFile.php', diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index 9b37b8955a..e57fcec265 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -34,6 +34,7 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', 'OCA\\Files_Trashbin\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php', 'OCA\\Files_Trashbin\\Sabre\\ITrash' => __DIR__ . '/..' . '/../lib/Sabre/ITrash.php', + 'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => __DIR__ . '/..' . '/../lib/Sabre/PropfindPlugin.php', 'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php', 'OCA\\Files_Trashbin\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFile.php', diff --git a/apps/files_trashbin/lib/Sabre/ITrash.php b/apps/files_trashbin/lib/Sabre/ITrash.php index 1c44334ffc..5c776966ad 100644 --- a/apps/files_trashbin/lib/Sabre/ITrash.php +++ b/apps/files_trashbin/lib/Sabre/ITrash.php @@ -24,4 +24,8 @@ namespace OCA\Files_Trashbin\Sabre; interface ITrash { public function restore(): bool; + + public function getFilename(): string; + + public function getOriginalLocation(): string; } diff --git a/apps/files_trashbin/lib/Sabre/PropfindPlugin.php b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php new file mode 100644 index 0000000000..11cfabe141 --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php @@ -0,0 +1,63 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Files_Trashbin\Sabre; + +use Sabre\DAV\INode; +use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; + +class PropfindPlugin extends ServerPlugin { + + const TRASHBIN_FILENAME = '{http://nextcloud.org/ns}trashbin-filename'; + const TRASHBIN_ORIGINAL_LOCATION = '{http://nextcloud.org/ns}trashbin-original-location'; + + /** @var Server */ + private $server; + + public function __construct() { + } + + public function initialize(Server $server) { + $this->server = $server; + + $this->server->on('propFind', [$this, 'propFind']); + } + + + public function propFind(PropFind $propFind, INode $node) { + if (!($node instanceof ITrash)) { + return; + } + + $propFind->handle(self::TRASHBIN_FILENAME, function() use ($node) { + return $node->getFilename(); + }); + + $propFind->handle(self::TRASHBIN_ORIGINAL_LOCATION, function() use ($node) { + return $node->getOriginalLocation(); + }); + } + +} diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php index 3e801a2757..215dcec577 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFile.php @@ -78,4 +78,13 @@ class TrashFile implements IFile, ITrash { return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); } + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->data['extraData']; + } + + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php index ebe7f7d487..495c98c920 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -52,9 +52,9 @@ class TrashFolder implements ICollection, ITrash { foreach ($entries as $entry) { if ($entry->getName() === $name) { if ($entry->getMimetype() === 'httpd/unix-directory') { - return new TrashFolderFolder($this->getName(), $this->userId, $entry); + return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } - return new TrashFolderFile($this->getName(), $this->userId, $entry); + return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } } } @@ -64,9 +64,9 @@ class TrashFolder implements ICollection, ITrash { $children = array_map(function (FileInfo $entry) { if ($entry->getMimetype() === 'httpd/unix-directory') { - return new TrashFolderFolder($this->getName(), $this->userId, $entry); + return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } - return new TrashFolderFile($this->getName(), $this->userId, $entry); + return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); }, $entries); return $children; @@ -104,5 +104,13 @@ class TrashFolder implements ICollection, ITrash { return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified()); } + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->data['extraData']; + } + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php index b927d0a087..a9b8e838e0 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php @@ -36,10 +36,17 @@ class TrashFolderFile implements IFile, ITrash { /** @var FileInfo */ private $data; - public function __construct(string $root, string $userId, FileInfo $data) { + /** @var string */ + private $location; + + public function __construct(string $root, + string $userId, + FileInfo $data, + string $location) { $this->root = $root; $this->userId = $userId; $this->data = $data; + $this->location = $location; } public function put($data) { @@ -82,4 +89,13 @@ class TrashFolderFile implements IFile, ITrash { return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); } + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->location . '/' . $this->getFilename(); + } + + } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php index efd208a1d8..3607f90c56 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -38,10 +38,17 @@ class TrashFolderFolder implements ICollection, ITrash { /** @var FileInfo */ private $data; - public function __construct(string $root, string $userId, FileInfo $data) { + /** @var string */ + private $location; + + public function __construct(string $root, + string $userId, + FileInfo $data, + string $location) { $this->root = $root; $this->userId = $userId; $this->data = $data; + $this->location = $location; } public function createFile($name, $data = null) { @@ -58,9 +65,9 @@ class TrashFolderFolder implements ICollection, ITrash { foreach ($entries as $entry) { if ($entry->getName() === $name) { if ($entry->getMimetype() === 'httpd/unix-directory') { - return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry); + return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } - return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry); + return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } } } @@ -70,9 +77,9 @@ class TrashFolderFolder implements ICollection, ITrash { $children = array_map(function (FileInfo $entry) { if ($entry->getMimetype() === 'httpd/unix-directory') { - return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry); + return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } - return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry); + return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); }, $entries); return $children; @@ -111,4 +118,13 @@ class TrashFolderFolder implements ICollection, ITrash { return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null); } + public function getFilename(): string { + return $this->data->getName(); + } + + public function getOriginalLocation(): string { + return $this->location . '/' . $this->getFilename(); + } + + } From dadc740db5eb7a5641be842e10c283490fbf4c4d Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 25 Apr 2018 11:59:48 +0200 Subject: [PATCH 5/6] Use getType to determine type of entry Signed-off-by: Roeland Jago Douma --- apps/files_trashbin/lib/Sabre/TrashFolder.php | 4 ++-- apps/files_trashbin/lib/Sabre/TrashFolderFolder.php | 4 ++-- apps/files_trashbin/lib/Sabre/TrashHome.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php index 495c98c920..390f1956ff 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -51,7 +51,7 @@ class TrashFolder implements ICollection, ITrash { foreach ($entries as $entry) { if ($entry->getName() === $name) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); @@ -63,7 +63,7 @@ class TrashFolder implements ICollection, ITrash { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); $children = array_map(function (FileInfo $entry) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php index 3607f90c56..435e1f0019 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -64,7 +64,7 @@ class TrashFolderFolder implements ICollection, ITrash { foreach ($entries as $entry) { if ($entry->getName() === $name) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); @@ -76,7 +76,7 @@ class TrashFolderFolder implements ICollection, ITrash { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); $children = array_map(function (FileInfo $entry) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation()); diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php index 0a04755afc..4b2713ad69 100644 --- a/apps/files_trashbin/lib/Sabre/TrashHome.php +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -75,7 +75,7 @@ class TrashHome implements ICollection { foreach ($entries as $entry) { if ($entry->getName() . '.d'.$entry->getMtime() === $name) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolder('/', $userId, $entry); } return new TrashFile($userId, $entry); @@ -91,7 +91,7 @@ class TrashHome implements ICollection { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); $children = array_map(function (FileInfo $entry) use ($userId) { - if ($entry->getMimetype() === 'httpd/unix-directory') { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { return new TrashFolder('/', $userId, $entry); } return new TrashFile($userId, $entry); From c625fc5931c904e5d6bafe855429eebeae23467f Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 25 Apr 2018 20:24:23 +0200 Subject: [PATCH 6/6] Add folder for trashbin The trashbin home now contains 2 entries restore and trash. Made all files strict. Added more types. Signed-off-by: Roeland Jago Douma --- .../composer/composer/autoload_classmap.php | 1 + .../composer/composer/autoload_static.php | 1 + apps/files_trashbin/lib/Sabre/ITrash.php | 1 + .../lib/Sabre/PropfindPlugin.php | 1 + .../lib/Sabre/RestoreFolder.php | 8 +- .../lib/Sabre/RootCollection.php | 5 +- apps/files_trashbin/lib/Sabre/TrashFile.php | 11 +- apps/files_trashbin/lib/Sabre/TrashFolder.php | 14 ++- .../lib/Sabre/TrashFolderFile.php | 11 +- .../lib/Sabre/TrashFolderFolder.php | 15 ++- apps/files_trashbin/lib/Sabre/TrashHome.php | 61 +++-------- apps/files_trashbin/lib/Sabre/TrashRoot.php | 103 ++++++++++++++++++ 12 files changed, 158 insertions(+), 74 deletions(-) create mode 100644 apps/files_trashbin/lib/Sabre/TrashRoot.php diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index 89e06f32c6..3713de530c 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -27,6 +27,7 @@ return array( 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => $baseDir . '/../lib/Sabre/TrashFolderFile.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => $baseDir . '/../lib/Sabre/TrashFolderFolder.php', 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => $baseDir . '/../lib/Sabre/TrashHome.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => $baseDir . '/../lib/Sabre/TrashRoot.php', 'OCA\\Files_Trashbin\\Storage' => $baseDir . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index e57fcec265..b00778741b 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -42,6 +42,7 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFile' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFile.php', 'OCA\\Files_Trashbin\\Sabre\\TrashFolderFolder' => __DIR__ . '/..' . '/../lib/Sabre/TrashFolderFolder.php', 'OCA\\Files_Trashbin\\Sabre\\TrashHome' => __DIR__ . '/..' . '/../lib/Sabre/TrashHome.php', + 'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => __DIR__ . '/..' . '/../lib/Sabre/TrashRoot.php', 'OCA\\Files_Trashbin\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php', 'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php', ); diff --git a/apps/files_trashbin/lib/Sabre/ITrash.php b/apps/files_trashbin/lib/Sabre/ITrash.php index 5c776966ad..b0ff2b1570 100644 --- a/apps/files_trashbin/lib/Sabre/ITrash.php +++ b/apps/files_trashbin/lib/Sabre/ITrash.php @@ -1,4 +1,5 @@ * diff --git a/apps/files_trashbin/lib/Sabre/PropfindPlugin.php b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php index 11cfabe141..e50ee08590 100644 --- a/apps/files_trashbin/lib/Sabre/PropfindPlugin.php +++ b/apps/files_trashbin/lib/Sabre/PropfindPlugin.php @@ -1,4 +1,5 @@ * diff --git a/apps/files_trashbin/lib/Sabre/RestoreFolder.php b/apps/files_trashbin/lib/Sabre/RestoreFolder.php index b2416b1aeb..04f23db0ed 100644 --- a/apps/files_trashbin/lib/Sabre/RestoreFolder.php +++ b/apps/files_trashbin/lib/Sabre/RestoreFolder.php @@ -63,19 +63,19 @@ class RestoreFolder implements ICollection, IMoveTarget { throw new Forbidden(); } - public function getLastModified() { + public function getLastModified(): int { return 0; } - public function getChildren() { + public function getChildren(): array { return []; } - public function childExists($name) { + public function childExists($name): bool { return false; } - function moveInto($targetName, $sourcePath, INode $sourceNode) { + public function moveInto($targetName, $sourcePath, INode $sourceNode): bool { if (!($sourceNode instanceof ITrash)) { return false; } diff --git a/apps/files_trashbin/lib/Sabre/RootCollection.php b/apps/files_trashbin/lib/Sabre/RootCollection.php index 226fc33e58..e425fb448e 100644 --- a/apps/files_trashbin/lib/Sabre/RootCollection.php +++ b/apps/files_trashbin/lib/Sabre/RootCollection.php @@ -1,4 +1,5 @@ * @@ -42,7 +43,7 @@ class RootCollection extends AbstractPrincipalCollection { * @param array $principalInfo * @return INode */ - public function getChildForPrincipal(array $principalInfo) { + public function getChildForPrincipal(array $principalInfo): TrashHome { list(,$name) = \Sabre\Uri\split($principalInfo['uri']); $user = \OC::$server->getUserSession()->getUser(); if (is_null($user) || $name !== $user->getUID()) { @@ -51,7 +52,7 @@ class RootCollection extends AbstractPrincipalCollection { return new TrashHome($principalInfo); } - public function getName() { + public function getName(): string { return 'trashbin'; } diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php index 215dcec577..29e7a95562 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFile.php @@ -1,4 +1,5 @@ * @@ -46,15 +47,15 @@ class TrashFile implements IFile, ITrash { return $this->data->getStorage()->fopen($this->data->getInternalPath().'.d'.$this->getLastModified(), 'rb'); } - public function getContentType() { + public function getContentType(): string { return $this->data->getMimetype(); } - public function getETag() { + public function getETag(): string { return $this->data->getEtag(); } - public function getSize() { + public function getSize(): int { return $this->data->getSize(); } @@ -62,7 +63,7 @@ class TrashFile implements IFile, ITrash { \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); } - public function getName() { + public function getName(): string { return $this->data->getName() . '.d' . $this->getLastModified(); } @@ -70,7 +71,7 @@ class TrashFile implements IFile, ITrash { throw new Forbidden(); } - public function getLastModified() { + public function getLastModified(): int { return $this->data->getMtime(); } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php index 390f1956ff..33236eea26 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php @@ -1,4 +1,5 @@ * @@ -24,6 +25,7 @@ namespace OCA\Files_Trashbin\Sabre; use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ICollection; class TrashFolder implements ICollection, ITrash { @@ -46,7 +48,7 @@ class TrashFolder implements ICollection, ITrash { throw new Forbidden(); } - public function getChild($name) { + public function getChild($name): ITrash { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); foreach ($entries as $entry) { @@ -57,9 +59,11 @@ class TrashFolder implements ICollection, ITrash { return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } } + + throw new NotFound(); } - public function getChildren() { + public function getChildren(): array { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); $children = array_map(function (FileInfo $entry) { @@ -72,7 +76,7 @@ class TrashFolder implements ICollection, ITrash { return $children; } - public function childExists($name) { + public function childExists($name): bool { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId); foreach ($entries as $entry) { @@ -88,7 +92,7 @@ class TrashFolder implements ICollection, ITrash { \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified()); } - public function getName() { + public function getName(): string { return $this->data->getName() . '.d' . $this->getLastModified(); } @@ -96,7 +100,7 @@ class TrashFolder implements ICollection, ITrash { throw new Forbidden(); } - public function getLastModified() { + public function getLastModified(): int { return $this->data->getMtime(); } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php index a9b8e838e0..95e82d95a6 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php @@ -1,4 +1,5 @@ * @@ -57,15 +58,15 @@ class TrashFolderFile implements IFile, ITrash { return $this->data->getStorage()->fopen($this->data->getInternalPath(), 'rb'); } - public function getContentType() { + public function getContentType(): string { return $this->data->getMimetype(); } - public function getETag() { + public function getETag(): string { return $this->data->getEtag(); } - public function getSize() { + public function getSize(): int { return $this->data->getSize(); } @@ -73,7 +74,7 @@ class TrashFolderFile implements IFile, ITrash { \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); } - public function getName() { + public function getName(): string { return $this->data->getName(); } @@ -81,7 +82,7 @@ class TrashFolderFile implements IFile, ITrash { throw new Forbidden(); } - public function getLastModified() { + public function getLastModified(): int { return $this->data->getMtime(); } diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php index 435e1f0019..d2923c5891 100644 --- a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php +++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php @@ -1,4 +1,5 @@ * @@ -24,6 +25,7 @@ namespace OCA\Files_Trashbin\Sabre; use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ICollection; class TrashFolderFolder implements ICollection, ITrash { @@ -31,7 +33,6 @@ class TrashFolderFolder implements ICollection, ITrash { /** @var string */ private $root; - /** @var string */ private $userId; @@ -59,7 +60,7 @@ class TrashFolderFolder implements ICollection, ITrash { throw new Forbidden(); } - public function getChild($name) { + public function getChild($name): ITrash { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); foreach ($entries as $entry) { @@ -70,9 +71,11 @@ class TrashFolderFolder implements ICollection, ITrash { return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation()); } } + + throw new NotFound(); } - public function getChildren() { + public function getChildren(): array { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); $children = array_map(function (FileInfo $entry) { @@ -85,7 +88,7 @@ class TrashFolderFolder implements ICollection, ITrash { return $children; } - public function childExists($name) { + public function childExists($name): bool { $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId); foreach ($entries as $entry) { @@ -101,7 +104,7 @@ class TrashFolderFolder implements ICollection, ITrash { \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null); } - public function getName() { + public function getName(): string { return $this->data->getName(); } @@ -110,7 +113,7 @@ class TrashFolderFolder implements ICollection, ITrash { throw new Forbidden(); } - function getLastModified() { + public function getLastModified(): int { return $this->data->getMtime(); } diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php index 4b2713ad69..d1c50c9c6a 100644 --- a/apps/files_trashbin/lib/Sabre/TrashHome.php +++ b/apps/files_trashbin/lib/Sabre/TrashHome.php @@ -1,4 +1,5 @@ * @@ -22,29 +23,21 @@ */ namespace OCA\Files_Trashbin\Sabre; -use OCP\Files\FileInfo; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\ICollection; class TrashHome implements ICollection { - /** - * @var array - */ + /** @var array */ private $principalInfo; - /** - * FilesHome constructor. - * - * @param array $principalInfo - */ - public function __construct($principalInfo) { + public function __construct(array $principalInfo) { $this->principalInfo = $principalInfo; } public function delete() { - \OCA\Files_Trashbin\Trashbin::deleteAll(); + throw new Forbidden(); } public function getName(): string { @@ -70,53 +63,27 @@ class TrashHome implements ICollection { if ($name === 'restore') { return new RestoreFolder($userId); } - - $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); - - foreach ($entries as $entry) { - if ($entry->getName() . '.d'.$entry->getMtime() === $name) { - if ($entry->getType() === FileInfo::TYPE_FOLDER) { - return new TrashFolder('/', $userId, $entry); - } - return new TrashFile($userId, $entry); - } + if ($name === 'trash') { + return new TrashRoot($userId); } throw new NotFound(); } - public function getChildren() { + public function getChildren(): array { list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); - $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); - - $children = array_map(function (FileInfo $entry) use ($userId) { - if ($entry->getType() === FileInfo::TYPE_FOLDER) { - return new TrashFolder('/', $userId, $entry); - } - return new TrashFile($userId, $entry); - }, $entries); - - $children[] = new RestoreFolder($userId); - - return $children; + return [ + new RestoreFolder($userId), + new TrashRoot($userId), + ]; } - public function childExists($name) { - list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']); - - $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $userId); - - foreach ($entries as $entry) { - if ($entry->getName() . '.d'.$entry->getMtime() === $name) { - return true; - } - } - - return false; + public function childExists($name): bool { + return $name === 'restore' || $name === 'trash'; } - public function getLastModified() { + public function getLastModified(): int { return 0; } } diff --git a/apps/files_trashbin/lib/Sabre/TrashRoot.php b/apps/files_trashbin/lib/Sabre/TrashRoot.php new file mode 100644 index 0000000000..73b9d44d7e --- /dev/null +++ b/apps/files_trashbin/lib/Sabre/TrashRoot.php @@ -0,0 +1,103 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_Trashbin\Sabre; + +use OCP\Files\FileInfo; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\ICollection; + +class TrashRoot implements ICollection { + + /** @var string */ + private $userId; + + public function __construct(string $userId) { + $this->userId = $userId; + } + + public function delete() { + \OCA\Files_Trashbin\Trashbin::deleteAll(); + } + + public function getName(): string { + return 'trash'; + } + + public function setName($name) { + throw new Forbidden('Permission denied to rename this trashbin'); + } + + public function createFile($name, $data = null) { + throw new Forbidden('Not allowed to create files in the trashbin'); + } + + public function createDirectory($name) { + throw new Forbidden('Not allowed to create folders in the trashbin'); + } + + public function getChild($name): ITrash { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolder('/', $this->userId, $entry); + } + return new TrashFile($this->userId, $entry); + } + } + + throw new NotFound(); + } + + public function getChildren(): array { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + $children = array_map(function (FileInfo $entry) { + if ($entry->getType() === FileInfo::TYPE_FOLDER) { + return new TrashFolder('/', $this->userId, $entry); + } + return new TrashFile($this->userId, $entry); + }, $entries); + + return $children; + } + + public function childExists($name): bool { + $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId); + + foreach ($entries as $entry) { + if ($entry->getName() . '.d'.$entry->getMtime() === $name) { + return true; + } + } + + return false; + } + + public function getLastModified(): int { + return 0; + } +}