summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-01-10 13:50:14 +0100
committerGitHub <noreply@github.com>2017-01-10 13:50:14 +0100
commit4dd2a1e6798b9915e20ac72272fbe1bab0266e93 (patch)
tree0af51b4d71cac3458391d1d60cc0a33f8be2591e /lib
parenta5bf14ada3b7edab724fac30ea89996f1a10f157 (diff)
parente19e7c08ad31816914710c45c8bfe0be9b3afff4 (diff)
downloadnextcloud-server-4dd2a1e6798b9915e20ac72272fbe1bab0266e93.tar.gz
nextcloud-server-4dd2a1e6798b9915e20ac72272fbe1bab0266e93.zip
Merge pull request #2943 from nextcloud/kill_old_preview_code
Cleanup old preview code
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php17
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Preview.php1349
-rw-r--r--lib/private/PreviewManager.php24
-rw-r--r--lib/private/Server.php3
-rw-r--r--lib/public/IPreview.php2
7 files changed, 24 insertions, 1373 deletions
diff --git a/lib/base.php b/lib/base.php
index dc8b29932ef..8b271010b10 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -747,9 +747,6 @@ class OC {
self::registerCacheHooks();
self::registerFilesystemHooks();
- if ($systemConfig->getValue('enable_previews', true)) {
- self::registerPreviewHooks();
- }
self::registerShareHooks();
self::registerLogRotate();
self::registerEncryptionWrapper();
@@ -900,20 +897,6 @@ class OC {
}
/**
- * register hooks for previews
- */
- public static function registerPreviewHooks() {
- OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
- OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
- OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
- OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
- OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
- OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
- OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
- OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
- }
-
- /**
* register hooks for sharing
*/
public static function registerShareHooks() {
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 48b457bbabe..2e5fc685e88 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -629,7 +629,6 @@ return array(
'OC\\OCS\\PrivateData' => $baseDir . '/lib/private/OCS/PrivateData.php',
'OC\\OCS\\Provider' => $baseDir . '/lib/private/OCS/Provider.php',
'OC\\OCS\\Result' => $baseDir . '/lib/private/OCS/Result.php',
- 'OC\\Preview' => $baseDir . '/lib/private/Preview.php',
'OC\\PreviewManager' => $baseDir . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => $baseDir . '/lib/private/PreviewNotAvailableException.php',
'OC\\Preview\\BMP' => $baseDir . '/lib/private/Preview/BMP.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 7c14ad7e847..2b8233f6569 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -659,7 +659,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\OCS\\PrivateData' => __DIR__ . '/../../..' . '/lib/private/OCS/PrivateData.php',
'OC\\OCS\\Provider' => __DIR__ . '/../../..' . '/lib/private/OCS/Provider.php',
'OC\\OCS\\Result' => __DIR__ . '/../../..' . '/lib/private/OCS/Result.php',
- 'OC\\Preview' => __DIR__ . '/../../..' . '/lib/private/Preview.php',
'OC\\PreviewManager' => __DIR__ . '/../../..' . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => __DIR__ . '/../../..' . '/lib/private/PreviewNotAvailableException.php',
'OC\\Preview\\BMP' => __DIR__ . '/../../..' . '/lib/private/Preview/BMP.php',
diff --git a/lib/private/Preview.php b/lib/private/Preview.php
deleted file mode 100644
index caa1e89bacc..00000000000
--- a/lib/private/Preview.php
+++ /dev/null
@@ -1,1349 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Georg Ehrke <georg@owncloud.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Tobias Kaminsky <tobias@kaminsky.me>
- *
- * @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;
-
-use OC\Preview\Provider;
-use OCP\Files\FileInfo;
-use OCP\Files\NotFoundException;
-
-class Preview {
- //the thumbnail folder
- const THUMBNAILS_FOLDER = 'thumbnails';
-
- const MODE_FILL = 'fill';
- const MODE_COVER = 'cover';
-
- //config
- private $maxScaleFactor;
- /** @var int maximum width allowed for a preview */
- private $configMaxWidth;
- /** @var int maximum height allowed for a preview */
- private $configMaxHeight;
-
- //fileview object
- private $fileView = null;
- private $userView = null;
-
- //vars
- private $file;
- private $maxX;
- private $maxY;
- private $scalingUp;
- private $mimeType;
- private $keepAspect = false;
- private $mode = self::MODE_FILL;
-
- //used to calculate the size of the preview to generate
- /** @var int $maxPreviewWidth max width a preview can have */
- private $maxPreviewWidth;
- /** @var int $maxPreviewHeight max height a preview can have */
- private $maxPreviewHeight;
- /** @var int $previewWidth calculated width of the preview we're looking for */
- private $previewWidth;
- /** @var int $previewHeight calculated height of the preview we're looking for */
- private $previewHeight;
-
- //filemapper used for deleting previews
- // index is path, value is fileinfo
- static public $deleteFileMapper = array();
- static public $deleteChildrenMapper = array();
-
- /**
- * preview images object
- *
- * @var \OCP\IImage
- */
- private $preview;
-
- /**
- * @var \OCP\Files\FileInfo
- */
- protected $info;
-
- /**
- * check if thumbnail or bigger version of thumbnail of file is cached
- *
- * @param string $user userid - if no user is given, OC_User::getUser will be used
- * @param string $root path of root
- * @param string $file The path to the file where you want a thumbnail from
- * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the
- * shape of the image
- * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the
- * shape of the image
- * @param bool $scalingUp Disable/Enable upscaling of previews
- *
- * @throws \Exception
- * @return mixed (bool / string)
- * false if thumbnail does not exist
- * path to thumbnail if thumbnail exists
- */
- public function __construct(
- $user = '',
- $root = '/',
- $file = '', $maxX = 1,
- $maxY = 1,
- $scalingUp = true
- ) {
- //init fileviews
- if ($user === '') {
- $user = \OC_User::getUser();
- }
- $this->fileView = new \OC\Files\View('/' . $user . '/' . $root);
- $this->userView = new \OC\Files\View('/' . $user);
-
- //set config
- $sysConfig = \OC::$server->getConfig();
- $this->configMaxWidth = $sysConfig->getSystemValue('preview_max_x', 2048);
- $this->configMaxHeight = $sysConfig->getSystemValue('preview_max_y', 2048);
- $this->maxScaleFactor = $sysConfig->getSystemValue('preview_max_scale_factor', 1);
-
- //save parameters
- $this->setFile($file);
- $this->setMaxX((int)$maxX);
- $this->setMaxY((int)$maxY);
- $this->setScalingup($scalingUp);
-
- $this->preview = null;
-
- //check if there are preview backends
- if (!\OC::$server->getPreviewManager()
- ->hasProviders()
- && \OC::$server->getConfig()
- ->getSystemValue('enable_previews', true)
- ) {
- \OCP\Util::writeLog('core', 'No preview providers exist', \OCP\Util::ERROR);
- throw new \Exception('No preview providers');
- }
- }
-
- /**
- * returns the path of the file you want a thumbnail from
- *
- * @return string
- */
- public function getFile() {
- return $this->file;
- }
-
- /**
- * returns the max width of the preview
- *
- * @return integer
- */
- public function getMaxX() {
- return $this->maxX;
- }
-
- /**
- * returns the max height of the preview
- *
- * @return integer
- */
- public function getMaxY() {
- return $this->maxY;
- }
-
- /**
- * returns whether or not scalingup is enabled
- *
- * @return bool
- */
- public function getScalingUp() {
- return $this->scalingUp;
- }
-
- /**
- * returns the name of the thumbnailfolder
- *
- * @return string
- */
- public function getThumbnailsFolder() {
- return self::THUMBNAILS_FOLDER;
- }
-
- /**
- * returns the max scale factor
- *
- * @return string
- */
- public function getMaxScaleFactor() {
- return $this->maxScaleFactor;
- }
-
- /**
- * returns the max width set in ownCloud's config
- *
- * @return integer
- */
- public function getConfigMaxX() {
- return $this->configMaxWidth;
- }
-
- /**
- * returns the max height set in ownCloud's config
- *
- * @return integer
- */
- public function getConfigMaxY() {
- return $this->configMaxHeight;
- }
-
- /**
- * Returns the FileInfo object associated with the file to preview
- *
- * @return false|Files\FileInfo|\OCP\Files\FileInfo
- */
- protected function getFileInfo() {
- $absPath = $this->fileView->getAbsolutePath($this->file);
- $absPath = Files\Filesystem::normalizePath($absPath);
- if (array_key_exists($absPath, self::$deleteFileMapper)) {
- $this->info = self::$deleteFileMapper[$absPath];
- } else if (!$this->info) {
- $this->info = $this->fileView->getFileInfo($this->file);
- }
-
- return $this->info;
- }
-
-
- /**
- * @return array|null
- */
- private function getChildren() {
- $absPath = $this->fileView->getAbsolutePath($this->file);
- $absPath = Files\Filesystem::normalizePath($absPath);
-
- if (array_key_exists($absPath, self::$deleteChildrenMapper)) {
- return self::$deleteChildrenMapper[$absPath];
- }
-
- return null;
- }
-
- /**
- * 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, $info = null) {
- $this->file = $file;
- $this->info = $info;
-
- if ($file !== '') {
- $this->getFileInfo();
- if ($this->info instanceof \OCP\Files\FileInfo) {
- $this->mimeType = $this->info->getMimetype();
- }
- }
-
- return $this;
- }
-
- /**
- * Forces the use of a specific media type
- *
- * @param string $mimeType
- */
- public function setMimetype($mimeType) {
- $this->mimeType = $mimeType;
- }
-
- /**
- * Sets the max width of the preview. It's capped by the maximum allowed size set in the
- * configuration
- *
- * @param int $maxX
- *
- * @throws \Exception
- * @return \OC\Preview
- */
- public function setMaxX($maxX = 1) {
- if ($maxX <= 0) {
- throw new \Exception('Cannot set width of 0 or smaller!');
- }
- $configMaxX = $this->getConfigMaxX();
- $maxX = $this->limitMaxDim($maxX, $configMaxX, 'maxX');
- $this->maxX = $maxX;
-
- return $this;
- }
-
- /**
- * Sets the max height of the preview. It's capped by the maximum allowed size set in the
- * configuration
- *
- * @param int $maxY
- *
- * @throws \Exception
- * @return \OC\Preview
- */
- public function setMaxY($maxY = 1) {
- if ($maxY <= 0) {
- throw new \Exception('Cannot set height of 0 or smaller!');
- }
- $configMaxY = $this->getConfigMaxY();
- $maxY = $this->limitMaxDim($maxY, $configMaxY, 'maxY');
- $this->maxY = $maxY;
-
- return $this;
- }
-
- /**
- * Sets whether we're allowed to scale up when generating a preview. It's capped by the maximum
- * allowed scale factor set in the configuration
- *
- * @param bool $scalingUp
- *
- * @return \OC\Preview
- */
- public function setScalingup($scalingUp) {
- if ($this->getMaxScaleFactor() === 1) {
- $scalingUp = false;
- }
- $this->scalingUp = $scalingUp;
-
- return $this;
- }
-
- /**
- * Set whether to cover or fill the specified dimensions
- *
- * @param string $mode
- *
- * @return \OC\Preview
- */
- public function setMode($mode) {
- $this->mode = $mode;
-
- return $this;
- }
-
- /**
- * Sets whether we need to generate a preview which keeps the aspect ratio of the original file
- *
- * @param bool $keepAspect
- *
- * @return \OC\Preview
- */
- public function setKeepAspect($keepAspect) {
- $this->keepAspect = $keepAspect;
-
- return $this;
- }
-
- /**
- * Makes sure we were given a file to preview and that it exists in the filesystem
- *
- * @return bool
- */
- public function isFileValid() {
- $file = $this->getFile();
- if ($file === '') {
- \OCP\Util::writeLog('core', 'No filename passed', \OCP\Util::DEBUG);
-
- return false;
- }
-
- if (!$this->getFileInfo() instanceof FileInfo) {
- \OCP\Util::writeLog('core', 'File:"' . $file . '" not found', \OCP\Util::DEBUG);
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Deletes the preview of a file with specific width and height
- *
- * This should never delete the max preview, use deleteAllPreviews() instead
- *
- * @return bool
- */
- public function deletePreview() {
- $fileInfo = $this->getFileInfo();
- if ($fileInfo !== null && $fileInfo !== false) {
- $fileId = $fileInfo->getId();
-
- $previewPath = $this->buildCachePath($fileId);
- if (!strpos($previewPath, 'max')) {
- return $this->userView->unlink($previewPath);
- }
- }
-
- return false;
- }
-
- /**
- * Deletes all previews of a file
- */
- public function deleteAllPreviews() {
- $thumbnailMount = $this->userView->getMount($this->getThumbnailsFolder());
- $propagator = $thumbnailMount->getStorage()->getPropagator();
- $propagator->beginBatch();
-
- $toDelete = $this->getChildren();
- $toDelete[] = $this->getFileInfo();
-
- foreach ($toDelete as $delete) {
- if ($delete instanceof FileInfo) {
- /** @var \OCP\Files\FileInfo $delete */
- $fileId = $delete->getId();
-
- // getId() might return null, e.g. when the file is a
- // .ocTransferId*.part file from chunked file upload.
- if (!empty($fileId)) {
- $previewPath = $this->getPreviewPath($fileId);
- $this->userView->rmdir($previewPath);
- }
- }
- }
-
- $propagator->commitBatch();
- }
-
- /**
- * Checks if a preview matching the asked dimensions or a bigger version is already cached
- *
- * * We first retrieve the size of the max preview since this is what we be used to create
- * all our preview. If it doesn't exist we return false, so that it can be generated
- * * Using the dimensions of the max preview, we calculate what the size of the new
- * thumbnail should be
- * * And finally, we look for a suitable candidate in the cache
- *
- * @param int $fileId fileId of the original file we need a preview of
- *
- * @return string|false path to the cached preview if it exists or false
- */
- public function isCached($fileId) {
- if (is_null($fileId)) {
- return false;
- }
-
- /**
- * Phase 1: Looking for the max preview
- */
- $previewPath = $this->getPreviewPath($fileId);
- // We currently can't look for a single file due to bugs related to #16478
- $allThumbnails = $this->userView->getDirectoryContent($previewPath);
- list($maxPreviewWidth, $maxPreviewHeight) = $this->getMaxPreviewSize($allThumbnails);
-
- // Only use the cache if we have a max preview
- if (!is_null($maxPreviewWidth) && !is_null($maxPreviewHeight)) {
-
- /**
- * Phase 2: Calculating the size of the preview we need to send back
- */
- $this->maxPreviewWidth = $maxPreviewWidth;
- $this->maxPreviewHeight = $maxPreviewHeight;
-
- list($previewWidth, $previewHeight) = $this->simulatePreviewDimensions();
- if (empty($previewWidth) || empty($previewHeight)) {
- return false;
- }
-
- $this->previewWidth = $previewWidth;
- $this->previewHeight = $previewHeight;
-
- /**
- * Phase 3: We look for a preview of the exact size
- */
- // This gives us a calculated path to a preview of asked dimensions
- // thumbnailFolder/fileId/<maxX>-<maxY>(-max|-with-aspect).png
- $preview = $this->buildCachePath($fileId, $previewWidth, $previewHeight);
-
- // This checks if we have a preview of those exact dimensions in the cache
- if ($this->thumbnailSizeExists($allThumbnails, basename($preview))) {
- return $preview;
- }
-
- /**
- * Phase 4: We look for a larger preview, matching the aspect ratio
- */
- if (($this->getMaxX() >= $maxPreviewWidth)
- && ($this->getMaxY() >= $maxPreviewHeight)
- ) {
- // The preview we-re looking for is the exact size or larger than the max preview,
- // so return that
- return $this->buildCachePath($fileId, $maxPreviewWidth, $maxPreviewHeight);
- } else {
- // The last resort is to look for something bigger than what we've calculated,
- // but still smaller than the max preview
- return $this->isCachedBigger($fileId, $allThumbnails);
- }
- }
-
- return false;
- }
-
- /**
- * Returns the dimensions of the max preview
- *
- * @param FileInfo[] $allThumbnails the list of all our cached thumbnails
- *
- * @return int[]
- */
- private function getMaxPreviewSize($allThumbnails) {
- $maxPreviewX = null;
- $maxPreviewY = null;
-
- foreach ($allThumbnails as $thumbnail) {
- $name = $thumbnail['name'];
- if (strpos($name, 'max')) {
- list($maxPreviewX, $maxPreviewY) = $this->getDimensionsFromFilename($name);
- break;
- }
- }
-
- return [$maxPreviewX, $maxPreviewY];
- }
-
- /**
- * 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 integer[]
- */
- private function simulatePreviewDimensions() {
- $askedWidth = $this->getMaxX();
- $askedHeight = $this->getMaxY();
-
- if ($this->keepAspect) {
- list($newPreviewWidth, $newPreviewHeight) =
- $this->applyAspectRatio($askedWidth, $askedHeight);
- } else {
- list($newPreviewWidth, $newPreviewHeight) = $this->fixSize($askedWidth, $askedHeight);
- }
-
- return [(int)$newPreviewWidth, (int)$newPreviewHeight];
- }
-
- /**
- * Resizes the boundaries to match the aspect ratio
- *
- * @param int $askedWidth
- * @param int $askedHeight
- *
- * @param int $originalWidth
- * @param int $originalHeight
- * @return integer[]
- */
- private function applyAspectRatio($askedWidth, $askedHeight, $originalWidth = 0, $originalHeight = 0) {
- if (!$originalWidth) {
- $originalWidth = $this->maxPreviewWidth;
- }
- if (!$originalHeight) {
- $originalHeight = $this->maxPreviewHeight;
- }
- $originalRatio = $originalWidth / $originalHeight;
- // Defines the box in which the preview has to fit
- $scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1;
- $askedWidth = min($askedWidth, $originalWidth * $scaleFactor);
- $askedHeight = min($askedHeight, $originalHeight * $scaleFactor);
-
- if ($askedWidth / $originalRatio < $askedHeight) {
- // width restricted
- $askedHeight = round($askedWidth / $originalRatio);
- } else {
- $askedWidth = round($askedHeight * $originalRatio);
- }
-
- return [(int)$askedWidth, (int)$askedHeight];
- }
-
- /**
- * Resizes the boundaries to cover the area
- *
- * @param int $askedWidth
- * @param int $askedHeight
- * @param int $previewWidth
- * @param int $previewHeight
- * @return integer[]
- */
- private function applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight) {
- $originalRatio = $previewWidth / $previewHeight;
- // Defines the box in which the preview has to fit
- $scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1;
- $askedWidth = min($askedWidth, $previewWidth * $scaleFactor);
- $askedHeight = min($askedHeight, $previewHeight * $scaleFactor);
-
- if ($askedWidth / $originalRatio > $askedHeight) {
- // height restricted
- $askedHeight = round($askedWidth / $originalRatio);
- } else {
- $askedWidth = round($askedHeight * $originalRatio);
- }
-
- return [(int)$askedWidth, (int)$askedHeight];
- }
-
- /**
- * Makes sure an upscaled preview doesn't end up larger than the max dimensions defined in the
- * config
- *
- * @param int $askedWidth
- * @param int $askedHeight
- *
- * @return integer[]
- */
- private function fixSize($askedWidth, $askedHeight) {
- if ($this->scalingUp) {
- $askedWidth = min($this->configMaxWidth, $askedWidth);
- $askedHeight = min($this->configMaxHeight, $askedHeight);
- }
-
- return [(int)$askedWidth, (int)$askedHeight];
- }
-
- /**
- * Checks if a bigger version of a file preview is cached and if not
- * return the preview of max allowed dimensions
- *
- * @param int $fileId fileId of the original image
- * @param FileInfo[] $allThumbnails the list of all our cached thumbnails
- *
- * @return string path to bigger thumbnail
- */
- private function isCachedBigger($fileId, $allThumbnails) {
- // This is used to eliminate any thumbnail narrower than what we need
- $maxX = $this->getMaxX();
-
- //array for usable cached thumbnails
- $possibleThumbnails = $this->getPossibleThumbnails($allThumbnails);
-
- foreach ($possibleThumbnails as $width => $path) {
- if ($width < $maxX) {
- continue;
- } else {
- return $path;
- }
- }
-
- // At this stage, we didn't find a preview, so we return the max preview
- return $this->buildCachePath($fileId, $this->maxPreviewWidth, $this->maxPreviewHeight);
- }
-
- /**
- * Get possible bigger thumbnails of the given image with the proper aspect ratio
- *
- * @param FileInfo[] $allThumbnails the list of all our cached thumbnails
- *
- * @return string[] an array of paths to bigger thumbnails
- */
- private function getPossibleThumbnails($allThumbnails) {
- if ($this->keepAspect) {
- $wantedAspectRatio = (float)($this->maxPreviewWidth / $this->maxPreviewHeight);
- } else {
- $wantedAspectRatio = (float)($this->getMaxX() / $this->getMaxY());
- }
-
- //array for usable cached thumbnails
- $possibleThumbnails = array();
- foreach ($allThumbnails as $thumbnail) {
- $name = rtrim($thumbnail['name'], '.png');
- list($x, $y, $aspectRatio) = $this->getDimensionsFromFilename($name);
- if (abs($aspectRatio - $wantedAspectRatio) >= 0.000001
- || $this->unscalable($x, $y)
- ) {
- continue;
- }
- $possibleThumbnails[$x] = $thumbnail['path'];
- }
-
- ksort($possibleThumbnails);
-
- return $possibleThumbnails;
- }
-
- /**
- * Looks at the preview filename from the cache and extracts the size of the preview
- *
- * @param string $name
- *
- * @return array<int,int,float>
- */
- private function getDimensionsFromFilename($name) {
- $size = explode('-', $name);
- $x = (int)$size[0];
- $y = (int)$size[1];
- $aspectRatio = (float)($x / $y);
-
- return array($x, $y, $aspectRatio);
- }
-
- /**
- * @param int $x
- * @param int $y
- *
- * @return bool
- */
- private function unscalable($x, $y) {
-
- $maxX = $this->getMaxX();
- $maxY = $this->getMaxY();
- $scalingUp = $this->getScalingUp();
- $maxScaleFactor = $this->getMaxScaleFactor();
-
- if ($x < $maxX || $y < $maxY) {
- if ($scalingUp) {
- $scaleFactor = $maxX / $x;
- if ($scaleFactor > $maxScaleFactor) {
- return true;
- }
- } else {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns a preview of a file
- *
- * The cache is searched first and if nothing usable was found then a preview is
- * generated by one of the providers
- *
- * @return \OCP\IImage
- */
- public function getPreview() {
- if (!is_null($this->preview) && $this->preview->valid()) {
- return $this->preview;
- }
-
- $this->preview = null;
- $fileInfo = $this->getFileInfo();
- if ($fileInfo === null || $fileInfo === false || !$fileInfo->isReadable()) {
- return new \OC_Image();
- }
-
- $fileId = $fileInfo->getId();
- $cached = $this->isCached($fileId);
- if ($cached) {
- $this->getCachedPreview($fileId, $cached);
- }
-
- if (is_null($this->preview)) {
- $this->generatePreview($fileId);
- }
-
- // We still don't have a preview, so we send back an empty object
- if (is_null($this->preview)) {
- $this->preview = new \OC_Image();
- }
-
- return $this->preview;
- }
-
- /**
- * Sends the preview, including the headers to client which requested it
- *
- * @param null|string $mimeTypeForHeaders the media type to use when sending back the reply
- *
- * @throws NotFoundException
- * @throws PreviewNotAvailableException
- */
- public function showPreview($mimeTypeForHeaders = null) {
- // Check if file is valid
- if ($this->isFileValid() === false) {
- throw new NotFoundException('File not found.');
- }
-
- if (is_null($this->preview)) {
- $this->getPreview();
- }
- if ($this->preview instanceof \OCP\IImage) {
- if ($this->preview->valid()) {
- \OCP\Response::enableCaching(3600 * 24); // 24 hours
- } else {
- $this->getMimeIcon();
- }
- $this->preview->show($mimeTypeForHeaders);
- }
- }
-
- /**
- * Retrieves the preview from the cache and resizes it if necessary
- *
- * @param int $fileId fileId of the original image
- * @param string $cached the path to the cached preview
- */
- private function getCachedPreview($fileId, $cached) {
- $stream = $this->userView->fopen($cached, 'r');
- $this->preview = null;
- if ($stream) {
- $image = new \OC_Image();
- $image->loadFromFileHandle($stream);
-
- $this->preview = $image->valid() ? $image : null;
-
- if (!is_null($this->preview)) {
- // Size of the preview we calculated
- $maxX = $this->previewWidth;
- $maxY = $this->previewHeight;
- // Size of the preview we retrieved from the cache
- $previewX = (int)$this->preview->width();
- $previewY = (int)$this->preview->height();
-
- // We don't have an exact match
- if ($previewX !== $maxX || $previewY !== $maxY) {
- $this->resizeAndStore($fileId);
- }
- }
-
- fclose($stream);
- }
- }
-
- /**
- * Resizes, crops, fixes orientation and stores in the cache
- *
- * @param int $fileId fileId of the original image
- */
- private function resizeAndStore($fileId) {
- $image = $this->preview;
- if (!($image instanceof \OCP\IImage)) {
- \OCP\Util::writeLog(
- 'core', '$this->preview is not an instance of \OCP\IImage', \OCP\Util::DEBUG
- );
-
- return;
- }
- $previewWidth = (int)$image->width();
- $previewHeight = (int)$image->height();
- $askedWidth = $this->getMaxX();
- $askedHeight = $this->getMaxY();
-
- if ($this->mode === self::MODE_COVER) {
- list($askedWidth, $askedHeight) =
- $this->applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight);
- }
-
- /**
- * Phase 1: If required, adjust boundaries to keep aspect ratio
- */
- if ($this->keepAspect) {
- list($askedWidth, $askedHeight) =
- $this->applyAspectRatio($askedWidth, $askedHeight, $previewWidth, $previewHeight);
- }
-
- /**
- * Phase 2: Resizes preview to try and match requirements.
- * Takes the scaling ratio into consideration
- */
- list($newPreviewWidth, $newPreviewHeight) = $this->scale(
- $image, $askedWidth, $askedHeight, $previewWidth, $previewHeight
- );
-
- // The preview has been resized and should now have the asked dimensions
- if ($newPreviewWidth === $askedWidth && $newPreviewHeight === $askedHeight) {
- $this->storePreview($fileId, $newPreviewWidth, $newPreviewHeight);
-
- return;
- }
-
- /**
- * Phase 3: We're still not there yet, so we're clipping and filling
- * to match the asked dimensions
- */
- // It turns out the scaled preview is now too big, so we crop the image
- if ($newPreviewWidth >= $askedWidth && $newPreviewHeight >= $askedHeight) {
- $this->crop($image, $askedWidth, $askedHeight, $newPreviewWidth, $newPreviewHeight);
- $this->storePreview($fileId, $askedWidth, $askedHeight);
-
- return;
- }
-
- // At least one dimension of the scaled preview is too small,
- // so we fill the space with a transparent background
- if (($newPreviewWidth < $askedWidth || $newPreviewHeight < $askedHeight)) {
- $this->cropAndFill(
- $image, $askedWidth, $askedHeight, $newPreviewWidth, $newPreviewHeight
- );
- $this->storePreview($fileId, $askedWidth, $askedHeight);
-
- return;
- }
-
- // The preview is smaller, but we can't touch it
- $this->storePreview($fileId, $newPreviewWidth, $newPreviewHeight);
- }
-
- /**
- * Calculates the new dimensions of the preview
- *
- * The new dimensions can be larger or smaller than the ones of the preview we have to resize
- *
- * @param \OCP\IImage $image
- * @param int $askedWidth
- * @param int $askedHeight
- * @param int $previewWidth
- * @param int $previewHeight
- *
- * @return int[]
- */
- private function scale($image, $askedWidth, $askedHeight, $previewWidth, $previewHeight) {
- $scalingUp = $this->getScalingUp();
- $maxScaleFactor = $this->getMaxScaleFactor();
-
- $factorX = $askedWidth / $previewWidth;
- $factorY = $askedHeight / $previewHeight;
-
- if ($factorX >= $factorY) {
- $factor = $factorX;
- } else {
- $factor = $factorY;
- }
-
- if ($scalingUp === false) {
- if ($factor > 1) {
- $factor = 1;
- }
- }
-
- // We cap when upscaling
- if (!is_null($maxScaleFactor)) {
- if ($factor > $maxScaleFactor) {
- \OCP\Util::writeLog(
- 'core', 'scale factor reduced from ' . $factor . ' to ' . $maxScaleFactor,
- \OCP\Util::DEBUG
- );
- $factor = $maxScaleFactor;
- }
- }
-
- $newPreviewWidth = round($previewWidth * $factor);
- $newPreviewHeight = round($previewHeight * $factor);
-
- $image->preciseResize($newPreviewWidth, $newPreviewHeight);
- $this->preview = $image;
-
- return [$newPreviewWidth, $newPreviewHeight];
- }
-
- /**
- * Crops a preview which is larger than the dimensions we've received
- *
- * @param \OCP\IImage $image
- * @param int $askedWidth
- * @param int $askedHeight
- * @param int $previewWidth
- * @param int $previewHeight
- */
- private function crop($image, $askedWidth, $askedHeight, $previewWidth, $previewHeight = null) {
- $cropX = floor(abs($askedWidth - $previewWidth) * 0.5);
- //don't crop previews on the Y axis, this sucks if it's a document.
- //$cropY = floor(abs($y - $newPreviewHeight) * 0.5);
- $cropY = 0;
- $image->crop($cropX, $cropY, $askedWidth, $askedHeight);
- $this->preview = $image;
- }
-
- /**
- * Crops an image if it's larger than the dimensions we've received and fills the empty space
- * with a transparent background
- *
- * @param \OCP\IImage $image
- * @param int $askedWidth
- * @param int $askedHeight
- * @param int $previewWidth
- * @param int $previewHeight
- */
- private function cropAndFill($image, $askedWidth, $askedHeight, $previewWidth, $previewHeight) {
- if ($previewWidth > $askedWidth) {
- $cropX = floor(($previewWidth - $askedWidth) * 0.5);
- $image->crop($cropX, 0, $askedWidth, $previewHeight);
- $previewWidth = $askedWidth;
- }
-
- if ($previewHeight > $askedHeight) {
- $cropY = floor(($previewHeight - $askedHeight) * 0.5);
- $image->crop(0, $cropY, $previewWidth, $askedHeight);
- $previewHeight = $askedHeight;
- }
-
- // Creates a transparent background
- $backgroundLayer = imagecreatetruecolor($askedWidth, $askedHeight);
- imagealphablending($backgroundLayer, false);
- $transparency = imagecolorallocatealpha($backgroundLayer, 0, 0, 0, 127);
- imagefill($backgroundLayer, 0, 0, $transparency);
- imagesavealpha($backgroundLayer, true);
-
- $image = $image->resource();
-
- $mergeX = floor(abs($askedWidth - $previewWidth) * 0.5);
- $mergeY = floor(abs($askedHeight - $previewHeight) * 0.5);
-
- // Pastes the preview on top of the background
- imagecopy(
- $backgroundLayer, $image, $mergeX, $mergeY, 0, 0, $previewWidth,
- $previewHeight
- );
-
- $image = new \OC_Image($backgroundLayer);
-
- $this->preview = $image;
- }
-
- /**
- * Saves a preview in the cache to speed up future calls
- *
- * Do not nullify the preview as it might send the whole process in a loop
- *
- * @param int $fileId fileId of the original image
- * @param int $previewWidth
- * @param int $previewHeight
- */
- private function storePreview($fileId, $previewWidth, $previewHeight) {
- if (empty($previewWidth) || empty($previewHeight)) {
- \OCP\Util::writeLog(
- 'core', 'Cannot save preview of dimension ' . $previewWidth . 'x' . $previewHeight,
- \OCP\Util::DEBUG
- );
-
- } else {
- $cachePath = $this->buildCachePath($fileId, $previewWidth, $previewHeight);
- $this->userView->file_put_contents($cachePath, $this->preview->data());
- }
- }
-
- /**
- * Returns the path to a preview based on its dimensions and aspect
- *
- * @param int $fileId
- * @param int|null $maxX
- * @param int|null $maxY
- *
- * @return string
- */
- private function buildCachePath($fileId, $maxX = null, $maxY = null) {
- if (is_null($maxX)) {
- $maxX = $this->getMaxX();
- }
- if (is_null($maxY)) {
- $maxY = $this->getMaxY();
- }
-
- $previewPath = $this->getPreviewPath($fileId);
- $previewPath = $previewPath . strval($maxX) . '-' . strval($maxY);
- $isMaxPreview =
- ($maxX === $this->maxPreviewWidth && $maxY === $this->maxPreviewHeight) ? true : false;
- if ($isMaxPreview) {
- $previewPath .= '-max';
- }
- if ($this->keepAspect && !$isMaxPreview) {
- $previewPath .= '-with-aspect';
- }
- if ($this->mode === self::MODE_COVER) {
- $previewPath .= '-cover';
- }
- $previewPath .= '.png';
-
- return $previewPath;
- }
-
- /**
- * Returns the path to the folder where the previews are stored, identified by the fileId
- *
- * @param int $fileId
- *
- * @return string
- */
- private function getPreviewPath($fileId) {
- return $this->getThumbnailsFolder() . '/' . $fileId . '/';
- }
-
- /**
- * Asks the provider to send a preview of the file which respects the maximum dimensions
- * defined in the configuration and after saving it in the cache, it is then resized to the
- * asked dimensions
- *
- * This is only called once in order to generate a large PNG of dimensions defined in the
- * configuration file. We'll be able to quickly resize it later on.
- * We never upscale the original conversion as this will be done later by the resizing
- * operation
- *
- * @param int $fileId fileId of the original image
- */
- private function generatePreview($fileId) {
- $file = $this->getFile();
- $preview = null;
-
- $previewProviders = \OC::$server->getPreviewManager()
- ->getProviders();
- foreach ($previewProviders as $supportedMimeType => $providers) {
- if (!preg_match($supportedMimeType, $this->mimeType)) {
- continue;
- }
-
- foreach ($providers as $closure) {
- $provider = $closure();
- if (!($provider instanceof \OCP\Preview\IProvider)) {
- continue;
- }
-
- \OCP\Util::writeLog(
- 'core', 'Generating preview for "' . $file . '" with "' . get_class($provider)
- . '"', \OCP\Util::DEBUG
- );
-
- /** @var $provider Provider */
- $preview = $provider->getThumbnail(
- $file, $this->configMaxWidth, $this->configMaxHeight, $scalingUp = false,
- $this->fileView
- );
-
- if (!($preview instanceof \OCP\IImage)) {
- continue;
- }
-
- $this->preview = $preview;
- $previewPath = $this->getPreviewPath($fileId);
-
- if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) {
- $this->userView->mkdir($this->getThumbnailsFolder() . '/');
- }
-
- if ($this->userView->is_dir($previewPath) === false) {
- $this->userView->mkdir($previewPath);
- }
-
- // This stores our large preview so that it can be used in subsequent resizing requests
- $this->storeMaxPreview($previewPath);
-
- break 2;
- }
- }
-
- // The providers have been kind enough to give us a preview
- if ($preview) {
- $this->resizeAndStore($fileId);
- }
- }
-
- /**
- * Defines the media icon, for the media type of the original file, as the preview
- * @throws PreviewNotAvailableException
- */
- private function getMimeIcon() {
- $image = new \OC_Image();
- $mimeIconWebPath = \OC::$server->getMimeTypeDetector()->mimeTypeIcon($this->mimeType);
- if (empty(\OC::$WEBROOT)) {
- $mimeIconServerPath = \OC::$SERVERROOT . $mimeIconWebPath;
- } else {
- $mimeIconServerPath = str_replace(\OC::$WEBROOT, \OC::$SERVERROOT, $mimeIconWebPath);
- }
- // we can't load SVGs into an image
- if (substr($mimeIconWebPath, -4) === '.svg') {
- throw new PreviewNotAvailableException('SVG mimetype cannot be rendered');
- }
- $image->loadFromFile($mimeIconServerPath);
-
- $this->preview = $image;
- }
-
- /**
- * Stores the max preview in the cache
- *
- * @param string $previewPath path to the preview
- */
- private function storeMaxPreview($previewPath) {
- $maxPreviewExists = false;
- $preview = $this->preview;
-
- $allThumbnails = $this->userView->getDirectoryContent($previewPath);
- // This is so that the cache doesn't need emptying when upgrading
- // Can be replaced by an upgrade script...
- foreach ($allThumbnails as $thumbnail) {
- $name = rtrim($thumbnail['name'], '.png');
- if (strpos($name, 'max')) {
- $maxPreviewExists = true;
- break;
- }
- }
- // We haven't found the max preview, so we create it
- if (!$maxPreviewExists) {
- $previewWidth = $preview->width();
- $previewHeight = $preview->height();
- $previewPath = $previewPath . strval($previewWidth) . '-' . strval($previewHeight);
- $previewPath .= '-max.png';
- $this->userView->file_put_contents($previewPath, $preview->data());
- $this->maxPreviewWidth = $previewWidth;
- $this->maxPreviewHeight = $previewHeight;
- }
- }
-
- /**
- * Limits a dimension to the maximum dimension provided as argument
- *
- * @param int $dim
- * @param int $maxDim
- * @param string $dimName
- *
- * @return integer
- */
- private function limitMaxDim($dim, $maxDim, $dimName) {
- if (!is_null($maxDim)) {
- if ($dim > $maxDim) {
- \OCP\Util::writeLog(
- 'core', $dimName . ' reduced from ' . $dim . ' to ' . $maxDim, \OCP\Util::DEBUG
- );
- $dim = $maxDim;
- }
- }
-
- return $dim;
- }
-
- /**
- * @param array $args
- */
- public static function post_write($args) {
- self::post_delete($args, 'files/');
- }
-
- /**
- * @param array $args
- */
- public static function prepare_delete_files($args) {
- self::prepare_delete($args, 'files/');
- }
-
- /**
- * @param array $args
- * @param string $prefix
- */
- public static function prepare_delete(array $args, $prefix = '') {
- $path = $args['path'];
- if (substr($path, 0, 1) === '/') {
- $path = substr($path, 1);
- }
-
- $view = new \OC\Files\View('/' . \OC_User::getUser() . '/' . $prefix);
-
- $absPath = Files\Filesystem::normalizePath($view->getAbsolutePath($path));
- $fileInfo = $view->getFileInfo($path);
- if ($fileInfo === false) {
- return;
- }
- self::addPathToDeleteFileMapper($absPath, $fileInfo);
- if ($view->is_dir($path)) {
- $children = self::getAllChildren($view, $path);
- self::$deleteChildrenMapper[$absPath] = $children;
- }
- }
-
- /**
- * @param string $absolutePath
- * @param \OCP\Files\FileInfo $info
- */
- private static function addPathToDeleteFileMapper($absolutePath, $info) {
- self::$deleteFileMapper[$absolutePath] = $info;
- }
-
- /**
- * @param \OC\Files\View $view
- * @param string $path
- *
- * @return array
- */
- private static function getAllChildren($view, $path) {
- $children = $view->getDirectoryContent($path);
- $childrensFiles = array();
-
- $fakeRootLength = strlen($view->getRoot());
-
- for ($i = 0; $i < count($children); $i++) {
- $child = $children[$i];
-
- $childsPath = substr($child->getPath(), $fakeRootLength);
-
- if ($view->is_dir($childsPath)) {
- $children = array_merge(
- $children,
- $view->getDirectoryContent($childsPath)
- );
- } else {
- $childrensFiles[] = $child;
- }
- }
-
- return $childrensFiles;
- }
-
- /**
- * @param array $args
- */
- public static function post_delete_files($args) {
- self::post_delete($args, 'files/');
- }
-
- /**
- * @param array $args
- */
- public static function post_delete_versions($args) {
- self::post_delete($args, 'files/');
- }
-
- /**
- * @param array $args
- * @param string $prefix
- */
- public static function post_delete($args, $prefix = '') {
- $path = Files\Filesystem::normalizePath($args['path']);
-
- $preview = new Preview(\OC_User::getUser(), $prefix, $path);
- $preview->deleteAllPreviews();
- }
-
-}
diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php
index 36b3730a720..8c5a7ad29f1 100644
--- a/lib/private/PreviewManager.php
+++ b/lib/private/PreviewManager.php
@@ -68,6 +68,9 @@ class PreviewManager implements IPreview {
/** @var array */
protected $defaultProviders;
+ /** @var string */
+ protected $userId;
+
/**
* PreviewManager constructor.
*
@@ -75,15 +78,18 @@ class PreviewManager implements IPreview {
* @param IRootFolder $rootFolder
* @param IAppData $appData
* @param EventDispatcherInterface $eventDispatcher
+ * @param string $userId
*/
public function __construct(IConfig $config,
IRootFolder $rootFolder,
IAppData $appData,
- EventDispatcherInterface $eventDispatcher) {
+ EventDispatcherInterface $eventDispatcher,
+ $userId) {
$this->config = $config;
$this->rootFolder = $rootFolder;
$this->appData = $appData;
$this->eventDispatcher = $eventDispatcher;
+ $this->userId = $userId;
}
/**
@@ -144,10 +150,22 @@ class PreviewManager implements IPreview {
* @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
* @param boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
* @return \OCP\IImage
+ * @deprecated 11 Use getPreview
*/
public function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false) {
- $preview = new \OC\Preview('', '/', $file, $maxX, $maxY, $scaleUp);
- return $preview->getPreview();
+ try {
+ $userRoot = $this->rootFolder->getUserFolder($this->userId)->getParent();
+ $node = $userRoot->get($file);
+ if (!($file instanceof File)) {
+ throw new NotFoundException();
+ }
+
+ $preview = $this->getPreview($node, $maxX, $maxY);
+ } catch (\Exception $e) {
+ return new \OC_Image();
+ }
+
+ return new \OC_Image($preview->getContent());
}
/**
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 147fa89582a..6888c492910 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -124,7 +124,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->getConfig(),
$c->getRootFolder(),
$c->getAppDataDir('preview'),
- $c->getEventDispatcher()
+ $c->getEventDispatcher(),
+ $c->getSession()->get('user_id')
);
});
diff --git a/lib/public/IPreview.php b/lib/public/IPreview.php
index a1a03fee3e1..207539b1170 100644
--- a/lib/public/IPreview.php
+++ b/lib/public/IPreview.php
@@ -86,7 +86,7 @@ interface IPreview {
* @param boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
* @return \OCP\IImage
* @since 6.0.0
- * @deprecated 9.2.0 Use getPreview
+ * @deprecated 11 Use getPreview
*/
public function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false);