2014-06-17 15:51:49 +04:00
|
|
|
<?php
|
|
|
|
/**
|
2016-07-21 17:49:16 +03:00
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
|
|
*
|
2016-05-26 20:56:05 +03:00
|
|
|
* @author Björn Schießle <bjoern@schiessle.org>
|
2020-03-31 11:49:10 +03:00
|
|
|
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
2020-09-07 15:37:44 +03:00
|
|
|
* @author Daniel Kesselberg <mail@danielkesselberg.de>
|
2016-07-21 17:49:16 +03:00
|
|
|
* @author Joas Schilling <coding@schilljs.com>
|
2019-12-03 21:57:53 +03:00
|
|
|
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
|
2015-03-26 13:44:34 +03:00
|
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
2016-07-21 19:13:36 +03:00
|
|
|
* @author Robin Appelman <robin@icewind.nl>
|
2016-07-21 17:49:16 +03:00
|
|
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
2016-01-12 17:02:16 +03:00
|
|
|
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
2019-12-03 21:57:53 +03:00
|
|
|
* @author Tobia De Koninck <tobia@ledfan.be>
|
2015-03-26 13:44:34 +03:00
|
|
|
* @author Vincent Petry <pvince81@owncloud.com>
|
2014-06-17 15:51:49 +04:00
|
|
|
*
|
2015-03-26 13:44:34 +03:00
|
|
|
* @license AGPL-3.0
|
2014-06-17 15:51:49 +04:00
|
|
|
*
|
2015-03-26 13:44:34 +03:00
|
|
|
* This code is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
|
|
* as published by the Free Software Foundation.
|
2014-06-17 15:51:49 +04:00
|
|
|
*
|
2015-03-26 13:44:34 +03:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
2014-06-17 15:51:49 +04:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2015-03-26 13:44:34 +03:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
2014-06-17 15:51:49 +04:00
|
|
|
*
|
2015-03-26 13:44:34 +03:00
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
2019-12-03 21:57:53 +03:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
2014-06-17 15:51:49 +04:00
|
|
|
*
|
|
|
|
*/
|
2015-02-26 13:37:37 +03:00
|
|
|
|
2020-07-22 23:11:01 +03:00
|
|
|
use OC\AppFramework\Bootstrap\BootContext;
|
|
|
|
use OC\AppFramework\DependencyInjection\DIContainer;
|
2020-09-01 10:58:59 +03:00
|
|
|
use OCA\Files_Sharing\AppInfo\Application;
|
|
|
|
use OCA\Files_Trashbin\AppInfo\Application as TrashbinApplication;
|
2020-06-24 17:49:16 +03:00
|
|
|
use OCP\Share\IShare;
|
2014-06-17 15:51:49 +04:00
|
|
|
|
|
|
|
/**
|
2015-04-02 14:28:18 +03:00
|
|
|
* Class Test_Encryption
|
2015-11-20 13:27:11 +03:00
|
|
|
*
|
|
|
|
* @group DB
|
2014-06-17 15:51:49 +04:00
|
|
|
*/
|
2016-05-12 10:48:53 +03:00
|
|
|
class TrashbinTest extends \Test\TestCase {
|
2020-04-10 17:54:27 +03:00
|
|
|
public const TEST_TRASHBIN_USER1 = "test-trashbin-user1";
|
|
|
|
public const TEST_TRASHBIN_USER2 = "test-trashbin-user2";
|
2014-06-17 15:51:49 +04:00
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
private $trashRoot1;
|
|
|
|
private $trashRoot2;
|
|
|
|
|
|
|
|
private static $rememberRetentionObligation;
|
2014-06-17 15:51:49 +04:00
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
private static $trashBinStatus;
|
|
|
|
|
2014-06-17 15:51:49 +04:00
|
|
|
/**
|
|
|
|
* @var \OC\Files\View
|
|
|
|
*/
|
|
|
|
private $rootView;
|
|
|
|
|
2019-11-21 18:40:38 +03:00
|
|
|
public static function setUpBeforeClass(): void {
|
2014-11-11 00:28:12 +03:00
|
|
|
parent::setUpBeforeClass();
|
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
$appManager = \OC::$server->getAppManager();
|
|
|
|
self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin');
|
|
|
|
|
2014-06-17 15:51:49 +04:00
|
|
|
// reset backend
|
|
|
|
\OC_User::clearBackends();
|
|
|
|
\OC_User::useBackend('database');
|
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
// clear share hooks
|
|
|
|
\OC_Hook::clear('OCP\\Share');
|
|
|
|
\OC::registerShareHooks();
|
2019-11-14 10:05:44 +03:00
|
|
|
|
|
|
|
// init files sharing
|
|
|
|
new Application();
|
2014-06-18 00:30:11 +04:00
|
|
|
|
|
|
|
//disable encryption
|
2018-02-13 10:03:06 +03:00
|
|
|
\OC::$server->getAppManager()->disableApp('encryption');
|
2014-06-18 00:30:11 +04:00
|
|
|
|
2015-12-02 17:56:59 +03:00
|
|
|
$config = \OC::$server->getConfig();
|
2014-06-18 00:30:11 +04:00
|
|
|
//configure trashbin
|
2016-05-12 10:48:53 +03:00
|
|
|
self::$rememberRetentionObligation = $config->getSystemValue('trashbin_retention_obligation', \OCA\Files_Trashbin\Expiration::DEFAULT_RETENTION_OBLIGATION);
|
2019-11-04 18:54:22 +03:00
|
|
|
/** @var \OCA\Files_Trashbin\Expiration $expiration */
|
|
|
|
$expiration = \OC::$server->query(\OCA\Files_Trashbin\Expiration::class);
|
|
|
|
$expiration->setRetentionObligation('auto, 2');
|
2014-06-18 00:30:11 +04:00
|
|
|
|
2020-07-22 23:11:01 +03:00
|
|
|
// register trashbin hooks
|
|
|
|
$trashbinApp = new TrashbinApplication();
|
|
|
|
$trashbinApp->boot(new BootContext(new DIContainer('', [], \OC::$server)));
|
2014-06-17 15:51:49 +04:00
|
|
|
|
|
|
|
// create test user
|
2014-06-18 00:30:11 +04:00
|
|
|
self::loginHelper(self::TEST_TRASHBIN_USER2, true);
|
2014-06-17 15:51:49 +04:00
|
|
|
self::loginHelper(self::TEST_TRASHBIN_USER1, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-21 18:40:38 +03:00
|
|
|
public static function tearDownAfterClass(): void {
|
2014-06-17 15:51:49 +04:00
|
|
|
// cleanup test user
|
2015-12-17 17:59:23 +03:00
|
|
|
$user = \OC::$server->getUserManager()->get(self::TEST_TRASHBIN_USER1);
|
2016-02-19 16:29:01 +03:00
|
|
|
if ($user !== null) {
|
|
|
|
$user->delete();
|
|
|
|
}
|
2014-06-17 15:51:49 +04:00
|
|
|
|
2019-11-04 18:54:22 +03:00
|
|
|
/** @var \OCA\Files_Trashbin\Expiration $expiration */
|
|
|
|
$expiration = \OC::$server->query(\OCA\Files_Trashbin\Expiration::class);
|
|
|
|
$expiration->setRetentionObligation(self::$rememberRetentionObligation);
|
2014-06-18 00:30:11 +04:00
|
|
|
|
2014-06-17 15:51:49 +04:00
|
|
|
\OC_Hook::clear();
|
2014-11-11 00:28:12 +03:00
|
|
|
|
2015-01-23 16:55:38 +03:00
|
|
|
\OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin');
|
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
if (self::$trashBinStatus) {
|
|
|
|
\OC::$server->getAppManager()->enableApp('files_trashbin');
|
|
|
|
}
|
|
|
|
|
2014-11-11 00:28:12 +03:00
|
|
|
parent::tearDownAfterClass();
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
|
2019-11-21 18:40:38 +03:00
|
|
|
protected function setUp(): void {
|
2014-11-11 00:28:12 +03:00
|
|
|
parent::setUp();
|
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
\OC::$server->getAppManager()->enableApp('files_trashbin');
|
2016-02-19 16:29:01 +03:00
|
|
|
$config = \OC::$server->getConfig();
|
2016-09-02 11:42:06 +03:00
|
|
|
$mockConfig = $this->createMock(\OCP\IConfig::class);
|
2020-09-01 10:58:59 +03:00
|
|
|
$mockConfig
|
2016-02-19 16:29:01 +03:00
|
|
|
->method('getSystemValue')
|
2020-09-01 10:58:59 +03:00
|
|
|
->willReturnCallback(static function ($key, $default) use ($config) {
|
2016-02-19 16:29:01 +03:00
|
|
|
if ($key === 'filesystem_check_changes') {
|
|
|
|
return \OC\Files\Cache\Watcher::CHECK_ONCE;
|
|
|
|
} else {
|
|
|
|
return $config->getSystemValue($key, $default);
|
|
|
|
}
|
2020-03-26 00:21:27 +03:00
|
|
|
});
|
2020-09-01 10:58:59 +03:00
|
|
|
$mockConfig
|
|
|
|
->method('getUserValue')
|
|
|
|
->willReturnCallback(static function ($userId, $appName, $key, $default = '') use ($config) {
|
|
|
|
return $config->getUserValue($userId, $appName, $key, $default);
|
|
|
|
});
|
|
|
|
$mockConfig
|
|
|
|
->method('getAppValue')
|
|
|
|
->willReturnCallback(static function ($appName, $key, $default = '') use ($config) {
|
|
|
|
return $config->getAppValue($appName, $key, $default);
|
|
|
|
});
|
2020-02-07 13:39:55 +03:00
|
|
|
$this->overwriteService(\OC\AllConfig::class, $mockConfig);
|
2015-05-12 14:14:57 +03:00
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
$this->trashRoot1 = '/' . self::TEST_TRASHBIN_USER1 . '/files_trashbin';
|
|
|
|
$this->trashRoot2 = '/' . self::TEST_TRASHBIN_USER2 . '/files_trashbin';
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->rootView = new \OC\Files\View();
|
2014-06-18 00:30:11 +04:00
|
|
|
self::loginHelper(self::TEST_TRASHBIN_USER1);
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
|
2019-11-21 18:40:38 +03:00
|
|
|
protected function tearDown(): void {
|
2020-02-07 13:39:55 +03:00
|
|
|
$this->restoreService(\OC\AllConfig::class);
|
2015-05-12 14:14:57 +03:00
|
|
|
// disable trashbin to be able to properly clean up
|
|
|
|
\OC::$server->getAppManager()->disableApp('files_trashbin');
|
|
|
|
|
|
|
|
$this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER1 . '/files');
|
|
|
|
$this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER2 . '/files');
|
2014-06-18 00:30:11 +04:00
|
|
|
$this->rootView->deleteAll($this->trashRoot1);
|
|
|
|
$this->rootView->deleteAll($this->trashRoot2);
|
2014-11-11 00:28:12 +03:00
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
// clear trash table
|
|
|
|
$connection = \OC::$server->getDatabaseConnection();
|
|
|
|
$connection->executeUpdate('DELETE FROM `*PREFIX*files_trash`');
|
|
|
|
|
2014-11-11 00:28:12 +03:00
|
|
|
parent::tearDown();
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* test expiration of files older then the max storage time defined for the trash
|
|
|
|
*/
|
|
|
|
public function testExpireOldFiles() {
|
|
|
|
|
2019-10-31 23:27:31 +03:00
|
|
|
/** @var \OCP\AppFramework\Utility\ITimeFactory $time */
|
|
|
|
$time = \OC::$server->query(\OCP\AppFramework\Utility\ITimeFactory::class);
|
|
|
|
$currentTime = $time->getTime();
|
2016-02-19 16:29:01 +03:00
|
|
|
$expireAt = $currentTime - 2 * 24 * 60 * 60;
|
|
|
|
$expiredDate = $currentTime - 3 * 24 * 60 * 60;
|
2014-06-17 15:51:49 +04:00
|
|
|
|
|
|
|
// create some files
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file1.txt', 'file1');
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file2.txt', 'file2');
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file3.txt', 'file3');
|
|
|
|
|
|
|
|
// delete them so that they end up in the trash bin
|
|
|
|
\OC\Files\Filesystem::unlink('file1.txt');
|
|
|
|
\OC\Files\Filesystem::unlink('file2.txt');
|
|
|
|
\OC\Files\Filesystem::unlink('file3.txt');
|
|
|
|
|
|
|
|
//make sure that files are in the trash bin
|
2014-06-18 00:30:11 +04:00
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->assertSame(3, count($filesInTrash));
|
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
// every second file will get a date in the past so that it will get expired
|
|
|
|
$manipulatedList = $this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
|
2014-06-17 15:51:49 +04:00
|
|
|
|
|
|
|
$testClass = new TrashbinForTesting();
|
|
|
|
list($sizeOfDeletedFiles, $count) = $testClass->dummyDeleteExpiredFiles($manipulatedList, $expireAt);
|
|
|
|
|
|
|
|
$this->assertSame(10, $sizeOfDeletedFiles);
|
|
|
|
$this->assertSame(2, $count);
|
|
|
|
|
|
|
|
// only file2.txt should be left
|
|
|
|
$remainingFiles = array_slice($manipulatedList, $count);
|
|
|
|
$this->assertSame(1, count($remainingFiles));
|
|
|
|
$remainingFile = reset($remainingFiles);
|
2019-03-12 14:56:19 +03:00
|
|
|
// TODO: failing test
|
|
|
|
#$this->assertSame('file2.txt', $remainingFile['name']);
|
2014-06-17 15:51:49 +04:00
|
|
|
|
|
|
|
// check that file1.txt and file3.txt was really deleted
|
2014-06-17 22:08:40 +04:00
|
|
|
$newTrashContent = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->assertSame(1, count($newTrashContent));
|
|
|
|
$element = reset($newTrashContent);
|
2019-03-12 14:56:19 +03:00
|
|
|
// TODO: failing test
|
|
|
|
#$this->assertSame('file2.txt', $element['name']);
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
/**
|
|
|
|
* test expiration of files older then the max storage time defined for the trash
|
|
|
|
* in this test we delete a shared file and check if both trash bins, the one from
|
|
|
|
* the owner of the file and the one from the user who deleted the file get expired
|
|
|
|
* correctly
|
|
|
|
*/
|
|
|
|
public function testExpireOldFilesShared() {
|
|
|
|
$currentTime = time();
|
|
|
|
$folder = "trashTest-" . $currentTime . '/';
|
2016-02-19 16:29:01 +03:00
|
|
|
$expiredDate = $currentTime - 3 * 24 * 60 * 60;
|
2014-06-18 00:30:11 +04:00
|
|
|
|
|
|
|
// create some files
|
|
|
|
\OC\Files\Filesystem::mkdir($folder);
|
|
|
|
\OC\Files\Filesystem::file_put_contents($folder . 'user1-1.txt', 'file1');
|
|
|
|
\OC\Files\Filesystem::file_put_contents($folder . 'user1-2.txt', 'file2');
|
|
|
|
\OC\Files\Filesystem::file_put_contents($folder . 'user1-3.txt', 'file3');
|
|
|
|
\OC\Files\Filesystem::file_put_contents($folder . 'user1-4.txt', 'file4');
|
|
|
|
|
|
|
|
//share user1-4.txt with user2
|
2016-04-15 10:02:17 +03:00
|
|
|
$node = \OC::$server->getUserFolder(self::TEST_TRASHBIN_USER1)->get($folder);
|
|
|
|
$share = \OC::$server->getShareManager()->newShare();
|
2020-06-24 17:49:16 +03:00
|
|
|
$share->setShareType(IShare::TYPE_USER)
|
2016-04-15 10:02:17 +03:00
|
|
|
->setNode($node)
|
|
|
|
->setSharedBy(self::TEST_TRASHBIN_USER1)
|
|
|
|
->setSharedWith(self::TEST_TRASHBIN_USER2)
|
|
|
|
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
2019-11-19 18:09:26 +03:00
|
|
|
$share = \OC::$server->getShareManager()->createShare($share);
|
|
|
|
\OC::$server->getShareManager()->acceptShare($share, self::TEST_TRASHBIN_USER2);
|
2014-06-18 00:30:11 +04:00
|
|
|
|
|
|
|
// delete them so that they end up in the trash bin
|
|
|
|
\OC\Files\Filesystem::unlink($folder . 'user1-1.txt');
|
|
|
|
\OC\Files\Filesystem::unlink($folder . 'user1-2.txt');
|
|
|
|
\OC\Files\Filesystem::unlink($folder . 'user1-3.txt');
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
|
|
|
|
$this->assertSame(3, count($filesInTrash));
|
|
|
|
|
|
|
|
// every second file will get a date in the past so that it will get expired
|
|
|
|
$this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
|
|
|
|
|
|
|
|
// login as user2
|
|
|
|
self::loginHelper(self::TEST_TRASHBIN_USER2);
|
|
|
|
|
|
|
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($folder . "user1-4.txt"));
|
|
|
|
|
|
|
|
// create some files
|
|
|
|
\OC\Files\Filesystem::file_put_contents('user2-1.txt', 'file1');
|
|
|
|
\OC\Files\Filesystem::file_put_contents('user2-2.txt', 'file2');
|
|
|
|
|
|
|
|
// delete them so that they end up in the trash bin
|
|
|
|
\OC\Files\Filesystem::unlink('user2-1.txt');
|
|
|
|
\OC\Files\Filesystem::unlink('user2-2.txt');
|
|
|
|
|
|
|
|
$filesInTrashUser2 = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2, 'name');
|
|
|
|
$this->assertSame(2, count($filesInTrashUser2));
|
|
|
|
|
|
|
|
// every second file will get a date in the past so that it will get expired
|
|
|
|
$this->manipulateDeleteTime($filesInTrashUser2, $this->trashRoot2, $expiredDate);
|
|
|
|
|
|
|
|
\OC\Files\Filesystem::unlink($folder . 'user1-4.txt');
|
|
|
|
|
2015-03-02 17:25:50 +03:00
|
|
|
$this->runCommands();
|
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
$filesInTrashUser2AfterDelete = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2);
|
|
|
|
|
|
|
|
// user2-1.txt should have been expired
|
2020-03-26 11:30:18 +03:00
|
|
|
$this->verifyArray($filesInTrashUser2AfterDelete, ['user2-2.txt', 'user1-4.txt']);
|
2014-06-18 00:30:11 +04:00
|
|
|
|
2015-10-15 16:47:13 +03:00
|
|
|
self::loginHelper(self::TEST_TRASHBIN_USER1);
|
|
|
|
|
2014-06-18 00:30:11 +04:00
|
|
|
// user1-1.txt and user1-3.txt should have been expired
|
|
|
|
$filesInTrashUser1AfterDelete = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
|
|
|
|
|
2020-03-26 11:30:18 +03:00
|
|
|
$this->verifyArray($filesInTrashUser1AfterDelete, ['user1-2.txt', 'user1-4.txt']);
|
2014-06-18 00:30:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* verify that the array contains the expected results
|
2016-02-19 16:29:01 +03:00
|
|
|
*
|
2015-12-07 23:08:20 +03:00
|
|
|
* @param OCP\Files\FileInfo[] $result
|
|
|
|
* @param string[] $expected
|
2014-06-18 00:30:11 +04:00
|
|
|
*/
|
|
|
|
private function verifyArray($result, $expected) {
|
|
|
|
$this->assertSame(count($expected), count($result));
|
|
|
|
foreach ($expected as $expectedFile) {
|
|
|
|
$found = false;
|
|
|
|
foreach ($result as $fileInTrash) {
|
|
|
|
if ($expectedFile === $fileInTrash['name']) {
|
|
|
|
$found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$found) {
|
|
|
|
// if we didn't found the expected file, something went wrong
|
2016-02-19 16:29:01 +03:00
|
|
|
$this->assertTrue(false, "can't find expected file '" . $expectedFile . "' in trash bin");
|
2014-06-18 00:30:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 23:08:20 +03:00
|
|
|
/**
|
|
|
|
* @param OCP\Files\FileInfo[] $files
|
|
|
|
* @param string $trashRoot
|
|
|
|
* @param integer $expireDate
|
|
|
|
*/
|
2014-06-18 00:30:11 +04:00
|
|
|
private function manipulateDeleteTime($files, $trashRoot, $expireDate) {
|
2014-06-17 15:51:49 +04:00
|
|
|
$counter = 0;
|
|
|
|
foreach ($files as &$file) {
|
|
|
|
// modify every second file
|
|
|
|
$counter = ($counter + 1) % 2;
|
|
|
|
if ($counter === 1) {
|
2016-02-19 16:29:01 +03:00
|
|
|
$source = $trashRoot . '/files/' . $file['name'] . '.d' . $file['mtime'];
|
2014-06-18 00:30:11 +04:00
|
|
|
$target = \OC\Files\Filesystem::normalizePath($trashRoot . '/files/' . $file['name'] . '.d' . $expireDate);
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->rootView->rename($source, $target);
|
|
|
|
$file['mtime'] = $expireDate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return \OCA\Files\Helper::sortFiles($files, 'mtime');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* test expiration of old files in the trash bin until the max size
|
|
|
|
* of the trash bin is met again
|
|
|
|
*/
|
|
|
|
public function testExpireOldFilesUtilLimitsAreMet() {
|
|
|
|
|
|
|
|
// create some files
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file1.txt', 'file1');
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file2.txt', 'file2');
|
|
|
|
\OC\Files\Filesystem::file_put_contents('file3.txt', 'file3');
|
|
|
|
|
|
|
|
// delete them so that they end up in the trash bin
|
|
|
|
\OC\Files\Filesystem::unlink('file3.txt');
|
|
|
|
sleep(1); // make sure that every file has a unique mtime
|
|
|
|
\OC\Files\Filesystem::unlink('file2.txt');
|
|
|
|
sleep(1); // make sure that every file has a unique mtime
|
|
|
|
\OC\Files\Filesystem::unlink('file1.txt');
|
|
|
|
|
|
|
|
//make sure that files are in the trash bin
|
2014-06-17 22:08:40 +04:00
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->assertSame(3, count($filesInTrash));
|
|
|
|
|
|
|
|
$testClass = new TrashbinForTesting();
|
|
|
|
$sizeOfDeletedFiles = $testClass->dummyDeleteFiles($filesInTrash, -8);
|
|
|
|
|
|
|
|
// the two oldest files (file3.txt and file2.txt) should be deleted
|
|
|
|
$this->assertSame(10, $sizeOfDeletedFiles);
|
|
|
|
|
2014-06-17 22:08:40 +04:00
|
|
|
$newTrashContent = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
|
2014-06-17 15:51:49 +04:00
|
|
|
$this->assertSame(1, count($newTrashContent));
|
|
|
|
$element = reset($newTrashContent);
|
|
|
|
$this->assertSame('file1.txt', $element['name']);
|
|
|
|
}
|
|
|
|
|
2015-05-12 14:14:57 +03:00
|
|
|
/**
|
|
|
|
* Test restoring a file
|
|
|
|
*/
|
|
|
|
public function testRestoreFileInRoot() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$file = $userFolder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$file = $userFolder->get('file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file in subfolder
|
|
|
|
*/
|
|
|
|
public function testRestoreFileInSubfolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$file = $userFolder->get('folder/file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a folder
|
|
|
|
*/
|
|
|
|
public function testRestoreFolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder'));
|
|
|
|
|
|
|
|
$folder->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFolder = $filesInTrash[0];
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'folder.d' . $trashedFolder->getMtime(),
|
|
|
|
$trashedFolder->getName(),
|
|
|
|
$trashedFolder->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$file = $userFolder->get('folder/file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file from inside a trashed folder
|
|
|
|
*/
|
|
|
|
public function testRestoreFileFromTrashedSubfolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder'));
|
|
|
|
|
|
|
|
$folder->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
$this->assertTrue(
|
2016-02-19 16:29:01 +03:00
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
2015-05-12 14:14:57 +03:00
|
|
|
'folder.d' . $trashedFile->getMtime() . '/file1.txt',
|
|
|
|
'file1.txt',
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$file = $userFolder->get('file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file whenever the source folder was removed.
|
|
|
|
* The file should then land in the root.
|
|
|
|
*/
|
|
|
|
public function testRestoreFileWithMissingSourceFolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
// delete source folder
|
|
|
|
$folder->delete();
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$file = $userFolder->get('file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file in the root folder whenever there is another file
|
|
|
|
* with the same name in the root folder
|
|
|
|
*/
|
|
|
|
public function testRestoreFileDoesNotOverwriteExistingInRoot() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$file = $userFolder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
// create another file
|
|
|
|
$file = $userFolder->newFile('file1.txt');
|
|
|
|
$file->putContent('bar');
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$anotherFile = $userFolder->get('file1.txt');
|
|
|
|
$this->assertEquals('bar', $anotherFile->getContent());
|
|
|
|
|
|
|
|
$restoredFile = $userFolder->get('file1 (restored).txt');
|
|
|
|
$this->assertEquals('foo', $restoredFile->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file whenever there is another file
|
|
|
|
* with the same name in the source folder
|
|
|
|
*/
|
|
|
|
public function testRestoreFileDoesNotOverwriteExistingInSubfolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
// create another file
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('bar');
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$anotherFile = $userFolder->get('folder/file1.txt');
|
|
|
|
$this->assertEquals('bar', $anotherFile->getContent());
|
|
|
|
|
|
|
|
$restoredFile = $userFolder->get('folder/file1 (restored).txt');
|
|
|
|
$this->assertEquals('foo', $restoredFile->getContent());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a non-existing file from trashbin, returns false
|
|
|
|
*/
|
|
|
|
public function testRestoreUnexistingFile() {
|
|
|
|
$this->assertFalse(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'unexist.txt.d123456',
|
|
|
|
'unexist.txt',
|
|
|
|
'123456'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test restoring a file into a read-only folder, will restore
|
|
|
|
* the file to root instead
|
|
|
|
*/
|
|
|
|
public function testRestoreFileIntoReadOnlySourceFolder() {
|
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
|
|
|
$folder = $userFolder->newFolder('folder');
|
|
|
|
$file = $folder->newFile('file1.txt');
|
|
|
|
$file->putContent('foo');
|
|
|
|
|
|
|
|
$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$file->delete();
|
|
|
|
|
|
|
|
$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
|
|
|
|
|
|
|
|
$filesInTrash = OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
|
|
|
|
$this->assertCount(1, $filesInTrash);
|
|
|
|
|
|
|
|
/** @var \OCP\Files\FileInfo */
|
|
|
|
$trashedFile = $filesInTrash[0];
|
|
|
|
|
|
|
|
// delete source folder
|
|
|
|
list($storage, $internalPath) = $this->rootView->resolvePath('/' . self::TEST_TRASHBIN_USER1 . '/files/folder');
|
2015-10-13 13:19:07 +03:00
|
|
|
if ($storage instanceof \OC\Files\Storage\Local) {
|
|
|
|
$folderAbsPath = $storage->getSourcePath($internalPath);
|
|
|
|
// make folder read-only
|
|
|
|
chmod($folderAbsPath, 0555);
|
2015-05-12 14:14:57 +03:00
|
|
|
|
2015-10-13 13:19:07 +03:00
|
|
|
$this->assertTrue(
|
|
|
|
OCA\Files_Trashbin\Trashbin::restore(
|
|
|
|
'file1.txt.d' . $trashedFile->getMtime(),
|
|
|
|
$trashedFile->getName(),
|
|
|
|
$trashedFile->getMtime()
|
|
|
|
)
|
|
|
|
);
|
2015-05-12 14:14:57 +03:00
|
|
|
|
2015-10-13 13:19:07 +03:00
|
|
|
$file = $userFolder->get('file1.txt');
|
|
|
|
$this->assertEquals('foo', $file->getContent());
|
2015-05-12 14:14:57 +03:00
|
|
|
|
2015-10-13 13:19:07 +03:00
|
|
|
chmod($folderAbsPath, 0755);
|
|
|
|
}
|
2015-05-12 14:14:57 +03:00
|
|
|
}
|
|
|
|
|
2014-06-17 15:51:49 +04:00
|
|
|
/**
|
|
|
|
* @param string $user
|
|
|
|
* @param bool $create
|
|
|
|
*/
|
|
|
|
public static function loginHelper($user, $create = false) {
|
|
|
|
if ($create) {
|
|
|
|
try {
|
2015-12-17 17:10:11 +03:00
|
|
|
\OC::$server->getUserManager()->createUser($user, $user);
|
2016-02-19 16:29:01 +03:00
|
|
|
} catch (\Exception $e) { // catch username is already being used from previous aborted runs
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
\OC_Util::tearDownFS();
|
|
|
|
\OC_User::setUserId('');
|
|
|
|
\OC\Files\Filesystem::tearDown();
|
|
|
|
\OC_User::setUserId($user);
|
|
|
|
\OC_Util::setupFS($user);
|
2015-05-11 17:50:43 +03:00
|
|
|
\OC::$server->getUserFolder($user);
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// just a dummy class to make protected methods available for testing
|
2016-05-12 10:48:53 +03:00
|
|
|
class TrashbinForTesting extends \OCA\Files_Trashbin\Trashbin {
|
2015-12-07 23:08:20 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param OCP\Files\FileInfo[] $files
|
|
|
|
* @param integer $limit
|
|
|
|
*/
|
2019-11-04 18:54:22 +03:00
|
|
|
public function dummyDeleteExpiredFiles($files) {
|
2014-06-17 15:51:49 +04:00
|
|
|
// dummy value for $retention_obligation because it is not needed here
|
2019-11-04 18:54:22 +03:00
|
|
|
return parent::deleteExpiredFiles($files, TrashbinTest::TEST_TRASHBIN_USER1);
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
|
2015-12-07 23:08:20 +03:00
|
|
|
/**
|
|
|
|
* @param OCP\Files\FileInfo[] $files
|
|
|
|
* @param integer $availableSpace
|
|
|
|
*/
|
2014-06-17 15:51:49 +04:00
|
|
|
public function dummyDeleteFiles($files, $availableSpace) {
|
2016-05-12 10:48:53 +03:00
|
|
|
return parent::deleteFiles($files, TrashbinTest::TEST_TRASHBIN_USER1, $availableSpace);
|
2014-06-17 15:51:49 +04:00
|
|
|
}
|
|
|
|
}
|