diff options
author | Vincent Petry <pvince81@owncloud.com> | 2014-03-10 16:04:47 +0100 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2014-03-10 16:04:47 +0100 |
commit | 4fdf7682c9d3a7f8f481712ee747cc10989c11d6 (patch) | |
tree | 07e7353de8d64dded35ce816c9e620b1f231d12a | |
parent | 3c5185edab2352ce0d825870ce2b4964a28a777b (diff) | |
parent | 5ddabd7cd02108718b286b36de5927d90afc150a (diff) | |
download | nextcloud-server-4fdf7682c9d3a7f8f481712ee747cc10989c11d6.tar.gz nextcloud-server-4fdf7682c9d3a7f8f481712ee747cc10989c11d6.zip |
Merge pull request #7398 from owncloud/trash_dont_rely_on_db
[trash] fall back if file is not in db
-rw-r--r-- | apps/files_trashbin/ajax/list.php | 6 | ||||
-rw-r--r-- | apps/files_trashbin/appinfo/database.xml | 4 | ||||
-rw-r--r-- | apps/files_trashbin/appinfo/update.php | 2 | ||||
-rw-r--r-- | apps/files_trashbin/appinfo/version | 2 | ||||
-rw-r--r-- | apps/files_trashbin/index.php | 13 | ||||
-rw-r--r-- | apps/files_trashbin/lib/helper.php | 62 | ||||
-rw-r--r-- | apps/files_trashbin/lib/trashbin.php | 139 | ||||
-rw-r--r-- | lib/private/files/cache/homecache.php | 2 |
8 files changed, 79 insertions, 151 deletions
diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php index c9dc13b7840..124a236bcbd 100644 --- a/apps/files_trashbin/ajax/list.php +++ b/apps/files_trashbin/ajax/list.php @@ -26,9 +26,9 @@ if($doBreadcrumb) { } // make filelist -$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); - -if ($files === null){ +try { + $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); +} catch (Exception $e) { header("HTTP/1.0 404 Not Found"); exit(); } diff --git a/apps/files_trashbin/appinfo/database.xml b/apps/files_trashbin/appinfo/database.xml index d08c3469b02..db104ee9298 100644 --- a/apps/files_trashbin/appinfo/database.xml +++ b/apps/files_trashbin/appinfo/database.xml @@ -49,7 +49,7 @@ <name>type</name> <type>text</type> <default></default> - <notnull>true</notnull> + <notnull>false</notnull> <length>4</length> </field> @@ -57,7 +57,7 @@ <name>mime</name> <type>text</type> <default></default> - <notnull>true</notnull> + <notnull>false</notnull> <length>255</length> </field> diff --git a/apps/files_trashbin/appinfo/update.php b/apps/files_trashbin/appinfo/update.php index 0ca232668d7..ca7b87a8681 100644 --- a/apps/files_trashbin/appinfo/update.php +++ b/apps/files_trashbin/appinfo/update.php @@ -2,7 +2,7 @@ $installedVersion=OCP\Config::getAppValue('files_trashbin', 'installed_version'); -if (version_compare($installedVersion, '0.4', '<')) { +if (version_compare($installedVersion, '0.6', '<')) { //size of the trash bin could be incorrect, remove it for all users to //enforce a recalculation during next usage. $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trashsize`'); diff --git a/apps/files_trashbin/appinfo/version b/apps/files_trashbin/appinfo/version index 2eb3c4fe4ee..5a2a5806df6 100644 --- a/apps/files_trashbin/appinfo/version +++ b/apps/files_trashbin/appinfo/version @@ -1 +1 @@ -0.5 +0.6 diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php index 93f385dd30b..f0c5b0508b8 100644 --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@ -37,19 +37,18 @@ if ($isIE8 && isset($_GET['dir'])){ $ajaxLoad = false; if (!$isIE8){ - $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); + try { + $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); + } catch (Exception $e) { + header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php')); + exit(); + } } else{ $files = array(); $ajaxLoad = true; } -// Redirect if directory does not exist -if ($files === null){ - header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php')); - exit(); -} - $dirlisting = false; if ($dir && $dir !== '/') { $dirlisting = true; diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php index c454b35a5f2..fe0d1d30a72 100644 --- a/apps/files_trashbin/lib/helper.php +++ b/apps/files_trashbin/lib/helper.php @@ -12,35 +12,42 @@ class Helper */ public static function getTrashFiles($dir){ $result = array(); + $timestamp = null; $user = \OCP\User::getUser(); - if ($dir && $dir !== '/') { - $view = new \OC_Filesystemview('/'.$user.'/files_trashbin/files'); - $dirContent = $view->opendir($dir); - if ($dirContent === false){ - return null; - } - if(is_resource($dirContent)){ - while(($entryName = readdir($dirContent)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { - $pos = strpos($dir.'/', '/', 1); - $tmp = substr($dir, 0, $pos); - $pos = strrpos($tmp, '.d'); - $timestamp = substr($tmp, $pos+2); - $result[] = array( - 'id' => $entryName, - 'timestamp' => $timestamp, - 'mime' => $view->getMimeType($dir.'/'.$entryName), - 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', - 'location' => $dir, - ); + $view = new \OC_Filesystemview('/' . $user . '/files_trashbin/files'); + + if (ltrim($dir, '/') !== '' && !$view->is_dir($dir)) { + throw new \Exception('Directory does not exists'); + } + + $dirContent = $view->opendir($dir); + if ($dirContent === false) { + return $result; + } + if (is_resource($dirContent)) { + while (($entryName = readdir($dirContent)) !== false) { + if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { + $id = $entryName; + if ($dir === '' || $dir === '/') { + $pathparts = pathinfo($entryName); + $timestamp = substr($pathparts['extension'], 1); + $id = $pathparts['filename']; + } else if ($timestamp === null) { + // for subfolders we need to calculate the timestamp only once + $parts = explode('/', ltrim($dir, '/')); + $timestamp = substr(pathinfo($parts[0], PATHINFO_EXTENSION), 1); } + $result[] = array( + 'id' => $id, + 'timestamp' => $timestamp, + 'mime' => \OC_Helper::getFileNameMimeType($id), + 'type' => $view->is_dir($dir . '/' . $entryName) ? 'dir' : 'file', + 'location' => $dir, + ); } - closedir($dirContent); } - } else { - $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); - $result = $query->execute(array($user))->fetchAll(); + closedir($dirContent); } $files = array(); @@ -51,6 +58,7 @@ class Helper $i['name'] = $r['id']; $i['date'] = \OCP\Util::formatDate($r['timestamp']); $i['timestamp'] = $r['timestamp']; + $i['etag'] = $r['timestamp']; // add fake etag, it is only needed to identify the preview image $i['mimetype'] = $r['mime']; $i['type'] = $r['type']; if ($i['type'] === 'file') { @@ -63,7 +71,11 @@ class Helper $i['directory'] = ''; } $i['permissions'] = \OCP\PERMISSION_READ; - $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($r['mime']); + if (\OCP\App::isEnabled('files_encryption')) { + $i['isPreviewAvailable'] = false; + } else { + $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($r['mime']); + } $i['icon'] = \OCA\Files\Helper::determineIcon($i); $files[] = $i; } diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index bc77e9c1543..f6816b2b4c2 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -62,11 +62,13 @@ class Trashbin { /** + * @brief copy file to owners trash + * @param string $sourcePath * @param string $owner + * @param string $ownerPath * @param integer $timestamp - * @param string $type */ - private static function copyFilesToOwner($sourcePath, $owner, $ownerPath, $timestamp, $type, $mime) { + private static function copyFilesToOwner($sourcePath, $owner, $ownerPath, $timestamp) { self::setUpTrash($owner); $ownerFilename = basename($ownerPath); @@ -82,12 +84,10 @@ class Trashbin { if ($view->file_exists($target)) { - $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`type`,`mime`,`user`) VALUES (?,?,?,?,?,?)"); - $result = $query->execute(array($ownerFilename, $timestamp, $ownerLocation, $type, $mime, $owner)); - if (!$result) { // if file couldn't be added to the database than also don't store it in the trash bin. - $view->deleteAll($owner.'/files_trashbin/files/' . $ownerFilename . '.d' . $timestamp); + $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)"); + $result = $query->execute(array($ownerFilename, $timestamp, $ownerLocation, $owner)); + if (!$result) { \OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated for the files owner', \OC_log::ERROR); - return; } } } @@ -110,18 +110,8 @@ class Trashbin { $filename = $path_parts['basename']; $location = $path_parts['dirname']; $timestamp = time(); - $mime = $view->getMimeType('files' . $file_path); - - if ($view->is_dir('files' . $file_path)) { - $type = 'dir'; - } else { - $type = 'file'; - } $userTrashSize = self::getTrashbinSize($user); - if ($userTrashSize === false || $userTrashSize < 0) { - $userTrashSize = self::calculateSize(new \OC\Files\View('/' . $user . '/files_trashbin')); - } // disable proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -132,12 +122,10 @@ class Trashbin { if ($view->file_exists('files_trashbin/files/' . $filename . '.d' . $timestamp)) { $size = $sizeOfAddedFiles; - $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`type`,`mime`,`user`) VALUES (?,?,?,?,?,?)"); - $result = $query->execute(array($filename, $timestamp, $location, $type, $mime, $user)); - if (!$result) { // if file couldn't be added to the database than also don't store it in the trash bin. - $view->deleteAll('files_trashbin/files/' . $filename . '.d' . $timestamp); + $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)"); + $result = $query->execute(array($filename, $timestamp, $location, $user)); + if (!$result) { \OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR); - return; } \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', array('filePath' => \OC\Files\Filesystem::normalizePath($file_path), 'trashPath' => \OC\Files\Filesystem::normalizePath($filename . '.d' . $timestamp))); @@ -147,7 +135,7 @@ class Trashbin { // if owner !== user we need to also add a copy to the owners trash if ($user !== $owner) { - self::copyFilesToOwner($file_path, $owner, $ownerPath, $timestamp, $type, $mime); + self::copyFilesToOwner($file_path, $owner, $ownerPath, $timestamp); } } else { \OC_Log::write('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OC_log::ERROR); @@ -155,17 +143,12 @@ class Trashbin { $userTrashSize += $size; $userTrashSize -= self::expire($userTrashSize, $user); - self::setTrashbinSize($user, $userTrashSize); // if owner !== user we also need to update the owners trash size if($owner !== $user) { $ownerTrashSize = self::getTrashbinSize($owner); - if ($ownerTrashSize === false || $ownerTrashSize < 0) { - $ownerTrashSize = self::calculateSize(new \OC\Files\View('/' . $owner . '/files_trashbin')); - } $ownerTrashSize += $size; $ownerTrashSize -= self::expire($ownerTrashSize, $owner); - self::setTrashbinSize($owner, $ownerTrashSize); } } @@ -326,33 +309,22 @@ class Trashbin { $user = \OCP\User::getUser(); $view = new \OC\Files\View('/' . $user); - $trashbinSize = self::getTrashbinSize($user); - if ($trashbinSize === false || $trashbinSize < 0) { - $trashbinSize = self::calculateSize(new \OC\Files\View('/' . $user . '/files_trashbin')); - } + $location = ''; if ($timestamp) { - $query = \OC_DB::prepare('SELECT `location`,`type` FROM `*PREFIX*files_trash`' - . ' WHERE `user`=? AND `id`=? AND `timestamp`=?'); + $query = \OC_DB::prepare('SELECT `location` FROM `*PREFIX*files_trash`' + . ' WHERE `user`=? AND `id`=? AND `timestamp`=?'); $result = $query->execute(array($user, $filename, $timestamp))->fetchAll(); if (count($result) !== 1) { \OC_Log::write('files_trashbin', 'trash bin database inconsistent!', \OC_Log::ERROR); - return false; - } - - // if location no longer exists, restore file in the root directory - $location = $result[0]['location']; - if ($result[0]['location'] !== '/' && - (!$view->is_dir('files' . $result[0]['location']) || - !$view->isUpdatable('files' . $result[0]['location']))) { - $location = ''; + } else { + $location = $result[0]['location']; + // if location no longer exists, restore file in the root directory + if ($location !== '/' && + (!$view->is_dir('files' . $location) || + !$view->isUpdatable('files' . $location))) { + $location = ''; + } } - } else { - $path_parts = pathinfo($file); - $result[] = array( - 'location' => $path_parts['dirname'], - 'type' => $view->is_dir('/files_trashbin/files/' . $file) ? 'dir' : 'files', - ); - $location = ''; } // we need a extension in case a file/dir with the same name already exists @@ -377,22 +349,15 @@ class Trashbin { $view->chroot($fakeRoot); \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', array('filePath' => \OC\Files\Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename), 'trashPath' => \OC\Files\Filesystem::normalizePath($file))); - if ($view->is_dir($target)) { - $trashbinSize -= self::calculateSize(new \OC\Files\View('/' . $user . '/' . $target)); - } else { - $trashbinSize -= $view->filesize($target); - } - $trashbinSize -= self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp); - $trashbinSize -= self::restoreEncryptionKeys($view, $file, $filename, $uniqueFilename, $location, $timestamp); + self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp); + self::restoreEncryptionKeys($view, $file, $filename, $uniqueFilename, $location, $timestamp); if ($timestamp) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?'); $query->execute(array($user, $filename, $timestamp)); } - self::setTrashbinSize($user, $trashbinSize); - // enable proxy \OC_FileProxy::$enabled = $proxyStatus; @@ -415,10 +380,8 @@ class Trashbin { * @param $location location if file * @param $timestamp deleteion time * - * @return size of restored versions */ private static function restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp) { - $size = 0; if (\OCP\App::isEnabled('files_versions')) { // disable proxy to prevent recursive calls @@ -439,15 +402,12 @@ class Trashbin { } if ($view->is_dir('/files_trashbin/versions/' . $file)) { - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . 'files_trashbin/versions/' . $file)); $rootView->rename(\OC\Files\Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath)); } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp)) { foreach ($versions as $v) { if ($timestamp) { - $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp); $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v); } else { - $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v); $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v); } } @@ -456,7 +416,6 @@ class Trashbin { // enable proxy \OC_FileProxy::$enabled = $proxyStatus; } - return $size; } /** @@ -469,11 +428,9 @@ class Trashbin { * @param $location location of file * @param $timestamp deleteion time * - * @return size of restored encrypted file */ private static function restoreEncryptionKeys($view, $file, $filename, $uniqueFilename, $location, $timestamp) { // Take care of encryption keys TODO! Get '.key' in file between file name and delete date (also for permanent delete!) - $size = 0; if (\OCP\App::isEnabled('files_encryption')) { $user = \OCP\User::getUser(); $rootView = new \OC\Files\View('/'); @@ -518,18 +475,15 @@ class Trashbin { if ($rootView->is_dir($keyfile)) { // handle keyfiles - $size += self::calculateSize(new \OC\Files\View($keyfile)); $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath); // handle share-keys if ($timestamp) { $sharekey .= '.d' . $timestamp; } - $size += self::calculateSize(new \OC\Files\View($sharekey)); $rootView->rename($sharekey, $baseDir . '/share-keys/' . $ownerPath); } else { // handle keyfiles - $size += $rootView->filesize($keyfile); $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath . '.key'); // handle share-keys @@ -538,8 +492,6 @@ class Trashbin { $ownerShareKey .= '.d' . $timestamp; } - $size += $rootView->filesize($ownerShareKey); - // move only owners key $rootView->rename($ownerShareKey, $baseDir . '/share-keys/' . $ownerPath . '.' . $user . '.shareKey'); @@ -566,7 +518,6 @@ class Trashbin { // enable proxy \OC_FileProxy::$enabled = $proxyStatus; } - return $size; } /** @@ -576,7 +527,6 @@ class Trashbin { $user = \OCP\User::getUser(); $view = new \OC\Files\View('/' . $user); $view->deleteAll('files_trashbin'); - self::setTrashbinSize($user, 0); $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?'); $query->execute(array($user)); @@ -597,11 +547,6 @@ class Trashbin { $view = new \OC\Files\View('/' . $user); $size = 0; - $trashbinSize = self::getTrashbinSize($user); - if ($trashbinSize === false || $trashbinSize < 0) { - $trashbinSize = self::calculateSize(new \OC\Files\View('/' . $user . '/files_trashbin')); - } - if ($timestamp) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?'); $query->execute(array($user, $filename, $timestamp)); @@ -620,8 +565,6 @@ class Trashbin { } $view->unlink('/files_trashbin/files/' . $file); \OC_Hook::emit('\OCP\Trashbin', 'delete', array('path' => '/files_trashbin/files/' . $file)); - $trashbinSize -= $size; - self::setTrashbinSize($user, $trashbinSize); return $size; } @@ -767,17 +710,10 @@ class Trashbin { $size = self::getTrashbinSize($user); - if ($size === false || $size < 0) { - $size = self::calculateSize(new \OC\Files\View('/' . $user . '/files_trashbin')); - } - $freeSpace = self::calculateFreeSpace($size); if ($freeSpace < 0) { - $newSize = $size - self::expire($size, $user); - if ($newSize !== $size) { - self::setTrashbinSize($user, $newSize); - } + self::expire($size, $user); } } @@ -954,28 +890,9 @@ class Trashbin { * @return mixed trash bin size or false if no trash bin size is stored */ private static function getTrashbinSize($user) { - $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*files_trashsize` WHERE `user`=?'); - $result = $query->execute(array($user))->fetchAll(); - - if ($result) { - return (int)$result[0]['size']; - } - return false; - } - - /** - * write to the database how much space is in use for the trash bin - * - * @param $user owner of the trash bin - * @param $size size of the trash bin - */ - private static function setTrashbinSize($user, $size) { - if (self::getTrashbinSize($user) === false) { - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*files_trashsize` (`size`, `user`) VALUES (?, ?)'); - } else { - $query = \OC_DB::prepare('UPDATE `*PREFIX*files_trashsize` SET `size`=? WHERE `user`=?'); - } - $query->execute(array($size, $user)); + $view = new \OC\Files\View('/' . $user); + $fileInfo = $view->getFileInfo('/files_trashbin'); + return $fileInfo['size']; } /** diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php index 2af5b03c6e1..82f31d0867d 100644 --- a/lib/private/files/cache/homecache.php +++ b/lib/private/files/cache/homecache.php @@ -16,7 +16,7 @@ class HomeCache extends Cache { * @return int */ public function calculateFolderSize($path) { - if ($path !== '/' and $path !== '' and $path !== 'files') { + if ($path !== '/' and $path !== '' and $path !== 'files' and $path !== 'files_trashbin') { return parent::calculateFolderSize($path); } |