diff options
-rw-r--r-- | core/ajax/preview.php | 2 | ||||
-rw-r--r-- | lib/private/preview.php | 27 | ||||
-rw-r--r-- | lib/private/repair.php | 2 | ||||
-rw-r--r-- | lib/repair/repairinvalidshares.php | 79 | ||||
-rw-r--r-- | tests/lib/preview.php | 74 | ||||
-rw-r--r-- | tests/lib/repair/repairinvalidsharestest.php | 123 | ||||
-rw-r--r-- | version.php | 2 |
7 files changed, 285 insertions, 24 deletions
diff --git a/core/ajax/preview.php b/core/ajax/preview.php index c8bc05453ed..b6362fb3a70 100644 --- a/core/ajax/preview.php +++ b/core/ajax/preview.php @@ -53,7 +53,7 @@ if (!$info instanceof OCP\Files\FileInfo || !$always && !\OC::$server->getPrevie \OC_Response::setStatus(404); } else { $preview = new \OC\Preview(\OC_User::getUser(), 'files'); - $preview->setFile($file); + $preview->setFile($file, $info); $preview->setMaxX($maxX); $preview->setMaxY($maxY); $preview->setScalingUp($scalingUp); diff --git a/lib/private/preview.php b/lib/private/preview.php index 1127048b7fd..b2accdfd00f 100644 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -252,12 +252,13 @@ class Preview { * Sets the path of the file you want a preview of * * @param string $file + * @param \OCP\Files\FileInfo|null $info * * @return \OC\Preview */ - public function setFile($file) { + public function setFile($file, $info = null) { $this->file = $file; - $this->info = null; + $this->info = $info; if ($file !== '') { $this->getFileInfo(); @@ -374,7 +375,7 @@ class Preview { return false; } - if (!$this->fileView->file_exists($file)) { + if (!$this->getFileInfo() instanceof FileInfo) { \OCP\Util::writeLog('core', 'File:"' . $file . '" not found', \OCP\Util::DEBUG); return false; @@ -478,7 +479,7 @@ class Preview { $preview = $this->buildCachePath($fileId, $previewWidth, $previewHeight); // This checks if we have a preview of those exact dimensions in the cache - if ($this->userView->file_exists($preview)) { + if ($this->thumbnailSizeExists($allThumbnails, basename($preview))) { return $preview; } @@ -524,6 +525,24 @@ class Preview { } /** + * Check if a specific thumbnail size is cached + * + * @param FileInfo[] $allThumbnails the list of all our cached thumbnails + * @param string $name + * @return bool + */ + private function thumbnailSizeExists(array $allThumbnails, $name) { + + foreach ($allThumbnails as $thumbnail) { + if ($name === $thumbnail->getName()) { + return true; + } + } + + return false; + } + + /** * Determines the size of the preview we should be looking for in the cache * * @return int[] diff --git a/lib/private/repair.php b/lib/private/repair.php index 3639440a518..20219e313fd 100644 --- a/lib/private/repair.php +++ b/lib/private/repair.php @@ -44,6 +44,7 @@ use OC\Repair\RepairLegacyStorages; use OC\Repair\RepairMimeTypes; use OC\Repair\SearchLuceneTables; use OC\Repair\UpdateOutdatedOcsIds; +use OC\Repair\RepairInvalidShares; class Repair extends BasicEmitter { /** @@ -113,6 +114,7 @@ class Repair extends BasicEmitter { new DropOldJobs(\OC::$server->getJobList()), new RemoveGetETagEntries(\OC::$server->getDatabaseConnection()), new UpdateOutdatedOcsIds(\OC::$server->getConfig()), + new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()), ]; } diff --git a/lib/repair/repairinvalidshares.php b/lib/repair/repairinvalidshares.php new file mode 100644 index 00000000000..21b4d8013e7 --- /dev/null +++ b/lib/repair/repairinvalidshares.php @@ -0,0 +1,79 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * 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. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\Repair; + +use OC\Hooks\BasicEmitter; + +/** + * Repairs shares with invalid data + */ +class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep { + + /** + * @var \OCP\IConfig + */ + protected $config; + + /** + * @var \OCP\IDBConnection + */ + protected $connection; + + /** + * @param \OCP\IConfig $config + * @param \OCP\IDBConnection $connection + */ + public function __construct($config, $connection) { + $this->connection = $connection; + $this->config = $config; + } + + public function getName() { + return 'Repair invalid shares'; + } + + /** + * Past bugs would make it possible to set an expiration date on user shares even + * though it is not supported. This functions removes the expiration date from such entries. + */ + private function removeExpirationDateFromNonLinkShares() { + $builder = $this->connection->getQueryBuilder(); + $builder + ->update('share') + ->set('expiration', 'null') + ->where($builder->expr()->isNotNull('expiration')) + ->andWhere($builder->expr()->neq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK))); + + $updatedEntries = $builder->execute(); + if ($updatedEntries > 0) { + $this->emit('\OC\Repair', 'info', array('Removed invalid expiration date from ' . $updatedEntries . ' shares')); + } + } + + public function run() { + $ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0'); + if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.7', '<')) { + // this situation was only possible before 8.2 + $this->removeExpirationDateFromNonLinkShares(); + } + } +} diff --git a/tests/lib/preview.php b/tests/lib/preview.php index 9374cf2393f..e4c599c66cf 100644 --- a/tests/lib/preview.php +++ b/tests/lib/preview.php @@ -22,7 +22,15 @@ namespace Test; +use OC\Files\FileInfo; +use OC\Files\Storage\Temporary; +use OC\Files\View; +use Test\Traits\MountProviderTrait; +use Test\Traits\UserTrait; + class Preview extends TestCase { + use UserTrait; + use MountProviderTrait; const TEST_PREVIEW_USER1 = "test-preview-user1"; @@ -59,11 +67,7 @@ class Preview extends TestCase { protected function setUp() { parent::setUp(); - $userManager = \OC::$server->getUserManager(); - $userManager->clearBackends(); - $backend = new \Test\Util\User\Dummy(); - $userManager->registerBackend($backend); - $backend->createUser(self::TEST_PREVIEW_USER1, self::TEST_PREVIEW_USER1); + $this->createUser(self::TEST_PREVIEW_USER1, self::TEST_PREVIEW_USER1); $this->loginAsUser(self::TEST_PREVIEW_USER1); $storage = new \OC\Files\Storage\Temporary([]); @@ -75,13 +79,13 @@ class Preview extends TestCase { // We simulate the max dimension set in the config \OC::$server->getConfig() - ->setSystemValue('preview_max_x', $this->configMaxWidth); + ->setSystemValue('preview_max_x', $this->configMaxWidth); \OC::$server->getConfig() - ->setSystemValue('preview_max_y', $this->configMaxHeight); + ->setSystemValue('preview_max_y', $this->configMaxHeight); // Used to test upscaling $this->maxScaleFactor = 2; \OC::$server->getConfig() - ->setSystemValue('preview_max_scale_factor', $this->maxScaleFactor); + ->setSystemValue('preview_max_scale_factor', $this->maxScaleFactor); // We need to enable the providers we're going to use in the tests $providers = [ @@ -92,7 +96,7 @@ class Preview extends TestCase { 'OC\\Preview\\Postscript' ]; \OC::$server->getConfig() - ->setSystemValue('enabledPreviewProviders', $providers); + ->setSystemValue('enabledPreviewProviders', $providers); // Sample is 1680x1050 JPEG $this->prepareSample('testimage.jpg', 1680, 1050); @@ -161,7 +165,7 @@ class Preview extends TestCase { $fileId = $fileInfo['fileid']; $thumbCacheFolder = '/' . self::TEST_PREVIEW_USER1 . '/' . \OC\Preview::THUMBNAILS_FOLDER . - '/' . $fileId . '/'; + '/' . $fileId . '/'; $this->assertSame(true, $this->rootView->is_dir($thumbCacheFolder), "$thumbCacheFolder \n"); @@ -318,7 +322,7 @@ class Preview extends TestCase { // There should be no cached thumbnails $thumbnailFolder = '/' . self::TEST_PREVIEW_USER1 . '/' . \OC\Preview::THUMBNAILS_FOLDER . - '/' . $sampleFileId; + '/' . $sampleFileId; $this->assertSame(false, $this->rootView->is_dir($thumbnailFolder)); $image = $preview->getPreview(); @@ -611,7 +615,7 @@ class Preview extends TestCase { // Need to take care of special postfix added to the dimensions $postfix = ''; $isMaxPreview = ($width === $this->maxPreviewWidth - && $height === $this->maxPreviewHeight) ? true : false; + && $height === $this->maxPreviewHeight) ? true : false; if ($isMaxPreview) { $postfix = '-max'; } @@ -731,7 +735,7 @@ class Preview extends TestCase { } return $userPath . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId - . '/' . $width . '-' . $height . $postfix . '.png'; + . '/' . $width . '-' . $height . $postfix . '.png'; } /** @@ -752,11 +756,11 @@ class Preview extends TestCase { $this->samples[] = [ - 'sampleFileId' => $fileInfo['fileid'], - 'sampleFileName' => $fileName, - 'sampleWidth' => $sampleWidth, - 'sampleHeight' => $sampleHeight, - 'maxPreviewWidth' => $maxPreviewWidth, + 'sampleFileId' => $fileInfo['fileid'], + 'sampleFileName' => $fileName, + 'sampleWidth' => $sampleWidth, + 'sampleHeight' => $sampleHeight, + 'maxPreviewWidth' => $maxPreviewWidth, 'maxPreviewHeight' => $maxPreviewHeight ]; } @@ -915,4 +919,38 @@ class Preview extends TestCase { $this->assertGreaterThanOrEqual(150, $image->width()); $this->assertGreaterThanOrEqual(150, $image->height()); } + + public function testSetFileWithInfo() { + $info = new FileInfo('/foo', null, '/foo', ['mimetype' => 'foo/bar'], null); + $preview = new \OC\Preview(); + $preview->setFile('/foo', $info); + $this->assertEquals($info, $this->invokePrivate($preview, 'getFileInfo')); + } + + public function testIsCached() { + $sourceFile = __DIR__ . '/../data/testimage.png'; + $userId = $this->getUniqueID(); + $this->createUser($userId, 'pass'); + + $storage = new Temporary(); + $storage->mkdir('files'); + $this->registerMount($userId, $storage, '/' . $userId); + + \OC_Util::tearDownFS(); + \OC_Util::setupFS($userId); + $preview = new \OC\Preview($userId, 'files'); + $view = new View('/' . $userId . '/files'); + $view->file_put_contents('test.png', file_get_contents($sourceFile)); + $info = $view->getFileInfo('test.png'); + $preview->setFile('test.png', $info); + + $preview->setMaxX(64); + $preview->setMaxY(64); + + $this->assertFalse($preview->isCached($info->getId())); + + $preview->getPreview(); + + $this->assertEquals('thumbnails/' . $info->getId() . '/64-64.png', $preview->isCached($info->getId())); + } } diff --git a/tests/lib/repair/repairinvalidsharestest.php b/tests/lib/repair/repairinvalidsharestest.php new file mode 100644 index 00000000000..89a5ba470e1 --- /dev/null +++ b/tests/lib/repair/repairinvalidsharestest.php @@ -0,0 +1,123 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Repair; + + +use OC\Repair\RepairInvalidShares; +use OC\Share\Constants; +use Test\TestCase; + +/** + * Tests for repairing invalid shares + * + * @see \OC\Repair\RepairInvalidShares + */ +class RepairInvalidSharesTest extends TestCase { + + /** @var \OC\RepairStep */ + private $repair; + + /** @var \OCP\IDBConnection */ + private $connection; + + protected function setUp() { + parent::setUp(); + + $config = $this->getMockBuilder('OCP\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $config->expects($this->any()) + ->method('getSystemValue') + ->with('version') + ->will($this->returnValue('8.0.0.0')); + + $this->connection = \OC::$server->getDatabaseConnection(); + $this->deleteAllShares(); + + /** @var \OCP\IConfig $config */ + $this->repair = new RepairInvalidShares($config, $this->connection); + } + + protected function tearDown() { + $this->deleteAllShares(); + + parent::tearDown(); + } + + protected function deleteAllShares() { + $qb = $this->connection->getQueryBuilder(); + $qb->delete('share')->execute(); + } + + /** + * Test remove expiration date for non-link shares + */ + public function testRemoveExpirationDateForNonLinkShares() { + // user share with bogus expiration date + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER), + 'share_with' => $qb->expr()->literal('recipientuser1'), + 'uid_owner' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('folder'), + 'item_source' => $qb->expr()->literal(123), + 'item_target' => $qb->expr()->literal('/123'), + 'file_source' => $qb->expr()->literal(123), + 'file_target' => $qb->expr()->literal('/test'), + 'permissions' => $qb->expr()->literal(1), + 'stime' => $qb->expr()->literal(time()), + 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00') + ]) + ->execute(); + + // select because lastInsertId does not work with OCI + $results = $this->connection->getQueryBuilder() + ->select('id') + ->from('share') + ->execute() + ->fetchAll(); + $bogusShareId = $results[0]['id']; + + // link share with expiration date + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK), + 'uid_owner' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('folder'), + 'item_source' => $qb->expr()->literal(123), + 'item_target' => $qb->expr()->literal('/123'), + 'file_source' => $qb->expr()->literal(123), + 'file_target' => $qb->expr()->literal('/test'), + 'permissions' => $qb->expr()->literal(1), + 'stime' => $qb->expr()->literal(time()), + 'expiration' => $qb->expr()->literal('2015-09-25 00:00:00'), + 'token' => $qb->expr()->literal('abcdefg') + ])->execute(); + + $this->repair->run(); + + $results = $this->connection->getQueryBuilder() + ->select('*') + ->from('share') + ->orderBy('share_type', 'ASC') + ->execute() + ->fetchAll(); + + $this->assertCount(2, $results); + + $userShare = $results[0]; + $linkShare = $results[1]; + $this->assertEquals($bogusShareId, $userShare['id'], 'sanity check'); + $this->assertNull($userShare['expiration'], 'bogus expiration date was removed'); + $this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there'); + } +} + diff --git a/version.php b/version.php index 711d82f1ca1..925e897d1ab 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(8, 2, 0, 6); +$OC_Version = array(8, 2, 0, 7); // The human readable string $OC_VersionString = '8.2 beta1'; |