From: Robin Appelman Date: Wed, 27 Feb 2013 19:29:19 +0000 (+0100) Subject: Merge master into trash_fileactions X-Git-Tag: v5.0.0RC1~8^2~4 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=429bf42e986c27a974571c474590840f304f7e08;p=nextcloud-server.git Merge master into trash_fileactions --- 429bf42e986c27a974571c474590840f304f7e08 diff --cc apps/files_trashbin/index.php index a4eb5cd216c,2f1fb32f8ce..31b46cc2dec --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@@ -39,11 -37,11 +39,11 @@@ if ($dir) ); } } - closedir($fullpath); - + closedir($dirContent); + } else { $dirlisting = false; -- $query = \OC_DB::prepare('SELECT id,location,timestamp,type,mime FROM *PREFIX*files_trash WHERE user=?'); ++ $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE user = ?'); $result = $query->execute(array($user))->fetchAll(); } @@@ -68,21 -66,9 +68,21 @@@ foreach ($result as $r) $files[] = $i; } +function fileCmp($a, $b) { + if ($a['type'] == 'dir' and $b['type'] != 'dir') { + return -1; + } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { + return 1; + } else { + return strnatcasecmp($a['name'], $b['name']); + } +} + +usort($files, "fileCmp"); + // Make breadcrumb - $breadcrumb = array(array('dir' => '', 'name' => 'Trash')); $pathtohere = ''; + $breadcrumb = array(); foreach (explode('/', $dir) as $i) { if ($i != '') { if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { @@@ -107,8 -93,9 +107,9 @@@ $list->assign('disableSharing', true) $list->assign('dirlisting', $dirlisting); $list->assign('disableDownloadActions', true); $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); ++$tmpl->assign('dirlisting', $dirlisting); $tmpl->assign('fileList', $list->fetchPage(), false); $tmpl->assign('files', $files); -$tmpl->assign('dirlisting', $dirlisting); -$tmpl->assign('dir', OC_Filesystem::normalizePath($view->getAbsolutePath())); +$tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($view->getAbsolutePath())); $tmpl->printPage(); diff --cc apps/files_trashbin/js/trash.js index c3429e7a838,7769def535e..9526859ad00 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@@ -114,23 -116,31 +116,48 @@@ $(document).ready(function() }); }); + $('.delete').click('click',function(event) { + console.log("delete selected"); + var spinner = ''; + var files=getSelectedFiles('file'); + var fileslist = JSON.stringify(files); + var dirlisting=getSelectedFiles('dirlisting')[0]; + + for (var i=0; ifile_exists('files_trashbin/'.$deleted.'.d'.$timestamp) ) { + $trashbinSize = self::getTrashbinSize($user); + if ( $trashbinSize === false || $trashbinSize < 0 ) { - $trashbinSize = self::calculateSize(new \OC_FilesystemView('/'. $user.'/files_trashbin')); ++ $trashbinSize = self::calculateSize(new \OC\Files\View('/'. $user.'/files_trashbin')); + } + $trashbinSize += self::copy_recursive($file_path, 'files_trashbin/files/'.$deleted.'.d'.$timestamp, $view); + + if ( $view->file_exists('files_trashbin/files/'.$deleted.'.d'.$timestamp) ) { $query = \OC_DB::prepare("INSERT INTO *PREFIX*files_trash (id,timestamp,location,type,mime,user) VALUES (?,?,?,?,?,?)"); $result = $query->execute(array($deleted, $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. @@@ -61,37 -71,78 +71,78 @@@ \OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR); return; } - + + // Take care of file versions if ( \OCP\App::isEnabled('files_versions') ) { if ( $view->is_dir('files_versions'.$file_path) ) { - $view->rename('files_versions'.$file_path, 'versions_trashbin/'. $deleted.'.d'.$timestamp); - } else if ( $versions = \OCA\Files_Versions\Storage::getVersions($file_path) ) { - $trashbinSize += self::calculateSize(new \OC_FilesystemView('/'. $user.'/files_versions/'.$file_path)); ++ $trashbinSize += self::calculateSize(new \OC\Files\View('/'. $user.'/files_versions/'.$file_path)); + $view->rename('files_versions'.$file_path, 'files_trashbin/versions'. $deleted.'.d'.$timestamp); + } else if ( $versions = \OCA\Files_Versions\Storage::getVersions($user, $file_path) ) { foreach ($versions as $v) { - $view->rename('files_versions'.$v['path'].'.v'.$v['version'], 'versions_trashbin/'. $deleted.'.v'.$v['version'].'.d'.$timestamp); + $trashbinSize += $view->filesize('files_versions'.$v['path'].'.v'.$v['version']); + $view->rename('files_versions'.$v['path'].'.v'.$v['version'], 'files_trashbin/versions'. $deleted.'.v'.$v['version'].'.d'.$timestamp); } } } + + // Take care of encryption keys - $keyfile = \OC_Filesystem::normalizePath('files_encryption/keyfiles/'.$file_path); ++ $keyfile = \OC\Files\Filesystem::normalizePath('files_encryption/keyfiles/'.$file_path); + if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile.'.key') ) { + if ( $view->is_dir('files'.$file_path) ) { - $trashbinSize += self::calculateSize(new \OC_FilesystemView('/'.$user.'/'.$keyfile)); ++ $trashbinSize += self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile)); + $view->rename($keyfile, 'files_trashbin/keyfiles/'. $deleted.'.d'.$timestamp); + } else { + $trashbinSize += $view->filesize($keyfile.'.key'); + $view->rename($keyfile.'.key', 'files_trashbin/keyfiles/'. $deleted.'.key.d'.$timestamp); + } + } + } else { + \OC_Log::write('files_trashbin', 'Couldn\'t move '.$file_path.' to the trash bin', \OC_log::ERROR); + } + + // get available disk space for user + $quota = \OC_Preferences::getValue($user, 'files', 'quota'); + if ( $quota === null ) { + $quota = \OC_Appconfig::getValue('files', 'default_quota'); + } + if ( $quota === null ) { + $quota = \OC\Files\Filesystem::free_space('/') / count(\OCP\User::getUsers()); } else { - \OC_Log::write('files_trashbin', 'Couldn\'t move '.$file_path.' to the trash bin' , \OC_log::ERROR); + $quota = \OCP\Util::computerFileSize($quota); } - self::expire(); + // calculate available space for trash bin + $rootInfo = $view->getFileInfo('/files'); + $free = $quota-$rootInfo['size']; // remaining free space for user + if ( $free > 0 ) { + $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions + } else { + $availableSpace = $free-$trashbinSize; + } + $trashbinSize -= self::expire($availableSpace); + + self::setTrashbinSize($user, $trashbinSize); + } - - + + /** * restore files from trash bin - * @param string $file path to the deleted file - * @param string $filename name of the file - * @param int $timestamp time when the file was deleted + * @param $file path to the deleted file + * @param $filename name of the file + * @param $timestamp time when the file was deleted */ public static function restore($file, $filename, $timestamp) { - $user = \OCP\User::getUser(); - $view = new \OC_FilesystemView('/'.$user); + $view = new \OC\Files\View('/'.$user); + $trashbinSize = self::getTrashbinSize($user); + if ( $trashbinSize === false || $trashbinSize < 0 ) { - $trashbinSize = self::calculateSize(new \OC_FilesystemView('/'. $user.'/files_trashbin')); ++ $trashbinSize = self::calculateSize(new \OC\Files\View('/'. $user.'/files_trashbin')); + } 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,type 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); @@@ -114,29 -165,62 +165,62 @@@ $location = ''; } - $source = \OC\Files\Filesystem::normalizePath('files_trashbin/'.$file); - $source = \OC_Filesystem::normalizePath('files_trashbin/files/'.$file); - $target = \OC_Filesystem::normalizePath('files/'.$location.'/'.$filename); ++ $source = \OC\Files\Filesystem::normalizePath('files_trashbin/files/'.$file); + $target = \OC\Files\Filesystem::normalizePath('files/'.$location.'/'.$filename); - + // we need a extension in case a file/dir with the same name already exists $ext = self::getUniqueExtension($location, $filename, $view); $mtime = $view->filemtime($source); if( $view->rename($source, $target.$ext) ) { $view->touch($target.$ext, $mtime); + if ($view->is_dir($target.$ext)) { - $trashbinSize -= self::calculateSize(new \OC_FilesystemView('/'.$user.'/'.$target.$ext)); ++ $trashbinSize -= self::calculateSize(new \OC\Files\View('/'.$user.'/'.$target.$ext)); + } else { + $trashbinSize -= $view->filesize($target.$ext); + } // if versioning app is enabled, copy versions from the trash bin back to the original location if ( \OCP\App::isEnabled('files_versions') ) { - if ( $result[0]['type'] == 'dir' ) { - $view->rename(\OC\Files\Filesystem::normalizePath('versions_trashbin/'. $file), \OC\Files\Filesystem::normalizePath('files_versions/'.$location.'/'.$filename.$ext)); - } else if ( $versions = self::getVersionsFromTrash($file, $timestamp) ) { + if ($timestamp ) { + $versionedFile = $filename; + } else { + $versionedFile = $file; + } + if ( $result[0]['type'] === 'dir' ) { - $trashbinSize -= self::calculateSize(new \OC_FilesystemView('/'.$user.'/'.'files_trashbin/versions/'. $file)); - $view->rename(\OC_Filesystem::normalizePath('files_trashbin/versions/'. $file), \OC_Filesystem::normalizePath('files_versions/'.$location.'/'.$filename.$ext)); ++ $trashbinSize -= self::calculateSize(new \OC\Files\View('/'.$user.'/'.'files_trashbin/versions/'. $file)); ++ $view->rename(\OC\Files\Filesystem::normalizePath('files_trashbin/versions/'. $file), \OC\Files\Filesystem::normalizePath('files_versions/'.$location.'/'.$filename.$ext)); + } else if ( $versions = self::getVersionsFromTrash($versionedFile, $timestamp) ) { foreach ($versions as $v) { if ($timestamp ) { - $view->rename('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + $trashbinSize -= $view->filesize('files_trashbin/versions/'.$versionedFile.'.v'.$v.'.d'.$timestamp); + $view->rename('files_trashbin/versions/'.$versionedFile.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); } else { - $view->rename('versions_trashbin/'.$file.'.v'.$v, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + $trashbinSize -= $view->filesize('files_trashbin/versions/'.$versionedFile.'.v'.$v); + $view->rename('files_trashbin/versions/'.$versionedFile.'.v'.$v, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); } } } } - + + // Take care of encryption keys TODO! Get '.key' in file between file name and delete date (also for permanent delete!) + $parts = pathinfo($file); + if ( $result[0]['type'] === 'dir' ) { - $keyfile = \OC_Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename); ++ $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename); + } else { - $keyfile = \OC_Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename.'.key'); ++ $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename.'.key'); + } + if ($timestamp) { + $keyfile .= '.d'.$timestamp; + } + if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile) ) { + if ( $result[0]['type'] === 'dir' ) { - $trashbinSize -= self::calculateSize(new \OC_FilesystemView('/'.$user.'/'.$keyfile)); ++ $trashbinSize -= self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile)); + $view->rename($keyfile, 'files_encryption/keyfiles/'. $location.'/'.$filename); + } else { + $trashbinSize -= $view->filesize($keyfile); + $view->rename($keyfile, 'files_encryption/keyfiles/'. $location.'/'.$filename.'.key'); + } + } + if ( $timestamp ) { $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?'); $query->execute(array($user,$filename,$timestamp)); @@@ -154,13 -240,18 +240,18 @@@ * delete file from trash bin permanently * @param $filename path to the file * @param $timestamp of deletion time - * @return true/false + * @return size of deleted files */ public static function delete($filename, $timestamp=null) { - $user = \OCP\User::getUser(); -- $view = new \OC_FilesystemView('/'.$user); ++ $view = new \OC\Files\View('/'.$user); + $size = 0; + $trashbinSize = self::getTrashbinSize($user); + if ( $trashbinSize === false || $trashbinSize < 0 ) { - $trashbinSize = self::calculateSize(new \OC_FilesystemView('/'. $user.'/files_trashbin')); ++ $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)); @@@ -168,40 -259,91 +259,91 @@@ } else { $file = $filename; } - + if ( \OCP\App::isEnabled('files_versions') ) { - if ($view->is_dir('versions_trashbin/'.$file)) { - $view->unlink('versions_trashbin/'.$file); - } else if ( $versions = self::getVersionsFromTrash($file, $timestamp) ) { + if ($view->is_dir('files_trashbin/versions/'.$file)) { - $size += self::calculateSize(new \OC_Filesystemview('/'.$user.'/files_trashbin/versions/'.$file)); ++ $size += self::calculateSize(new \OC\Files\view('/'.$user.'/files_trashbin/versions/'.$file)); + $view->unlink('files_trashbin/versions/'.$file); + } else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) { foreach ($versions as $v) { if ($timestamp ) { - $view->unlink('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp); + $size += $view->filesize('/files_trashbin/versions/'.$filename.'.v'.$v.'.d'.$timestamp); + $view->unlink('/files_trashbin/versions/'.$filename.'.v'.$v.'.d'.$timestamp); } else { - $view->unlink('versions_trashbin/'.$file.'.v'.$v); + $size += $view->filesize('/files_trashbin/versions/'.$filename.'.v'.$v); + $view->unlink('/files_trashbin/versions/'.$filename.'.v'.$v); } } } } + + // Take care of encryption keys + $parts = pathinfo($file); + if ( $view->is_dir('/files_trashbin/files/'.$file) ) { - $keyfile = \OC_Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename); ++ $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename); + } else { - $keyfile = \OC_Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename.'.key'); ++ $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename.'.key'); + } + if ($timestamp) { + $keyfile .= '.d'.$timestamp; + } + if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile) ) { + if ( $view->is_dir($keyfile) ) { - $size += self::calculateSize(new \OC_FilesystemView('/'.$user.'/'.$keyfile)); ++ $size += self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile)); + } else { + $size += $view->filesize($keyfile); + } + $view->unlink($keyfile); + } - $view->unlink('/files_trashbin/'.$file); + if ($view->is_dir('/files_trashbin/files/'.$file)) { - $size += self::calculateSize(new \OC_Filesystemview('/'.$user.'/files_trashbin/files/'.$file)); ++ $size += self::calculateSize(new \OC\Files\View('/'.$user.'/files_trashbin/files/'.$file)); + } else { + $size += $view->filesize('/files_trashbin/files/'.$file); + } + $view->unlink('/files_trashbin/files/'.$file); + $trashbinSize -= $size; + self::setTrashbinSize($user, $trashbinSize); - return true; + return $size; } - - + + /** + * check to see whether a file exists in trashbin + * @param $filename path to the file + * @param $timestamp of deletion time + * @return true if file exists, otherwise false + */ + public static function file_exists($filename, $timestamp=null) { + $user = \OCP\User::getUser(); - $view = new \OC_FilesystemView('/'.$user); ++ $view = new \OC\Files\View('/'.$user); + + if ($timestamp) { + $filename = $filename.'.d'.$timestamp; + } else { + $filename = $filename; + } + - $target = \OC_Filesystem::normalizePath('files_trashbin/files/'.$filename); ++ $target = \OC\Files\Filesystem::normalizePath('files_trashbin/files/'.$filename); + return $view->file_exists($target); + } + /** * clean up the trash bin + * @param max. available disk space for trashbin */ - private static function expire() { - - $view = new \OC\Files\View('/'.\OCP\User::getUser()); + private static function expire($availableSpace) { + $user = \OCP\User::getUser(); - - $view = new \OC_FilesystemView('/'.$user); ++ $view = new \OC\Files\View('/'.$user); + $size = 0; + $query = \OC_DB::prepare('SELECT location,type,id,timestamp FROM *PREFIX*files_trash WHERE user=?'); $result = $query->execute(array($user))->fetchAll(); - - $retention_obligation = \OC_Config::getValue('trashbin_retention_obligation', self::DEFAULT_RETENTION_OBLIGATION); - + + $retention_obligation = \OC_Config::getValue('trashbin_retention_obligation', + self::DEFAULT_RETENTION_OBLIGATION); + $limit = time() - ($retention_obligation * 86400); foreach ( $result as $r ) { @@@ -247,20 -401,20 +401,20 @@@ $view->copy( 'files'.$source, $destination ); $view->touch($destination, $view->filemtime('files'.$source)); } + return $size; } - + /** * find all versions which belong to the file we want to restore - * @param string $filename name of the file which should be restored - * @param int $timestamp timestamp when the file was deleted + * @param $filename name of the file which should be restored + * @param $timestamp timestamp when the file was deleted */ private static function getVersionsFromTrash($filename, $timestamp) { - $view = new \OC\Files\View('/'.\OCP\User::getUser().'/versions_trashbin'); - $view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin/versions'); ++ $view = new \OC\Files\View('/'.\OCP\User::getUser().'/files_trashbin/versions'); $versionsName = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath($filename); $versions = array(); - if ($timestamp ) { - // fetch for old versions + // fetch for old versions $matches = glob( $versionsName.'.v*.d'.$timestamp ); $offset = -strlen($timestamp)-2; } else {